fix(release): pin build dispatch to the tag, fix release-branch naming - #90
Merged
Merged
Conversation
Contributor
📝 WalkthroughWalkthroughRelease workflows now create or reuse frozen prerelease branches, tag RCs from the target release branch, and dispatch ChangesRelease workflow snapshot handling
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
prerelease.yml triggered build.yml without --ref, so the build ran on the
default branch (main), where package.json is still the previous stable
version. The RC version bump lives only on the release branch / RC tag, so
build.yml's publish-release guard rejected it ("package.json version 1.6.0
does not match 1.7.0-rc.1 from tag v1.7.0-rc.1") and no release was created.
Pass --ref so the build checks out the tag's tree (bumped package.json +
frozen code). Apply the same pin in promote.yml for the stable build, which
previously only worked because the main-merge happened to leave main at the
stable version first.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ross RCs
prerelease.yml created release/v${PRERELEASE} (e.g. release/v1.7.0-rc.1) but
promote.yml resolves release/v${STABLE_VERSION} (release/v1.7.0), so promote
would die at `git fetch origin release/v1.7.0`. v1.7.0-rc.1 is the first RC cut
under the release-branch freeze, so this path had never run.
Worse, each re-cut created a *new* branch off main and force-deleted the remote
branch first, so cutting rc.2 would both sweep in whatever had landed on main
and destroy the cherry-picks on the rc.1 branch. That silently defeats the
freeze the contract is supposed to guarantee.
Use one branch per stable version (release/vX.Y.Z), created at rc.1 and reused
for later RCs: fetch and check it out when it exists, branch from the dispatched
ref when it doesn't, and never delete it. Fold the package.json bump into the
same step so the version is written after the correct branch is checked out.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
EtienneLescot
force-pushed
the
claude/prerelease-version-tag-ee96ae
branch
from
July 16, 2026 15:13
02759fc to
1d6a8a1
Compare
4 tasks
EtienneLescot
added a commit
that referenced
this pull request
Aug 11, 2026
The manual fallback was the only real defect. It bumped `package.json` with a `sed` while `set-release-version.mjs` — which prerelease.yml and promote.yml both call — also writes `package-lock.json`. A fallback release cut by hand therefore shipped a lockfile disagreeing with the package it locks, the exact drift that script was written to stop. It now calls the script, and hoists the RC version into `$RC` so rc.2+ does not need three edits kept in sync. Also: "promote.yml is the only writer" now says *automated* writer, so it stops contradicting the manual fallback three sections below; the cherry-pick rule points at `git log release/vX.Y.Z..main` for seeing what is not in the RC; the product constraint distinguishes gating on readiness from gating on the user, so an unfinished capture backend can still hide behind a flag; and `.harness/memory/MEMORY.md` no longer describes the pre-#90 `release/vX.Y.Z-rc.N` naming.
EtienneLescot
added a commit
that referenced
this pull request
Aug 11, 2026
`.harness/docs/git-workflow.md` and `technical-documentation/engineering/release-and-secrets.md` both documented the release flow, and only one of them was ever checked. `check-docs.mjs` walks `technical-documentation/` alone, so when #90 changed the release-branch naming the docs tree was corrected and the harness copy was not — it kept sending readers to `release/vX.Y.Z-rc.N`, a branch the workflows never create, for a month. `.harness/memory/MEMORY.md` repeated it. Both files already declared non-overlapping scopes: git-workflow.md is "conventions for the Mavis reins", release-and-secrets.md is "the operational reference for cutting releases", and the latter already delegated branching and PR procedure back. The release flow sitting in git-workflow.md violated that split. So: move, then collapse. Moved into release-and-secrets.md, none of it duplicated there before — why the build dispatch is pinned to the tag (GITHUB_TOKEN does not fire `push:`, and the build must check out the tag or fail the version guard), the numbered branch contract including "never delete or recreate", the v1.6.0 postmortem with what actually shipped, the runnable manual fallback, backports, and milestone handling. git-workflow.md §Release flow is now four lines and a pointer: 154 lines to 48, in a file loaded into every agent run. The fallback there also still said to prepare "the correct `package.json` commit" — the same lockfile trap the harness copy had, in the file operators actually read. It now points at set-release-version.mjs and says why. Root cause last: `check-docs.mjs` walks `.harness/` too, and the retired branch naming is a LEGACY identifier, so CI fails on any doc reintroducing it. `.harness/` passes all three existing passes today, so this adds a gate without a migration. The new test asserts the script *rejects* a planted violation, because a checker that silently stops checking still prints OK — which is how this rotted unnoticed in the first place.
EtienneLescot
added a commit
that referenced
this pull request
Aug 11, 2026
`.harness/docs/git-workflow.md` and `technical-documentation/engineering/release-and-secrets.md` both documented the release flow, and only one of them was ever checked. `check-docs.mjs` walks `technical-documentation/` alone, so when #90 changed the release-branch naming the docs tree was corrected and the harness copy was not — it kept sending readers to `release/vX.Y.Z-rc.N`, a branch the workflows never create, for a month. `.harness/memory/MEMORY.md` repeated it. Both files already declared non-overlapping scopes: git-workflow.md is "conventions for the Mavis reins", release-and-secrets.md is "the operational reference for cutting releases", and the latter already delegated branching and PR procedure back. The release flow sitting in git-workflow.md violated that split. So: move, then collapse. Moved into release-and-secrets.md, none of it duplicated there before — why the build dispatch is explicit and pinned to the tag, the numbered branch contract including "never delete or recreate", the v1.6.0 postmortem with what actually shipped, the runnable manual fallback, backports, and milestone handling. git-workflow.md §Release flow is now four lines and a pointer: 154 lines to 48, in a file loaded into every agent run. The dispatch rationale is documented per workflow rather than in general, because the two do not push their tags the same way: promote.yml uses GITHUB_TOKEN, whose tag push does not fire build.yml's `push:` trigger, while prerelease.yml uses the PAT because a GITHUB_TOKEN tag push is answered with a 500 from a tag ruleset — the failure that took down the v1.8.0-rc.1 cut. Only the `--ref` pinning is required in both cases, for the publish version guard. The fallback there also still said to prepare "the correct `package.json` commit" — the same lockfile trap the harness copy had, in the file operators actually read. It now points at set-release-version.mjs and says why. Root cause last: `check-docs.mjs` walks `.harness/` too, and the retired branch naming is a LEGACY identifier, so CI fails on any doc reintroducing it. `.harness/` passes all three existing passes today, so this adds a gate without a migration. The new test asserts the script *rejects* a planted violation, because a checker that silently stops checking still prints OK — which is how this rotted unnoticed in the first place.
EtienneLescot
added a commit
that referenced
this pull request
Aug 12, 2026
The manual fallback was the only real defect. It bumped `package.json` with a `sed` while `set-release-version.mjs` — which prerelease.yml and promote.yml both call — also writes `package-lock.json`. A fallback release cut by hand therefore shipped a lockfile disagreeing with the package it locks, the exact drift that script was written to stop. It now calls the script, and hoists the RC version into `$RC` so rc.2+ does not need three edits kept in sync. Also: "promote.yml is the only writer" now says *automated* writer, so it stops contradicting the manual fallback three sections below; the cherry-pick rule points at `git log release/vX.Y.Z..main` for seeing what is not in the RC; the product constraint distinguishes gating on readiness from gating on the user, so an unfinished capture backend can still hide behind a flag; and `.harness/memory/MEMORY.md` no longer describes the pre-#90 `release/vX.Y.Z-rc.N` naming.
EtienneLescot
added a commit
that referenced
this pull request
Aug 12, 2026
`.harness/docs/git-workflow.md` and `technical-documentation/engineering/release-and-secrets.md` both documented the release flow, and only one of them was ever checked. `check-docs.mjs` walks `technical-documentation/` alone, so when #90 changed the release-branch naming the docs tree was corrected and the harness copy was not — it kept sending readers to `release/vX.Y.Z-rc.N`, a branch the workflows never create, for a month. `.harness/memory/MEMORY.md` repeated it. Both files already declared non-overlapping scopes: git-workflow.md is "conventions for the Mavis reins", release-and-secrets.md is "the operational reference for cutting releases", and the latter already delegated branching and PR procedure back. The release flow sitting in git-workflow.md violated that split. So: move, then collapse. Moved into release-and-secrets.md, none of it duplicated there before — why the build dispatch is explicit and pinned to the tag, the numbered branch contract including "never delete or recreate", the v1.6.0 postmortem with what actually shipped, the runnable manual fallback, backports, and milestone handling. git-workflow.md §Release flow is now four lines and a pointer: 154 lines to 48, in a file loaded into every agent run. The dispatch rationale is documented per workflow rather than in general, because the two do not push their tags the same way: promote.yml uses GITHUB_TOKEN, whose tag push does not fire build.yml's `push:` trigger, while prerelease.yml uses the PAT because a GITHUB_TOKEN tag push is answered with a 500 from a tag ruleset — the failure that took down the v1.8.0-rc.1 cut. Only the `--ref` pinning is required in both cases, for the publish version guard. The fallback there also still said to prepare "the correct `package.json` commit" — the same lockfile trap the harness copy had, in the file operators actually read. It now points at set-release-version.mjs and says why. Root cause last: `check-docs.mjs` walks `.harness/` too, and the retired branch naming is a LEGACY identifier, so CI fails on any doc reintroducing it. `.harness/` passes all three existing passes today, so this adds a gate without a migration. The new test asserts the script *rejects* a planted violation, because a checker that silently stops checking still prints OK — which is how this rotted unnoticed in the first place.
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.
Two bugs in the release pipeline, both found while cutting v1.7.0-rc.1 (the first RC under the release-branch freeze, so neither path had ever run).
1. Build dispatched on the wrong ref
prerelease.ymlrangh workflow run build.ymlwithout--ref, so the build dispatched on the default branch (main), wherepackage.jsonis still the previous stable version. The RC bump lives only on the release branch, sobuild.yml's publish guard rejected it:No release was created, and the installers were stamped
1.6.0. Fixed by pinning--ref "${RC_TAG}"(and--ref "${STABLE_TAG}"inpromote.yml, which only worked before because the preceding main-merge happened to leavemainat the stable version).2. Release branch naming breaks promote and defeats the freeze
prerelease.ymlcreatedrelease/v${PRERELEASE}→release/v1.7.0-rc.1promote.ymlresolvesrelease/v${STABLE_VERSION}→release/v1.7.0That branch doesn't exist, so promote would have failed at
git fetch origin release/v1.7.0.Worse: each re-cut created a new branch off
mainand force-deleted the remote branch first. Cutting rc.2 would therefore sweep in anything landed onmainand destroy the cherry-picks on the rc.1 branch — silently defeating the freeze the contract exists to guarantee.Fixed by using one branch per stable version (
release/vX.Y.Z), created at rc.1 and reused for later RCs: fetch + check out when it exists, branch from the dispatched ref when it doesn't, never delete. Thepackage.jsonbump moved into the same step so the version is written after the correct branch is checked out.Verification
build.yml --ref v1.7.0-rc.1(equivalent of fix 1) ran green on Windows/macOS(arm64+x64)/Linux and publishedv1.7.0-rc.1with 6 assets.release/v1.7.0and let promote resolve it.🤖 Generated with Claude Code
Summary by CodeRabbit