ci: fast-forward bump PRs as the release app instead of waiting for a human merge - #266
Merged
Merged
Conversation
… human merge The require-review ruleset lists the release app as a bypass actor, but GitHub only honours app bypass on direct ref updates, never on the merge API or auto-merge. The bump script therefore polled 1800s for a human to merge and then died with the tag stranded. The script now waits for the PR's checks, verifies the live target tip is still the SHA the bump was built on, fast-forwards the target ref without force, verifies GitHub reports the PR merged, and only then tags. Co-Authored-By: Larry Osakwe <larry@keycard.ai>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
An unregistered check rollup reads as pending, never passing, and the stable-wait re-arms after every bump-branch rebuild, so a fresh commit cannot merge before Actions reports on it. A PR merged by hand mid-wait is adopted and tagged at its merge commit. A stale bump branch or open bump PR from a failed run is reused, and the branch is deleted after the tag. A refused fast-forward re-probes the live tip and rebuilds within the round budget, and a rebuild refuses when the target changed any file under the package directory. Failed-check aborts name the blocking check.
Larry-Osakwe
approved these changes
Sep 2, 2026
Larry-Osakwe
left a comment
Contributor
There was a problem hiding this comment.
Reviewed as release infrastructure: the checks gate fails closed on empty rollups, the fast-forward is strict with the non-force PATCH as the TOCTOU backstop, the tag is unreachable without a verified merge, and all four lived failure modes (5am hands-off, human merge mid-wait, failed checks, moved main) end clean. Five mutation checks caught, 42 script tests green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scripts/bump_package.pyopened the bump PR, armed auto-merge, asked for a squash merge, then polled up to 1800s for the PR to merge and died with the tag stranded. The require-review ruleset lists the release app as a bypass actor, but GitHub only honours app bypass on direct ref updates, never on the merge API or auto-merge, so neither path could ever land the PR without a human. Two manual tag recoveries this week.The app-performed direct ref update is now the primary, deliberate merge path, sequenced so the incident-class protections from #253 stay intact (tag only after a verified merge, scoped bump detection and
NO_COMMITS_FOUNDhandling untouched,recover_untagged_bumpstill covers a run that dies between merge and tag):checks_verdictreplaceschecks_green: FAILURE beats PENDING, so one red check aborts even while others still run; pending never passes. The fast-forward log line states the ref update was performed by the release app under its ruleset bypass, so an auditor understands why no review appears on the PR.Auto-merge arming was dropped: with the app doing the merge it only adds a race where a squash merge could land first and turn the fast-forward into a spurious non-FF refusal.
.github/workflows/bump-package.ymlis unchanged. The app installation token already needs contents write (it creates tag refs and the bump branch today) and pull-requests write; the fast-forward is anotherrefswrite under the same permission, so no additional permission is required.Tests (
python3 -m unittest discover -s scripts -p 'test_*.py', 28 pass with commitizen installed): strict-FF guard refuses when the target moved and never touches the refs API; the FF PATCH carries noforce; rebuild refuses when the target changed bumped files; tag is unreachable whenverify_pr_mergedreturns None; checks gate refuses on FAILURE and times out on PENDING without opening the merge path.Link to Devin session: https://app.devin.ai/sessions/52b1004809294cdaa25c036b6c644e7f
Open in Devin Desktop: https://app.devin.ai/desktop/session/52b1004809294cdaa25c036b6c644e7f?variant=devin
Requested by: @Larry-Osakwe