fix(release): keep the tag on main and push it atomically - #64
Merged
Conversation
Two releases were published from commits that are not on main. The tag is what triggers the release workflow, so the artifacts on npm and pub.dev were built from a tree nobody can see. v0.9.36 is the clearest case. PR #38 merged into origin/main on 04-14 02:47Z. On 04-15 06:48Z the release was cut from a stale local main still at v0.9.35, and `git push origin main --tags` pushed each ref independently: the branch was rejected as non-fast-forward, the tag went through anyway. CI started from that orphaned commit 5 seconds later. The `pull --rebase` that followed 31 seconds after replayed the same two commits onto origin/main — same author dates, later committer dates, identical patch-ids — leaving the tag on the pre-rebase copy. v0.9.24 failed the same way on 03-17. Reproduced the ref-splitting behaviour against a scratch remote. Before touching any file the script now requires that HEAD is main, that the tag does not already exist, and that main matches origin/main exactly, naming whether it is ahead or behind. Aborting this early matters because the version bumps run before the confirmation prompt. The push is now `--atomic` and names only this release's tag, so a rejected branch update can no longer let the tag through, and unrelated local tags are not swept along by `--tags`. On failure the local tag is deleted so a retry starts clean.
3 tasks
The generated entry carries a "TODO: Add your changes here" line and the warning to replace it only prints, so it is easy to walk past. Ten released versions have that literal string as their entire changelog, including the three most recent. Block on it instead. The check reads only the section for the version being released, so an older unfilled entry does not stop a new release.
Member
Author
|
Added a second guard to this PR while preparing the 0.9.37 release.
The script now refuses to proceed while the placeholder is still there. The check is scoped to the section for the version being released (awk stops at the next |
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.
Root cause of the "tag exists but no release / wrong contents" problem behind #57.
What went wrong
Two releases were published from commits that are not on
main—v0.9.24andv0.9.36. The tag is what triggersrelease.yml, so npm and pub.dev shipped a tree that exists nowhere in the branch history.v0.9.36is the clearest case:origin/main→376cdd7b#43fix committed on a stale local main, still atv0.9.35release.shcreateschore: Release v0.9.36(b73fd0c2) + tagb73fd0c2— the tag landed, the branch did notpull --rebasereplays both commits onto376cdd7b→2e6f6ba3+1ce1eccaEvidence that the last step was a rebase rather than two separate edits: the pairs share author dates to the second but have committer dates 36 s later, and
git patch-idis identical (41ffdbba…).gh run viewconfirms the release run'sheadShaisb73fd0c2, the orphaned commit.Why the tag landed but the branch didn't
git push origin main --tagsupdates each ref independently. Reproduced against a scratch remote:The remote is left holding a tag that is not on
main— exactly the production state.set -edoes not help: the tag is already delivered by the time the command reports failure.Consequence
Everything merged after the divergence never shipped: #38, #47, #51, #53, #55, #58, #59. #51 is the painful one — released
v0.9.36still haspackaging/npm/dart/bin/server.dartimportingpackage:flutter_skill/…while the vendored pubspec isname: flutter_skill_npm, so the Dart fallback cannot compile. That is the direct cause of the errors still open in #45, #49 and #50.Changes
Pre-flight, before any file is touched — the version bumps run before the confirmation prompt, so a late abort leaves a dirty tree:
mainmainmust matchorigin/mainexactly, reporting whether it is ahead or behind and what to do about itPush —
git push --atomic origin main "refs/tags/v$VERSION":--atomicmeans a rejected branch update can no longer let the tag through--tagssweeping up unrelated local tagsTest plan
! [rejected] v9.9.9 (atomic push failed), remote has no tag. The old form pushed the tag.Releases must be cut from main0.9.36) → abortsbehind: 6 commit(s) ahead: 0, aborts, suggestsgit pull --rebasebehind: 0 ahead: 1, aborts, suggestsgit push origin mainbash -n scripts/release.shNot exercised: a real end-to-end release, which needs a live tag push.
Follow-up
v0.9.36still points at the orphaned commit. Once the queued PRs merge, the nextrelease.shrun cuts0.9.37frommainand picks up all seven stranded PRs — worth spelling out in the CHANGELOG, since the change volume is far larger than the version bump suggests.🤖 Generated with Claude Code