Releasing¶
Steps 1–3 are runs of Actions → Release → Run workflow on main, with a bump
(minor or major, counted from the newest final release) and a stage. Before
starting, a maintainer checks that no deprecation is due for removal.
- Alphas (optional). Stage alpha tags
vX.Y.0aNonmain, published as a pre-release. Run it again for the next alpha; features keep landing onmain. - Betas (optional): the feature freeze. Stage beta creates
release/X.Yfrommain, tagsvX.Y.0b1and opens the release PRchore: release vX.Y.0as a draft. From then on only backported fixes reachX.Y: each one merged intorelease/X.Ytags the next beta and updates the release PR. Features merged intomainwait for the next release. - Release candidates. Stage rc promotes a release in beta: it tags
vX.Y.0rc1onrelease/X.Yand marks the release PR ready for review. Without betas, it createsrelease/X.YwithvX.Y.0rc1and opens the release PR. Every backport then tags the next candidate. Testing pre-releases is optional (pip install --pre <package>==X.Y.0rcN). - Release. A maintainer reviews the changelog in the release PR and merges it. The
bot tags
vX.Y.0; the repository's publish workflow builds, drafts the GitHub release with every file attached, publishes to PyPI and publishes the release, which makes it immutable. The bot then adds the release's section ofCHANGELOG.mdtomainthrough a PR that it merges itself, and closes the pending patch release PR of the previous line, if any: its support ends here, and its fixes are inX.Y.0. Merge that PR first to ship them.
The workflow refuses to go backwards (an alpha once release/X.Y exists, a beta once it
is at release candidates), and to create a release branch while another one has no final
release yet. CHANGELOG.md on main lists every final release of every line; to reword
an older section, edit it on main with a normal PR (a release PR only adds its own
section to main).
A published release never changes. A broken one is yanked on PyPI and replaced by a new
patch release. Only the bot creates v* tags.