feat(sdk-python): replace verbatim release notes inheritance with --generate-notes - #3835
Conversation
…enerate-notes The previous implementation fetched the entire body of the previous GitHub release and appended it to the new release notes. Because each release body already contained the body of the one before it, this created a linear chain that grew with every stable release — eventually hitting GitHub's 125 KB release body limit. Replace the body-chaining approach with GitHub's built-in --generate-notes flag, which auto-generates a bounded, PR-based changelog scoped between two tags via --notes-start-tag. The SDK metadata header (package name + version) is preserved via --notes-file, which GitHub prepends above the auto-generated changelog. For the first-ever release (no previous SDK tag), --generate-notes is skipped to avoid pulling in unrelated non-SDK commits, falling back to a static "Initial release" message instead. Closes #3796 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Updates the Python SDK release workflow to stop inheriting the entire previous release body and instead rely on GitHub CLI’s auto-generated notes (bounded by the previous SDK tag), preventing release bodies from growing toward GitHub’s size limit.
Changes:
- Replace “fetch previous release body and append” logic with
gh release create --generate-notes. - Add
--notes-start-tag sdk-python-<prev>when a previous SDK release tag exists; otherwise skip generation and emit an “Initial release” message.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Rename NOTES_START_TAG_FLAG → NOTES_START_TAG_ARG (contains key-value pair, not just a flag) - Fix misleading "Initial release" message — PREVIOUS_RELEASE_TAG is empty for all nightly/preview releases, not just the first release - Add comments explaining why old error handling is safe to remove 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
…art-tag If a prior release published to PyPI but failed to create a GitHub release/tag, the tag won't exist in Git. Using --notes-start-tag with a nonexistent tag would cause gh release create to fail after PyPI publish, leaving a partial release state. Add a git rev-parse check before using --notes-start-tag. When the tag is missing, fall back to static notes with a ::warning:: annotation, ensuring the GitHub release is always created. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…eview/nightly The comment previously implied the else-branch was only for preview/nightly, but PREVIOUS_RELEASE_TAG is also empty for the very first stable release (no prior stable version on PyPI). 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
wenshao
left a comment
There was a problem hiding this comment.
No review findings. LGTM! ✅
— deepseek-v4-pro via Qwen Code /review
Code ReviewOverviewReplaces the verbatim previous-release-body inheritance in CorrectnessLogic flow is sound. The three branches are now well-defined:
The drift-recovery case added in 819d82f is the right call — it prevents a partial-release state where PyPI succeeds but
Empty-string flag expansion: Code quality / style
Risks / things to watch
Suggestions (follow-ups)
VerdictLGTM — ready to merge. The fix correctly addresses the root cause (chain growth), edge cases around missing tags and first releases are handled defensively, and prior review feedback has been addressed in 819d82f / cb23ae2. The remaining bash-quoting nit and the parallel TS workflow fix are reasonable as follow-ups. |
ShellCheck SC2086 flags unquoted variables containing spaces
(NOTES_START_TAG_ARG holds "--notes-start-tag sdk-python-v0.1.0").
Replace string-based flag variables with a Bash array that is expanded
via "${GH_RELEASE_ARGS[@]}" — properly quoted and shellcheck-safe.
Also consolidates the prerelease flag into the same array, removing the
now-unused PRERELEASE_FLAG variable.
🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
Code Review: PR #3835 —
|
wenshao
left a comment
There was a problem hiding this comment.
Looks good — the chain-growth root cause is fixed by switching to --generate-notes --notes-start-tag, and the iteration round (the git rev-parse guard for the PyPI-published-without-GitHub-tag case, the comment cleanup, the move from ${PRERELEASE_FLAG} to a properly quoted bash array) addresses every concern raised earlier. The fall-through to static notes when the previous tag is missing is the right choice — it keeps the release path resilient if the PyPI publish ran but the GitHub tag creation failed on a prior run.
One small style nit inline.
Follow-up worth considering separately (not blocking): --generate-notes will include every PR merged between sdk-python-${prev} and the new tag — including ones that don't touch SDK Python. A .github/release.yml with category/label filters (or a path-scoped exclude) would make the auto-generated changelog more relevant for SDK Python releases in this monorepo. Out of scope for this PR.
DRY improvement: sdk-python-${PREVIOUS_RELEASE_TAG} was repeated 3
times. Extract into a local PREVIOUS_TAG_NAME variable, symmetric with
the existing TAG_NAME at the top of the script.
🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
tanzhenxin
left a comment
There was a problem hiding this comment.
Review
Targets the real root cause of the chain-growth bug — each previous release body already embedded all prior bodies, so verbatim inheritance grew linearly until it hit GitHub's 125 KB limit. Switching to gh release create --generate-notes --notes-start-tag produces a PR-based changelog bounded between the two tags, which is exactly the right shape. The git rev-parse guard that falls back to a static "see commit history" message when the previous tag is missing locally (PyPI publish succeeded but the GitHub release/tag step didn't) is the right defensive move and was correctly added in response to review feedback.
The refactor from string-concatenated PRERELEASE_FLAG to a GH_RELEASE_ARGS Bash array is cleaner and avoids the trailing empty-arg expansion class of bug. Comments accurately call out the non-obvious branches — empty PREVIOUS_RELEASE_TAG covers both preview/nightly and the very first stable release. The PREVIOUS_TAG_NAME extraction in the latest commit is a tidy DRY follow-up.
Verdict
APPROVE — Small, focused fix for a real problem with correct fallback handling.
…enerate-notes (#3835) * feat(sdk-python): replace verbatim release notes inheritance with --generate-notes The previous implementation fetched the entire body of the previous GitHub release and appended it to the new release notes. Because each release body already contained the body of the one before it, this created a linear chain that grew with every stable release — eventually hitting GitHub's 125 KB release body limit. Replace the body-chaining approach with GitHub's built-in --generate-notes flag, which auto-generates a bounded, PR-based changelog scoped between two tags via --notes-start-tag. The SDK metadata header (package name + version) is preserved via --notes-file, which GitHub prepends above the auto-generated changelog. For the first-ever release (no previous SDK tag), --generate-notes is skipped to avoid pulling in unrelated non-SDK commits, falling back to a static "Initial release" message instead. Closes #3796 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): address review comments on release notes - Rename NOTES_START_TAG_FLAG → NOTES_START_TAG_ARG (contains key-value pair, not just a flag) - Fix misleading "Initial release" message — PREVIOUS_RELEASE_TAG is empty for all nightly/preview releases, not just the first release - Add comments explaining why old error handling is safe to remove 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): validate previous tag exists before using --notes-start-tag If a prior release published to PyPI but failed to create a GitHub release/tag, the tag won't exist in Git. Using --notes-start-tag with a nonexistent tag would cause gh release create to fail after PyPI publish, leaving a partial release state. Add a git rev-parse check before using --notes-start-tag. When the tag is missing, fall back to static notes with a ::warning:: annotation, ensuring the GitHub release is always created. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): clarify else-branch comment covers first stable + preview/nightly The comment previously implied the else-branch was only for preview/nightly, but PREVIOUS_RELEASE_TAG is also empty for the very first stable release (no prior stable version on PyPI). 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): use Bash array for gh release args to fix SC2086 lint ShellCheck SC2086 flags unquoted variables containing spaces (NOTES_START_TAG_ARG holds "--notes-start-tag sdk-python-v0.1.0"). Replace string-based flag variables with a Bash array that is expanded via "${GH_RELEASE_ARGS[@]}" — properly quoted and shellcheck-safe. Also consolidates the prerelease flag into the same array, removing the now-unused PRERELEASE_FLAG variable. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * refactor(sdk-python): extract PREVIOUS_TAG_NAME to reduce repetition DRY improvement: sdk-python-${PREVIOUS_RELEASE_TAG} was repeated 3 times. Extract into a local PREVIOUS_TAG_NAME variable, symmetric with the existing TAG_NAME at the top of the script. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
…enerate-notes (QwenLM#3835) * feat(sdk-python): replace verbatim release notes inheritance with --generate-notes The previous implementation fetched the entire body of the previous GitHub release and appended it to the new release notes. Because each release body already contained the body of the one before it, this created a linear chain that grew with every stable release — eventually hitting GitHub's 125 KB release body limit. Replace the body-chaining approach with GitHub's built-in --generate-notes flag, which auto-generates a bounded, PR-based changelog scoped between two tags via --notes-start-tag. The SDK metadata header (package name + version) is preserved via --notes-file, which GitHub prepends above the auto-generated changelog. For the first-ever release (no previous SDK tag), --generate-notes is skipped to avoid pulling in unrelated non-SDK commits, falling back to a static "Initial release" message instead. Closes QwenLM#3796 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): address review comments on release notes - Rename NOTES_START_TAG_FLAG → NOTES_START_TAG_ARG (contains key-value pair, not just a flag) - Fix misleading "Initial release" message — PREVIOUS_RELEASE_TAG is empty for all nightly/preview releases, not just the first release - Add comments explaining why old error handling is safe to remove 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): validate previous tag exists before using --notes-start-tag If a prior release published to PyPI but failed to create a GitHub release/tag, the tag won't exist in Git. Using --notes-start-tag with a nonexistent tag would cause gh release create to fail after PyPI publish, leaving a partial release state. Add a git rev-parse check before using --notes-start-tag. When the tag is missing, fall back to static notes with a ::warning:: annotation, ensuring the GitHub release is always created. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): clarify else-branch comment covers first stable + preview/nightly The comment previously implied the else-branch was only for preview/nightly, but PREVIOUS_RELEASE_TAG is also empty for the very first stable release (no prior stable version on PyPI). 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): use Bash array for gh release args to fix SC2086 lint ShellCheck SC2086 flags unquoted variables containing spaces (NOTES_START_TAG_ARG holds "--notes-start-tag sdk-python-v0.1.0"). Replace string-based flag variables with a Bash array that is expanded via "${GH_RELEASE_ARGS[@]}" — properly quoted and shellcheck-safe. Also consolidates the prerelease flag into the same array, removing the now-unused PRERELEASE_FLAG variable. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * refactor(sdk-python): extract PREVIOUS_TAG_NAME to reduce repetition DRY improvement: sdk-python-${PREVIOUS_RELEASE_TAG} was repeated 3 times. Extract into a local PREVIOUS_TAG_NAME variable, symmetric with the existing TAG_NAME at the top of the script. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
Summary
--generate-notes+--notes-start-tagflags. For first-ever releases (no previous SDK tag),--generate-notesis skipped and a static "Initial release" message is used instead.--notes-start-tagprefix (sdk-python-) matching the actual Git tag format.Validation
--generate-notescombined with--notes-fileprepends custom body (per GitHub docs).Scope / Risk
Testing Matrix
Testing matrix notes:
Linked Issues / Bugs
Closes #3796
🤖 Generated with Qwen Code