chore(release): decouple CHANGELOG/tagging from starting a build - #166
Merged
Conversation
`just release <semver>` bumped the version, generated the CHANGELOG entry, tagged, and started the Xcode Cloud build all in one step — but App Store review can reject or delay a build for days, during which main keeps moving. The tag and changelog range ended up pinned to whatever HEAD happened to be at release time, not to what actually shipped. `release` now only bumps the version and starts a build. A new `tag-release <semver>` records the changelog entry and tag, meant to run after App Store Connect confirms the version is actually live. It resolves the shipped commit via Xcode Cloud's own build-run records (matching the App Store version's attached-build number, via `asc versions view --include-build`) rather than trusting app/pubspec.yaml's build number — build-run history shows Xcode Cloud assigns CFBundleVersion from its own counter, which doesn't reliably match what was last bumped in pubspec. Also fixes ci_post_clone.sh's comment, which asserted the opposite. Also restores CLAUDE.md's release docs, which claimed TestFlight-only iteration works indefinitely on one marketing version — disproven this session: Apple closes a version's pre-release train entirely once it ships (ITMS-90186 + ITMS-90062), TestFlight included. Co-Authored-By: Claude Sonnet 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.
Summary
just release <semver>used to bump the version, generate the CHANGELOG entry, tag, and start an Xcode Cloud build all in one step. But App Store review can reject or delay a build for days, during whichmainkeeps moving — the tag and changelog range ended up pinned to whateverHEADhappened to be at release time, not to what actually shipped.releasenow only bumpsapp/pubspec.yamland starts a build; it no longer touchesCHANGELOG.mdor tags.just tag-release <semver>records the changelog entry and git tag, meant to run once App Store Connect confirms the version is actually live (READY_FOR_DISTRIBUTION).tag-releaseresolves the commit that actually shipped via Xcode Cloud's own build-run records — matching the App Store version's attached build (asc versions view --include-build), not just the newest upload under that marketing version, since those can differ if a build-onlyjust releaseruns again after submission. It does not trustapp/pubspec.yaml's build number for this: build-run history shows Xcode Cloud assignsCFBundleVersionfrom its own run counter, which doesn't reliably match what was last bumped in pubspec (run 48 and run 49 both built the identical commit and produced two different ASC build numbers).ci_post_clone.sh's comment, which asserted the opposite (that CFBundleVersion comes straight from pubspec) — that assertion predated this finding and is now corrected.CLAUDE.md's release docs, which claimed TestFlight-only iteration works indefinitely on one marketing version. Disproven this session: once a version actually ships, Apple closes its pre-release train entirely (ITMS-90186"Invalid Pre-Release Train" +ITMS-90062), TestFlight included — a real build attempt against the already-shipped 1.0.0 failed with exactly this.tag-release: version-state gate, tag-already-exists guard (with an accurate message distinguishing "already shipped" from "a previous run's push failed, exists locally only"), and a local-main-in-sync-with-origin check (a stale clone would compute the wrong shipped commit).release/tag-releaseinto private recipes (_check-semver-format,_check-on-main), following the existingcheck:dependency pattern in this justfile.Known, documented (not fixed) limitation: if a later semver is tag-released before an earlier delayed one, the earlier version's changelog section can repeat commits already published under the later one — flagged with a
ponytail:comment at the point it would occur, since a full fix means tracking already-published commit ranges rather than deriving them from tag ancestry, and this ordering is rare for a single-operator release cadence.Test plan
No app code changed — this is release tooling only (
justfile,CLAUDE.md,cliff.toml,ci_post_clone.sh), so the Flutter test suite is unaffected.just --list/just --show release/just --show tag-releaseparse correctly_check-semver-format,_check-on-main,_check-tag-absentdirectly — all fail closed with the expected messagestag-releaseresolution chain against the real, already-shipped 1.0.0 release (no writes): confirmedasc versions view --include-buildreturns the correct attached build (48, not the newer 49 upload), Xcode Cloud build-run lookup resolves the correct source commit, andgit-cliff <range> --output -produces the expected section without touchingCHANGELOG.mdjust release/just tag-releasefor real against production Xcode Cloud/App Store Connect🤖 Generated with Claude Code