release: prepare v2.0.0 - #106
Merged
Merged
Conversation
MCamner
added a commit
that referenced
this pull request
Jul 29, 2026
* fix(release): obey release_mode instead of pushing main .mq/repo-contract.json declares release_mode: pull_request, but release.sh committed the version bump on main, tagged it, and ran `git push origin main`. main has no branch protection on GitHub, so nothing outside the contract would have refused that push. v2.0.0 was released through PR #106 plus a hand-made tag on the merge commit — the script was the only part of the flow that disagreed with how releases are actually cut here. The mode is read from the contract, not from a flag. A flag would have left `./release.sh <version>` working as a direct-push path in a repo whose contract forbids one, which is the bug rather than a fix for it. pull_request: bump on release/v<version>, push the branch, open the PR via gh when present (warn-only — the branch is already safe on origin by then), return the checkout to main, create no tag. Tagging is printed as a post-merge step because the tag belongs on the merge commit, and the wiki Command-Reference and GitHub Release move with it: until the merge lands, main does not carry the version they would document. direct: unchanged, and still reachable only when the contract asks for it. The error trap now also restores the base branch. `git branch -d` refuses unmerged work, so a branch already holding the release commit survives a failure rather than taking the commit with it. `git checkout main` in the sync step loses its `|| true`: a swallowed failure used to mean bumping whatever branch was out, and would now mean branching the release off it. tests/release-pull-request-mode-smoke.sh asserts origin's ref state against a real bare repo, not a stub's command log — a push nobody logged can fool a stub, but not a ref. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(release): run the rollback the gates always skipped Driving the real flow found it: `./release.sh --dry-run 2.0.1` against this repo's own contract failed the CHANGELOG gate and left VERSION, README.md and .mq/repo-contract.json bumped on disk, with no "Rolled back" line and no "Release command failed" line — the trap had not run at all. Bash does not run an ERR trap for an explicit `exit`, and every gate here exits rather than failing a command. So the rollback the usage text promises has never covered the gates: not the CHANGELOG check, not the contract re-gate, not the tag checks. Only a command that failed on its own reached it. That is a pre-existing hole, but it stops being only pre-existing once the release runs on a branch: a gate tripping after the branch is cut would strand the checkout on it. So the EXIT trap lands with the mode change rather than after it. Cleanup is guarded on a mutation flag rather than running unconditionally. Before the first bump the tree still holds whatever the operator had, and `git checkout --` there would discard their work instead of restoring ours — an unknown flag must not clean the tree. Test [5/5] cuts a release for a version with no CHANGELOG section and asserts the tree is clean, the release branch is gone, and the checkout is back on main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(changelog): record the release rollback fix Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.
The version bump
release.shproduced. Opened as a PR because the repository rule onmainrequires one.Three files, three lines. Generated by
./release.sh 2.0.0, not by hand.What happened
release.shstep 13 pushesmainand the tag together. That push was rejected:Nothing reached origin — no commit, no tag. The local tag was deleted rather than kept, because a squash merge gives this content a new SHA and the tag would have pointed at a commit that never lands on
main.Release state
Everything else the release needs is already in place and was verified on
mainbefore the attempt:release.shalso re-gates after the bump that.mq/repo-contract.jsonmatchesVERSION, which it does — that check passed before the push was attempted.After merge
Tag the merged commit and push only the tag:
The GitHub Release stays a separate deliberate step after the tag is verified.
Follow-up worth filing
release.shcannot complete on this repository as written — steps 11–13 assume a direct push tomainthat the branch rule forbids. It should either push the tag only and leave the commit to a PR, or grow a mode that does. Not fixed here; a release PR is not the place to change the release script.🤖 Generated with Claude Code