fix(ci): start release notes from a tag that exists - #333
Conversation
The notes range was built from the previous release's *name*, never from a check that it exists. 1.9.3 shipped only as rc.1, so v1.9.4-rc.1 asked git for v1.9.3..v1.9.4-rc.1 and the publish step died on `unknown revision` -- after all four platforms had already built and uploaded their artifacts. The existing rc walk-down covers a skipped RC. Nothing covered a skipped stable, and that loop does not run at all for an rc.1 (`for n = 0; n >= 1`). This is not only about release notes: publish-msstore has `needs: publish-release`, so the same missing tag would have taken the Store deployment down with it on a stable promotion, which is the one place that failure is expensive to discover. Falls back to the nearest tag reachable from the release commit's parent, which is what "since the last release" meant to begin with -- v1.9.2 for the tag that failed, a 25-commit range. If no tag is reachable at all, the root commit keeps the range valid rather than handing git an empty left-hand side.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe build workflow validates the computed previous-release tag. Missing tags use a reachable fallback when available. RC notes and stable release creation handle the absence of a previous tag without creating an invalid range. ChangesRelease note generation
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/build.yml:
- Around line 762-763: Update the release-notes setup around FALLBACK and
NOTES_START_TAG to track whether a previous tag exists instead of using the root
commit SHA as a notes-start tag. Omit --notes-start-tag for the first stable
release, while retaining the root SHA only for RC git log range calculations.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: cc899fb5-8862-47e0-a860-506c5ee2654f
📒 Files selected for processing (1)
.github/workflows/build.yml
| FALLBACK="$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || true)" | ||
| NOTES_START_TAG="${FALLBACK:-$(git rev-list --max-parents=0 HEAD | tail -1)}" |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
ROOT_COMMIT="$(git rev-list --max-parents=0 HEAD | tail -n 1)"
if git show-ref --verify --quiet "refs/tags/${ROOT_COMMIT}"; then
echo "::error::The root commit is already tagged; use an untagged test repository."
exit 1
fi
rg -n -C 2 -- '--notes-start-tag "\$NOTES_START_TAG"' .github/workflows/build.yml
if [[ -z "${GH_TOKEN:-}" || -z "${GITHUB_REPOSITORY:-}" || -z "${RELEASE_TAG:-}" ]]; then
echo "Set GH_TOKEN, GITHUB_REPOSITORY, and RELEASE_TAG to test the API request."
exit 0
fi
gh api --method POST \
"/repos/${GITHUB_REPOSITORY}/releases/generate-notes" \
-f "tag_name=${RELEASE_TAG}" \
-f "previous_tag_name=${ROOT_COMMIT}" \
--jq '.body' >/dev/nullRepository: getopenscreen/openscreen
Length of output: 548
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' '--- workflow context ---'
sed -n '735,850p' .github/workflows/build.yml
printf '%s\n' '--- tags ---'
git tag --sort=creatordate | tail -n 30
printf '%s\n' '--- relevant identifiers ---'
rg -n -C 3 'NOTES_START_TAG|FALLBACK|NOTES_ARGS|generate-notes|release create|RC|stable' .github/workflows/build.ymlRepository: getopenscreen/openscreen
Length of output: 18090
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
# Read-only verifier for the fallback contract and the two release-note paths.
set +e
current_tag="$(git describe --tags --abbrev=0 HEAD 2>/dev/null)"
describe_status=$?
set -e
root_commit="$(git rev-list --max-parents=0 HEAD | tail -n 1)"
printf 'root_commit=%s\n' "$root_commit"
printf 'describe_head_status=%s value=%s\n' "$describe_status" "${current_tag:-<none>}"
if [[ -n "$current_tag" ]]; then
set +e
previous_tag="$(git describe --tags --abbrev=0 "${current_tag}^" 2>/dev/null)"
previous_status=$?
set -e
else
previous_tag=''
previous_status=128
fi
printf 'fallback_status=%s value=%s\n' "$previous_status" "${previous_tag:-<none>}"
if [[ -n "$previous_tag" ]]; then
notes_start_tag="$previous_tag"
notes_start_tag_is_tag=true
else
notes_start_tag="$root_commit"
notes_start_tag_is_tag=false
fi
printf 'notes_start_tag=%s\n' "$notes_start_tag"
printf 'notes_start_tag_is_tag=%s\n' "$notes_start_tag_is_tag"
if [[ "$notes_start_tag_is_tag" == true ]]; then
printf 'stable_notes_args=--generate-notes --notes-start-tag %s\n' "$notes_start_tag"
else
printf 'stable_notes_args=--generate-notes\n'
fi
printf 'rc_range=%s..HEAD\n' "$notes_start_tag"Repository: getopenscreen/openscreen
Length of output: 463
🌐 Web query:
GitHub REST API generate release notes previous_tag_name tag name commit SHA behavior gh release create --notes-start-tag
💡 Result:
The GitHub Release Notes API and the GitHub CLI (gh) provide mechanisms to automatically generate release notes, specifically allowing you to define the range of changes by specifying a starting point. GitHub REST API (Generate Release Notes Endpoint) The endpoint POST /repos/{owner}/{repo}/releases/generate-notes is designed to generate release notes without saving them [1][2]. - previous_tag_name: This body parameter allows you to manually specify the starting tag for the range of changes [1][2]. If provided, the API generates notes for the changes between this tag and the tag_name specified [1]. - tag_name: This required body parameter is the tag name for the new release [1][2]. - target_commitish: This specifies the commit SHA or branch for the tag [1][2]. If the tag does not yet exist, this is required to define where the tag should be placed [1][2]. GitHub CLI (gh release create) The GitHub CLI command gh release create uses the Generate Release Notes API when the --generate-notes flag is passed [3][4]. - --notes-start-tag: This flag allows you to specify the starting tag for the generated release notes, which corresponds to the previous_tag_name parameter in the underlying REST API [5]. - Behavior Note: When using --notes-start-tag, it is often necessary to explicitly include the --generate-notes flag to ensure the CLI uses the Release Notes API to produce the body content rather than reverting to interactive mode or other defaults [6]. - Distinction: --notes-start-tag (used with --generate-notes) should not be confused with --notes-from-tag. The latter fetches notes from the git tag annotation or the commit message associated with the tag, rather than invoking the Release Notes API to summarize changes and contributors [7][4]. In summary, the REST API uses previous_tag_name to define the range, and the CLI exposes this via the --notes-start-tag flag, which should be used in conjunction with --generate-notes to produce automated summary content [1][5].
Citations:
- 1: https://docs.github.com/en/rest/releases/releases
- 2: https://docs.github.com/v3/repos/releases
- 3: docs(release create): difference
--generate-notesand--notes-from-tagcli/cli#11534 - 4: Improve documentation to distinguish between
gh release create--notes-from-tagand--generate-notescli/cli#8372 - 5: Support
--previous-tagflag for generating release notes ingh release createcli/cli#5963 - 6: gh release create --notes-start-tag is not generating notes cli/cli#8820
- 7: https://cli.github.com/manual/gh_release_create
Do not pass the root commit SHA as --notes-start-tag.
When no prior tag exists, NOTES_START_TAG contains the root commit SHA. The stable-release path always passes this value to GitHub's tag-based release-notes API. Track whether the value is a tag, and omit --notes-start-tag for the first stable release. Use the root SHA only for RC git log ranges.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/build.yml around lines 762 - 763, Update the release-notes
setup around FALLBACK and NOTES_START_TAG to track whether a previous tag exists
instead of using the root commit SHA as a notes-start tag. Omit
--notes-start-tag for the first stable release, while retaining the root SHA
only for RC git log range calculations.
The fallback filled NOTES_START_TAG with the root commit's SHA so the range would always be valid. That is right for the RC path, which feeds it to `git log`, and wrong for the stable path, which feeds it to `gh release create --notes-start-tag` -- the API's previous_tag_name, which takes a tag NAME. A SHA there is an invalid argument, not a lenient fallback, so the one case the fallback existed for would still have failed. It now stays empty when no tag is reachable, and each consumer handles that: the RC notes walk the whole history and drop the "since <tag>" wording rather than printing a blank where a tag should be, and the stable path omits the flag so GitHub picks its own previous release -- which is the correct answer when there is not one. Unreachable on this repo today (v1.9.2 is right there), so this is about the next fork or a fresh repository rather than about 1.9.4.
v1.9.4-rc.1built all four platforms, uploaded every artifact, then died publishing:build.yml:727 derives the notes range from the previous release's name and never checks that the tag exists. 1.9.3 only ever shipped as
rc.1, sov1.9.3is a name for nothing.The rc walk-down just below it handles a skipped RC. Nothing handled a skipped stable — and that loop does not execute at all for an rc.1 (
for n = RC_NUMBER - 1; n >= 1withRC_NUMBER=1).Why this is worse than lost release notes
publish-msstoredeclaresneeds: publish-release. So the same missing tag takes the Microsoft Store deployment down with it on a stable promotion — the one place where discovering this is expensive. Promoting 1.9.4 would have failed identically.The fix
Verify the computed tag, and when it is absent fall back to the nearest tag reachable from the release commit's parent — which is what "since the last release" meant to begin with. For the tag that failed:
A sensible range rather than a crash. If no tag is reachable at all — a first release — the root commit keeps the range valid instead of handing git an empty left-hand side.
Needs cherry-picking onto
release/v1.9.4before rc.2 is cut, since that branch is frozen at the commit before this one.Summary by CodeRabbit