fix(ci): baseline the release changelog on the previous tag, not published_at - #125
Open
basilebong wants to merge 1 commit into
Open
fix(ci): baseline the release changelog on the previous tag, not published_at#125basilebong wants to merge 1 commit into
basilebong wants to merge 1 commit into
Conversation
…ished_at `publish.yml`'s release job called `releases/generate-notes` without `previous_tag_name`, so GitHub chose the baseline itself — the newest prior release by `published_at`. That ordering is permanently wrong in this repo: alpha.3's Release was backfilled on 2026-07-21 two seconds after alpha.4's was created, so alpha.3 has the later `published_at` and looks like the most recent release forever. alpha.5 shipped with the result: a changelog spanning alpha.3...alpha.5 that replayed five PRs already released in alpha.4 (#105, #103, #107, #106, #108). Its body was corrected by hand after the fact; without this fix alpha.6 and every release after it reproduce the same bug. Resolve the previous tag from git ancestry instead — a backfilled Release can't reorder the commit graph. This needs a checkout in the release job (`fetch-depth: 0`, since `git describe` walks history); `persist-credentials: false` per supply-chain.md, and the job keeps its single `contents: write` grant. `git tag -l --sort=-v:refname` was the obvious alternative and is a trap: it sorts `v0.1.0-alpha.1` above `v0.1.0` unless `versionsort.suffix` is set, so it would break on the first stable release — the one release you least want wrong. Verified both against the real tags before choosing. No test accompanies this: the repo has no harness for workflow YAML, and a CI-only path can't be exercised without a tag push. Verified by hand instead — YAML parses, the extracted script passes `bash -n` and shellcheck, and the resolution logic dry-runs correctly over the real tags (alpha.5 -> alpha.4, alpha.4 -> alpha.3, alpha.2 -> no predecessor, which correctly omits the field). The real proof is alpha.6's changelog. Co-Authored-By: Claude Opus 5 (1M context) <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 bug
publish.yml'sreleasejob callsreleases/generate-noteswithoutprevious_tag_name, leaving GitHub to pick the baseline: the newest prior release bypublished_at. That ordering is permanently wrong in this repo.alpha.3's Release was backfilled by hand on 2026-07-21, two seconds after alpha.4's was created:
published_at2026-07-21T07:42:45Z2026-07-21T07:42:47Z← laterSo alpha.3 looks like the most recent release forever, and every changelog baselines against it.
This already shipped. v0.0.1-alpha.5's auto-generated body spanned
alpha.3...alpha.5and re-listed five PRs already released in alpha.4 — #105, #103, #107, #106, #108. I corrected that release's body by hand. Without this fix, alpha.6 and every release after it reproduce it, and the duplication grows.published_atisn't settable via the API, so the mis-ordering can't be repaired at the source.The fix
Resolve the previous tag from git ancestry — a backfilled Release can't reorder the commit graph:
PREV="$(git describe --tags --abbrev=0 --match 'v*.*.*' "$TAG^" 2>/dev/null || true)"Empty
PREV(the very first tag, which has no predecessor) omits the field and letsgenerate-notesfall back to its own default.This needs a checkout in the
releasejob, withfetch-depth: 0becausegit describewalks history and a shallow clone can't see prior tags.persist-credentials: falsepersupply-chain.md; the job keeps its singlecontents: writegrant, so least-privilege is unchanged.Why not
git tag -l --sort=-v:refnameIt's the obvious alternative and it's a trap — it sorts prereleases above the stable release they precede unless
versionsort.suffixis configured:It happens to work on today's all-prerelease tag list, then breaks on the first stable release — the one release you least want wrong. Ancestry needs no config and has no such edge.
Verification
No test accompanies this: the repo has no harness for workflow YAML, and a CI-only path can't be exercised without a tag push. Verified by hand instead:
releasejob's steps andpermissionsare as intended.runscript passesbash -nand shellcheck (the one remainingSC2016is pre-existing and a false positive — those%sare printf placeholders).generate-noteswithprevious_tag_name=v0.0.1-alpha.4returns exactly the 10 commits inalpha.4..HEAD.The real proof is alpha.6's changelog starting at alpha.5. Worth a glance at the "Full Changelog" compare link on the next release.
🤖 Generated with Claude Code