Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 13 additions & 14 deletions .github/workflows/merge-bot-pull-request.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
name: Merge bot pull request action

# Enable auto-merge once per PR on opened/reopened; disable it when a maintainer pushes to a bot branch. Merge
# method by base branch (develop = squash, main = merge). App token so the merge fires downstream workflows
# (GITHUB_TOKEN pushes don't) and so the disable job has write access on read-only Dependabot PRs.

# `pull_request_target` (not `pull_request`): these jobs hold the App private key, so the workflow definition and
# its action SHAs must resolve from the trusted base branch, not the PR head. Safe because no job checks out PR
# code - each only runs `gh pr merge` against the PR by URL.
# Auto-merges in-repo Dependabot PRs: enable on opened/reopened, disable on a maintainer push. Carried from the
# fleet reference trimmed to the Dependabot jobs - no codegen bot opens PRs against this repo.
# - Merge method by base: develop = squash, main = merge.
# - App token, not GITHUB_TOKEN: fires downstream workflows on merge, and grants write on read-only Dependabot PRs.
# - pull_request_target, not pull_request: jobs hold the App key, so the workflow + action SHAs resolve from the
# trusted base, not PR head. Safe because no job checks out PR code (each runs gh pr merge by URL).
on:
pull_request_target:
types: [opened, reopened, synchronize]

# Per-PR group: under `pull_request_target` `github.ref` is the base branch, which would serialize every bot PR
# against that base; key on the PR number so each PR's events queue independently. `cancel-in-progress: false` so a
# follow-up synchronize doesn't cancel an in-flight `opened` run before it enables auto-merge.
# Concurrency keys on the PR number, not github.ref (the base branch under pull_request_target, which would
# serialize every bot PR against it), so each PR queues independently. cancel-in-progress: false so a follow-up
# synchronize doesn't cancel an in-flight opened run before it enables auto-merge.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: false
Expand All @@ -23,8 +22,7 @@ jobs:
merge-dependabot:
name: Merge dependabot pull request job
runs-on: ubuntu-latest
# In-repo Dependabot PRs only, on opened/reopened so the disable job stays sticky. Every tier
# auto-merges, semver-major included: the required checks are the gate, not the version bump.
# Dependabot PRs from this repo (not forks). Only on opened/reopened so the disable job stays sticky.
if: >-
(github.event.action == 'opened' || github.event.action == 'reopened') &&
github.event.pull_request.user.login == 'dependabot[bot]' &&
Expand All @@ -42,6 +40,7 @@ jobs:
client-id: ${{ secrets.CODEGEN_APP_CLIENT_ID }}
private-key: ${{ secrets.CODEGEN_APP_PRIVATE_KEY }}

# Auto-merge every tier, semver-major included: the required checks are the gate, not the bump magnitude.
- name: Merge pull request step
run: |
set -euo pipefail
Expand All @@ -53,7 +52,7 @@ jobs:
exit 1
;;
esac
gh pr merge --auto --delete-branch "$method" "$PR_URL"
gh pr merge --auto "$method" "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
Expand All @@ -62,7 +61,7 @@ jobs:
name: Disable auto-merge on maintainer push job
runs-on: ubuntu-latest
# Fires when a maintainer pushes to a bot's branch (synchronize, actor != bot). Disables auto-merge so the
# maintainer's commits don't merge with the bot's; they re-enable it manually. The disable call is idempotent.
# maintainer's commits don't merge with the bot's, and they re-enable it manually. The disable call is idempotent.
if: >-
github.event.action == 'synchronize' &&
github.event.pull_request.head.repo.full_name == github.repository &&
Expand Down
73 changes: 73 additions & 0 deletions AUDIT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# AUDIT.md

How this repository audits itself against its committed baseline and reports drift. This is the repo-scoped adaptation of the fleet-wide AUDIT.md kept at the fleet hub (carried per the [repo-config downstream carry][repo-config-readme]); the hub's fleet-wide audit remains authoritative. The ground truth here is the committed [`repo-config/`][repo-config] payloads and [`spec/secrets.json`][secrets]; the prose authorities are [`AGENTS.md`][agents], [`CODESTYLE.md`][codestyle], and [`WORKFLOW.md`][workflow].

The audit is read-only: it diffs live state against the committed baseline and reports findings; it never applies changes. The verdict vocabulary is [`WORKFLOW.md`][workflow]'s: **operational / not operational**, **N/A**, **defect**, and the applicable/absent rule.

