Skip to content

fix(release): list squash-merged PRs in the generated changelog - #226

Merged
robercano-ghbot merged 1 commit into
mainfrom
fix/release-changelog-squash-merges
Aug 6, 2026
Merged

fix(release): list squash-merged PRs in the generated changelog#226
robercano-ghbot merged 1 commit into
mainfrom
fix/release-changelog-squash-merges

Conversation

@robercano-ghbot

Copy link
Copy Markdown
Collaborator

Prerequisite for cutting v0.3.1: without this, release.sh would generate a wrong changelog for that release.

The bug

release.sh derived its CHANGELOG section from git log --merges whenever any merge commit existed in the range, and fell back to non-merge subjects only when there were none. So a single merge commit in range silently discarded every squash-merged PR.

This repo's history mixes both styles — #215/#216 landed as merge commits, #217#221 as squashes. Simulating the generator over the real v0.3.0..origin/main range:

- #215: feat/issue-178-release-v0.3.0            <- the v0.3.0 release PR itself
- #216: feat/issue-187-census-gh-parse-robustness

Two bullets instead of seven. It omitted all five shipped fixes (#217, #218, #219, #220, #221) and named the previous release's own PR as a change in the next one.

The fix

Walk the base branch's first-parent chain. One bullet per landed change, whatever shape it landed in:

  • a merge-committed PR contributes its merge subject, rewritten to #N: branch
  • a squash-merged PR contributes its squash subject
  • a merged PR's internal commits are still excluded — they hang off the second parent, off the first-parent chain. That exclusion is what the --merges-only path was really guarding against, and --first-parent gets it without discarding anything.
  • a direct-to-base commit is on the first-parent chain and is a real shipped change, so it is now listed too

Verified against real history: 7 first-parent entries in v0.3.0..origin/main (5 squashes + 2 merges), with #216's two internal commits correctly dropped.

Tests

release.test.sh scenario A carried "in-range non-merge commit is excluded once merge commits exist", which encoded the old behaviour deliberately. That assertion is inverted, and paired with a new one asserting merged PRs' internal commits are still never double-listed.

New scenario H covers mixed merge+squash history — the exact v0.3.0..v0.3.1 shape — asserting both styles appear and the section holds exactly one bullet per landed change.

release.test.sh: PASS (51 checks)

Gates

GATES_FILE=self/gates.json — build: pass, lint: pass. test: release.test.sh passes; the suite as a whole has one pre-existing, unrelated failure in pr-feedback.test.sh scenario C that also reproduces on pristine origin/main and at the v0.3.0 tag (see the review comment below).

release.sh derived its CHANGELOG section from `git log --merges` whenever any
merge commit existed in the range, falling back to non-merge subjects only when
there were none. That silently dropped every squash-merged PR as soon as ONE
merge commit was present.

This repo's history mixes both styles: #215/#216 landed as merge commits,
#217-#221 as squashes. The v0.3.0..HEAD range therefore generated 2 bullets
instead of 7 — omitting five shipped fixes and naming the v0.3.0 release PR
itself as a change in the next release.

Walk the base branch's first-parent chain instead. One bullet per landed
change, whatever shape it landed in:
  - a merge-committed PR contributes its merge subject (rewritten to "#N: branch")
  - a squash-merged PR contributes its squash subject
  - a merged PR's internal commits stay excluded — they hang off the second
    parent, which is the double-listing the --merges-only path was really
    guarding against
A direct-to-base commit is on the first-parent chain and is a real shipped
change, so it is now listed too.

Tests: scenario A's "non-merge commit is excluded once merge commits exist"
assertion encoded the old behaviour and is inverted, paired with a new
assertion that merged PRs' internal commits are still never double-listed.
New scenario H covers mixed merge+squash history — the real v0.3.0..v0.3.1
shape — asserting exactly one bullet per landed change.

release.test.sh: PASS (51 checks)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@robercano-ghbot robercano-ghbot added the needs-human Loop escalated: attempt budget exhausted, manual triage required label Aug 6, 2026
@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(release): list squash-merged PRs in the generated changelog (not yet reviewed)

@robercano-ghbot robercano-ghbot added claude-ci-fixing In-flight guard: an automated CI-fix pass is addressing this PR and removed needs-human Loop escalated: attempt budget exhausted, manual triage required labels Aug 6, 2026
@robercano-ghbot robercano-ghbot added the needs-human Loop escalated: attempt budget exhausted, manual triage required label Aug 6, 2026
@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(release): list squash-merged PRs in the generated changelog (not yet reviewed)

@robercano-ghbot robercano-ghbot added needs-human Loop escalated: attempt budget exhausted, manual triage required and removed needs-human Loop escalated: attempt budget exhausted, manual triage required labels Aug 6, 2026
@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(release): list squash-merged PRs in the generated changelog (not yet reviewed)

@robercano-ghbot robercano-ghbot removed the needs-human Loop escalated: attempt budget exhausted, manual triage required label Aug 6, 2026
@robercano-ghbot
robercano-ghbot merged commit 686c5ff into main Aug 6, 2026
24 of 27 checks passed
@robercano-ghbot
robercano-ghbot deleted the fix/release-changelog-squash-merges branch August 6, 2026 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude-ci-fixing In-flight guard: an automated CI-fix pass is addressing this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants