5. Release¶
Publish Python packages to GitHub Releases and documentation to GitHub Pages.
Automatic release¶
Merge a releasable change to dev for a release candidate, or promote dev to main for a stable
release. main-release.yml validates the source, versions and builds the package, then uploads artifacts.
A tagged stable release also deploys docs from that tag. Docs-only commits do not publish docs.
Versions come from Conventional Commits;
never edit versions or create tags manually.
By hand¶
Use a clean main (stable) or dev (prerelease), synchronized with origin.
Complete setup and GitHub login, then run:
The release command versions, builds and uploads the full wheel/sdist set. It changes Git and GitHub;
coding agents need explicit per-action approval. Locally, the source revision is HEAD;
GitHub Actions supplies its tested GITHUB_SHA automatically. Confirm required CI passed before
publishing manually; make check alone does not establish hosted integration success.
For a stable manual release, publish docs separately from the clean released tag:
That command pushes gh-pages and requires separate authorization.
Retry an interrupted release¶
Retry the failed CI job if its tested source still matches the release. Locally, rerun make release
on the matching clean release branch. To upload from a clean checkout of the exact release tag:
If newer application commits exist, let their own workflow validate/release them.
Never rebuild an older release from later source. release-assets can create a missing GitHub
release and uploads missing attachments after comparing existing files (a different published file stops it); it does not publish to a package index.
Credentials¶
Credentials resolve from GH_TOKEN (in the environment), then the token saved by gh auth login,
then a hidden terminal prompt. release-assets uses the token or gh login. CI supplies its
automatic GitHub token; never print credentials. Use make install-dev for release and documentation tools.
Release sequence and safeguards¶
| Target / stage | Behavior |
|---|---|
make release-version |
Require main/dev, a clean tree and HEAD equal to fetched origin |
| Semantic-release build hook | uv lock && git add uv.lock && make test-installation; build failure stops commit/tag/publication |
make release-assets |
Require the tag at HEAD and one verified wheel/sdist pair for this package |
make release |
Run versioning, reuse valid artifacts or build missing ones, then upload sequentially |
The wheel and sdist versions equal project.version. Tags retain vX.Y.Z-rc.N spelling;
Python artifacts use normalized X.Y.ZrcN filenames.
CI retries may accept the exact single-parent chore(release): v<version> [skip ci] child of
the tested source, including recovery before its tag was pushed; newer application changes require
validation. Git hooks are disabled only during
semantic-release. With no new version or matching tag at HEAD, make release stops without uploading.
Repository settings (once)¶
Enable Actions release write permissions and configure Pages to deploy from gh-pages.
Enable squash merging so PR titles determine versions. CI installs locked tools with make install-dev.
After a release: sync main into dev¶
Merge main back into dev after a stable release. Use the stable version/changelog as the base
for the next candidate; see branch conventions.