require_code_owner_reviews + count=1 with no bypass meant EVERY PR needed a
code-owner approval — including code owners' own PRs, which can't be
self-approved, so an owner's PR deadlocked on the other owner (forcing admin
overrides). Intended behavior: review is required only for non-owners.
Add bypass_pull_request_allowances for the two engineering owners (ragnorc,
aaltshuler): they merge their own PRs after CI without a second review;
non-owners still require a code-owner approval. CI status checks remain
required for everyone. Applied live via scripts/apply-branch-protection.sh.
Note: the bypass list mirrors codeowners-roles.yml engineering members by hand
(render-codeowners.py doesn't generate it) — keep in sync on owner changes.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The CODEOWNERS required checks blocked every PR — the real root cause was a
name mismatch, compounded by a path filter:
- branch-protection.json required the contexts `CODEOWNERS / drift` and
`CODEOWNERS / noedit` (the GitHub UI "workflow / job-id" display form), but
the jobs report check-run names from their `name:` fields — "CODEOWNERS
matches source" / "CODEOWNERS not hand-edited". The required contexts
therefore never matched any reported check and sat permanently pending.
- The workflow was also path-filtered to CODEOWNERS files, so it didn't even
run for most PRs.
Net effect: with both required checks unsatisfiable, every PR could only land
via admin override (e.g. #140).
Fixes:
- A: drop the `paths:` filter so the workflow runs on every PR and both
required contexts always report.
- name fix: point branch-protection.json at the actual job names verbatim, and
add a doc note that the contexts must equal the job `name:` values.
- B: the `drift` job now re-renders and, on same-repo PRs, auto-commits the
regenerated artifacts back to the branch (mirrors the openapi.json job in
ci.yml); forks / manual runs strict-check instead. Contributors no longer
run the script by hand.
- D: render-codeowners.py also generates a "who owns what" path->owners +
roles table spliced into docs/dev/codeowners.md between markers, so the
human-readable view never drifts. Idempotent; CODEOWNERS output unchanged.
- docs: correct the stale `enforce_admins: true` line (JSON and live are
false).
NOTE: the branch-protection.json change only takes effect after an admin runs
`./scripts/apply-branch-protection.sh` (deliberate manual step, per
docs/dev/branch-protection.md). Until then `main` still requires the old
mismatched contexts, so this PR itself needs an admin-override merge — the last
one that should be necessary.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Flip enforce_admins from true to false. Repo admins can now merge
their own PRs without waiting for code-owner review, by clicking
"Merge without waiting for requirements to be met" once CI is green.
The action is recorded in the audit log.
Non-admins still see full enforcement: code-owner review required,
1 approving review, required status checks must pass.
Rationale: as the solo owner of most CODEOWNERS scopes, the author
cannot satisfy GitHub's "non-self approver" rule on their own PRs,
which made every PR block on a second human. Admin bypass restores
the practical workflow while keeping the protection rules as the
default for everyone else.
Branch protection on main, declared as code rather than as opaque
GitHub UI state. Pairs with the CODEOWNERS chassis (#88): once this
PR lands and an admin runs the apply script, every PR to main must
satisfy code-owner review and the listed required checks.
Components:
- .github/branch-protection.json — the policy. Edit this to change
required checks, review counts, etc. Includes a _comment field for
human readers; the apply script strips it before PUT.
- scripts/apply-branch-protection.sh — idempotent apply via `gh api`.
Reads back current state for verification. Supports DRY_RUN=1.
- docs/branch-protection.md — explains the policy, how to apply, how
to change, why declared as code.
- AGENTS.md topic-index row.
Policy summary:
- Required status checks (strict): Classify Changes, Check AGENTS.md
Links, Test Workspace, Test omnigraph-server --features aws,
CODEOWNERS / drift, CODEOWNERS / noedit.
- Required approving reviews: 1, must be a code owner.
- Dismiss stale reviews on new commits.
- Required linear history (squash or rebase merges only).
- No force pushes, no deletions, no admin bypasses.
- Required conversation resolution.
What's NOT in this PR:
- Required signed commits — not yet; maintainers must enroll GPG/SSH
signing first or merges will block.
- Tag protection for v* tags — separate PR.
- Additional required checks (cargo deny, audit, fmt, clippy, CodeQL,
schema-lint MR-946) — separate PRs as each lands.
- The script is NOT run by CI. Branch-protection changes are admin
actions; CI-driven auto-apply would defeat the purpose. Manual
invocation is the audit point.
How to apply after merge:
./scripts/apply-branch-protection.sh
Requires gh-CLI auth with repo-admin permissions.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>