From 62c6a0686d89195407319c5a113b4793590dcc28 Mon Sep 17 00:00:00 2001 From: Etienne Lescot Date: Wed, 5 Aug 2026 09:05:17 +0200 Subject: [PATCH] fix(ci): scope RC release notes to the previous RC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every RC of a line shipped the same release body. The notes start tag was derived from the stable version, so v1.9.0-rc.1 and v1.9.0-rc.2 both spanned v1.8.0.. — rc.2 just repeated rc.1's list plus its own few entries, and v1.8.0-rc.8 and rc.9 came out byte-identical. Testers had no way to see what a re-cut actually changed, which is the one question an RC body has to answer. Resolve the previous RC of the same line instead, walking down from the current rc number so a skipped or failed RC doesn't break the chain. rc.1 still falls back to the previous stable, and stable releases are untouched. Build the RC body from `git log` rather than --generate-notes. GitHub's generator lists only the PRs it manages to associate and silently drops real ones: #254 and #261 were merged into release/v1.9.0 yet never appeared in v1.9.0-rc.2's body, so an RC could omit the very fix it was cut for. The commit range is the actual diff. Stable releases keep --generate-notes — they are the public-facing ones and want the PR links and the New Contributors section. Needs fetch-depth: 0 on the publish job's checkout for the tags and history. --- .github/workflows/build.yml | 54 ++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2203ae78d..3c3f82937 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -474,6 +474,10 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + # Full history + tags: the RC notes below are built from `git log` over the + # range since the previous RC tag, and resolving that tag needs the tags. + fetch-depth: 0 - name: Resolve release tag id: release @@ -521,6 +525,21 @@ jobs: else NOTES_START_TAG="v$((PX - 1)).0.0" fi + # For an RC, compare against the PREVIOUS RC of the same line, not the previous + # stable. Deriving the start tag from STABLE_VERSION alone made every RC of a + # line span the same range, so each re-cut just repeated the last RC's notes + # plus its own handful, and testers could not see what the re-cut changed. + # Walk down from the current rc number so a skipped or failed RC doesn't break it. + if [[ "$IS_PRERELEASE" == "true" ]]; then + RC_NUMBER="${VERSION##*.}" + for (( n = RC_NUMBER - 1; n >= 1; n-- )); do + CANDIDATE="v${STABLE_VERSION}-rc.${n}" + if git rev-parse -q --verify "refs/tags/${CANDIDATE}" >/dev/null; then + NOTES_START_TAG="$CANDIDATE" + break + fi + done + fi echo "Computed notes_start_tag=${NOTES_START_TAG} for tag=${TAG}" echo "tag=$TAG" >> "$GITHUB_OUTPUT" @@ -570,17 +589,38 @@ jobs: if gh release view "$TAG" >/dev/null 2>&1; then gh release upload "$TAG" "${FILES[@]}" --clobber else - # --notes-start-tag controls which previous tag GitHub compares against - # when auto-generating the release notes. Default behaviour (most recent - # prior release by date) doesn't work for this fork because the v1.4.0 - # release in the fork was re-published after v1.5.0, which makes GitHub - # pick v1.4.0 as the "previous" for any v1.5.x release. + if [[ -n "$PRERELEASE_FLAG" ]]; then + # RC notes come from `git log`, not --generate-notes. GitHub's generator + # lists only the PRs it manages to associate, and on this repo it silently + # drops real ones — #254 and #261 were merged into the release branch and + # never appeared in v1.9.0-rc.2's body — so an RC could omit the very fix + # the re-cut was for. The commit range is the actual diff and can't lie. + # Stable releases keep --generate-notes below: they're the public-facing + # ones and want the PR links and the New Contributors section. + { + echo "## Changes since ${NOTES_START_TAG}" + echo + git log --no-merges --reverse --pretty='- %s' \ + --invert-grep --grep='^chore(release): bump to' \ + "${NOTES_START_TAG}..${TAG}" + echo + echo "**Full Changelog**: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/compare/${NOTES_START_TAG}...${TAG}" + } > "${RUNNER_TEMP}/rc-notes.md" + cat "${RUNNER_TEMP}/rc-notes.md" + NOTES_ARGS=(--notes-file "${RUNNER_TEMP}/rc-notes.md") + else + # --notes-start-tag controls which previous tag GitHub compares against + # when auto-generating the release notes. Default behaviour (most recent + # prior release by date) doesn't work for this fork because the v1.4.0 + # release in the fork was re-published after v1.5.0, which makes GitHub + # pick v1.4.0 as the "previous" for any v1.5.x release. + NOTES_ARGS=(--generate-notes --notes-start-tag "$NOTES_START_TAG") + fi # shellcheck disable=SC2086 gh release create "$TAG" "${FILES[@]}" \ --target "$GITHUB_SHA" \ --title "$TAG" \ - --generate-notes \ - --notes-start-tag "$NOTES_START_TAG" \ + "${NOTES_ARGS[@]}" \ $PRERELEASE_FLAG fi