## Scope

This is a release-model repo: the self-audit covers the `main` and `develop` rulesets, general repository settings, and secret names. Code-project conformance (analyzers, tests, coverage, publish workflows) is CI's job and the fleet hub's fleet-wide audit's, not this self-audit's - see [AGENTS.md "Branching Model"][agents-branching-model] for the model this baseline encodes.

## General Settings

Diff the live repository settings against [`repo-config/settings.json`][repo-config-settings]. The two state-dependent settings are not in the file: `has_discussions` follows visibility (public on / private off) and `default_branch` is `main`.

```sh
repo="$(gh repo view --json nameWithOwner --jq '.nameWithOwner')"
live=$(gh api "repos/$repo" --jq '{has_wiki,has_projects,allow_merge_commit,allow_squash_merge,allow_rebase_merge,allow_auto_merge,allow_update_branch,delete_branch_on_merge}')
diff <(jq -S . repo-config/settings.json) <(jq -S . <<<"$live") \
&& echo "settings: in sync" || echo "settings: DRIFT"
```

## Rulesets

Diff each live ruleset against the committed expected payload with a normalized comparison (sort the order-insensitive `rules[]` and `bypass_actors[]` before diffing so a reordered but equivalent ruleset does not read as drift). This release carry keeps its `develop` payload at [`repo-config/develop.json`][repo-config-develop].

```sh
repo="$(gh repo view --json nameWithOwner --jq '.nameWithOwner')"
norm='{name,target,enforcement,bypass_actors,conditions,rules} | .rules|=sort_by(.type) | .bypass_actors|=sort_by(.actor_id)'
for b in develop main; do
file="repo-config/$b.json"
id=$(gh api "repos/$repo/rulesets" --jq ".[]|select(.name==\"$b\").id")
diff <(jq -S "$norm" "$file") \
<(gh api "repos/$repo/rulesets/$id" --jq '{name,target,enforcement,bypass_actors,conditions,rules}' | jq -S "$norm") \
&& echo "$b: in sync" || echo "$b: DRIFT"
done
```

The result must be exactly two rulesets named `develop` and `main` - a missing ruleset or a divergent payload is a **defect**; a duplicate or stray ruleset is a **drift finding**.

## Secrets

Confirm each name [`spec/secrets.json`][secrets] requires exists in the stores its mechanism claims, and no forbidden name is present (names only; values are not readable). The baseline App pair and the Docker Hub pair live in both the Actions and Dependabot stores; `CODECOV_TOKEN` is claimed in the Actions store.

```sh
repo="$(gh repo view --json nameWithOwner --jq '.nameWithOwner')"
for store in actions dependabot; do
names=$(gh api "repos/$repo/$store/secrets" --jq '.secrets[].name')
want="CODEGEN_APP_CLIENT_ID CODEGEN_APP_PRIVATE_KEY DOCKER_HUB_USERNAME DOCKER_HUB_ACCESS_TOKEN"
[ "$store" = "actions" ] && want="$want CODECOV_TOKEN"
for s in $want; do
grep -qx "$s" <<<"$names" && echo "$store/$s: present" || echo "$store/$s: MISSING (defect)"
done
Comment thread
ptr727 marked this conversation as resolved.
for s in CODEGEN_APP_ID; do
grep -qx "$s" <<<"$names" && echo "$store/$s: forbidden name present (defect)" || true
done
done
```

## Verdict and Follow-Up

A missing required item or a divergent payload is a **defect** (not operational); an equivalent outcome in a non-standard form is a **drift finding**. N/A items are excluded, never counted as failures. Surface findings as repository issues; fixes land as a pull request to `develop` per [AGENTS.md "Branching Model"][agents-branching-model]. To re-apply the whole baseline, run `repo-config/configure.sh` (see [repo-config/README.md][repo-config-readme]).

<!-- Repo -->

[agents]: ./AGENTS.md
[agents-branching-model]: ./AGENTS.md#branching-model
[codestyle]: ./CODESTYLE.md
[repo-config]: ./repo-config/
[repo-config-develop]: ./repo-config/develop.json
[repo-config-readme]: ./repo-config/README.md
[repo-config-settings]: ./repo-config/settings.json
[secrets]: ./spec/secrets.json
[workflow]: ./WORKFLOW.md
Loading