Skip to content

ci(release): narrow release-bump exemption in the release gate (CR-245, G13) - #485

Closed
luisleo526 wants to merge 3 commits into
mainfrom
fu/cr245-release-bump-exemption
Closed

luisleo526 wants to merge 3 commits into
mainfrom
fu/cr245-release-bump-exemption

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

CR-245 (G13, L6: before the 1.7.0 rc). The #479 release gate (scripts/ci_release_gate.py) accepts main's head when it is a release-bump commit and all of these hold:
(a) every push-event workflow run of that sha on main has actor AND triggering_actor pineforge-app[bot], and there is at least one; AND the cumulative bypass of all ACTIVE branch rulesets on main that carry pull_request / required_status_checks is exactly {Integration 4105147, always}, read at gate time;
(b) it has a single parent that itself passes phase 1;
(c) it touches exactly VERSION and docker/run_failure_codes_diff.json (status M, mode unchanged).
Anything else refuses, including any API error, a missing bypass_actors, a disabled ruleset, malformed pages or zero runs. The gate relies on the App permission administration: read, which is named in release.yml, docs/ci.md and the preflight pins. Red tests through gate() for every case, 13 source mutation controls and 5 preflight workflow mutations. Two commits (rounds 1+2). Reads: fresh sol + argon, then a Fable read (release gate); L6 lands.

🤖 Generated with Claude Code

luisleo526 and others added 3 commits October 24, 2026 07:06
…p pushed it (CR-245, round 1)

The release workflow pushes a version-bump commit to main; no PR head has that tree, so the next
release run refused at phase 1. The gate now also accepts main's head when it is a bump commit that
(a) every push-event run of the sha on main records as pushed by the release App
(actor and triggering_actor both pineforge-app[bot], at least one run, all pages read, a run by any
other actor refuses), (b) has a single parent that itself passes phase 1 (a bump on a bump or a merge
commit refuses), and (c) touches exactly the files the workflow writes and stages, VERSION and
docker/run_failure_codes_diff.json, as modifications with unchanged mode 100644 and nothing else.
Red-first tests through gate() with the injected API for the accepted path and each refusal, a mutation
control per condition, preflight pins and docs. Commit metadata is not used for identity: it is
forgeable. Round 2 adds the branch-ruleset check that makes the App the only possible pusher.

Lane: ci-fu-cr245b (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
…pp can push to main (CR-245, round 2)

The actor check of round 1 is only as strong as the guarantee that nobody else can produce a push
run as the release App. The gate now reads the repository's branch rulesets at gate time and
requires that the cumulative bypass of every ACTIVE ruleset that applies to main and carries a
pull_request or required_status_checks rule is exactly the release App (Integration 4105147, bypass
mode always). It refuses when no push-blocking ruleset applies to main, when one is disabled or
evaluate-only, when another actor or a pull-request-only bypass appears, when bypass_actors is not
returned, when an inventory or detail response is malformed or incomplete (every page is read and
linked), when an applicable ref pattern is not understood, and on any API error. No ruleset id or name
is hard-coded. The gate relies on the App installation permission `administration: read`; release.yml,
docs/ci.md and the preflight pins say so, so removing the permission is a visible breaking change.
Nineteen ruleset tests and thirteen source mutation controls; preflight workflow mutations for the
gate token wiring. Rounds 1 and 2 land together.

Lane: ci-fu-cr245c (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
…ricted to the release App; Actions pagination honours Link (CR-245, round 3)

Fresh sol read of the round-2 head: intersecting bypass descriptors across rulesets does not prove an
App-only barrier (a person who holds a role and a team bypasses two rulesets whose lists share only the
App entry), and a required_status_checks rule alone is not a push barrier. The condition is now: at least
one ACTIVE branch ruleset applies to main, carries a pull_request rule, and its OWN bypass list is exactly
the release App (Integration 4105147, bypass mode always); other rulesets, such as the broad default one,
no longer matter. required_status_checks no longer counts. The Actions workflow-runs reader also proves
completeness with the Link header (an advertised unread next page refuses), as the rulesets reader
already did. The round-2 tests that encoded the intersection and the status-only acceptance are
rewritten (status-only now refuses) and new red rows cover overlapping role/team principals, a hybrid
PR/status pair, a valid barrier beside broader rulesets, a second bypass actor, a non-always mode and
the unread-page input; docs, preflight pins and the release.yml comment follow the new wording.

Lane: ci-fu-cr245d (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
@luisleo526

Copy link
Copy Markdown
Collaborator Author

Superseded by #486 (same series plus round 3 on a new branch; no force-push).

@luisleo526 luisleo526 closed this Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant