feat(release): attach built distributions to the GitHub Release on tag - #2
Merged
Conversation
…n tag A `v*` tag published to PyPI and left the tag bare here: no Release, and none of the artifacts the run had already built. A third job now downloads the same artifact the build job uploads and creates or updates the Release with the wheel and sdist attached. Release notes come from the changelog section for the tag rather than from generated notes, which summarise commits and so cannot describe a release that arrives as a single commit. `scripts/release_notes.py` extracts the section, rewrites its relative links absolute and pinned at the tag — a release body is not rendered relative to the repository root, so relative targets 404 — and exits non-zero when no section matches, so the workflow falls back to generated notes instead of publishing an empty body. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GeBdcy43H9CZkcjk4Jvt8n
haoranc
approved these changes
Sep 7, 2026
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 v0.1.0 tag published to PyPI and left this repository with a bare tag — no Release, and none of the artifacts the run had already built and uploaded. This adds the job that closes that.
The v0.1.0 Release was created by hand from that run's artifacts so it is not left empty. This is so nobody has to do that again.
The job
A third job,
needs: build,permissions: contents: write, downloading the samepython-package-distributionsartifact the build job already uploads. Create-or-update, so a re-run refreshes the assets rather than failing.It depends on
buildrather than onpublish-pypi, so a Release still appears if the PyPI upload is skipped or fails. Noting that as a deliberate choice rather than an oversight.Why the notes come from the changelog
Generated release notes summarise the commits in a release. This repository receives each version as a single commit, so generated notes for v0.1.0 would have been one line describing thirteen changes. The changelog section is already one line per user-visible change, each linking into the command reference.
scripts/release_notes.pyextracts it and does two things a raw paste would get wrong:docs/commands.md#initwould 404. Pinning at the tag rather than a branch also keeps old release notes pointing at the documentation as it stood for that version.Verified
--tag v0.1.0exits 0 — 13 links, all absolute, all pinned at/blob/v0.1.0/.--tag v9.9.9exits 1 with a diagnostic, and the workflow branches on that to fall back to generated notes. A guard that cannot fail is not a guard, so this direction was tested rather than assumed.## 0.1.0 - DATEand the bracketed## [0.1.0] - DATE.make preflightgreen — ruff clean including the new script, 654 passed / 46 skipped, both artifacts built,twine checkPASSED.No changelog entry: a release-pipeline step is not a user-visible delta, and an entry would consume the next version number for plumbing.
🤖 Generated with Claude Code
https://claude.ai/code/session_01GeBdcy43H9CZkcjk4Jvt8n