Release Workflow (Maintainers Only)
The release workflow includes two tools to help automate the process.
Towncrier aggregates all files in newsfragments/ into CHANGELOG.md, then deletes the used fragment files.
Bump My Version updates the version in the appropriate files.
This workflow produces:
one release commit (version bumps + changelog),
one git tag (
vX.Y.Z).
Note:
Do not run this on forks of the project
This requires tag permissions
Prerequisites
Make sure the working tree is ready for a release
Up to date with upstream
mainVerify tests and basic install/use
Release environment available (uv, towncrier, bump-my-version)
Decide on the type of release (
patch,minor, ormajor)Review/edit fragment wording for clarity
Call out breaking changes explicitly (if any)
Ensure release notes are understandable to users
Step-By-Step Release
At release time, the following steps need to be completed.
1) Sync and create a release branch
git checkout main
git pull --ff-only
git checkout -b release/next
2) Verify news fragments exist
uv run towncrier check
This should report no problems.
If this reports any problems, add/fix fragments in newsfragments/ before continuing.
3) Check clean git tree and bump the version (updates files, no commit/tag yet)
Check to make sure the git tree is ready for release. If the following command prints anything, fix it before continuing:
git status --porcelain
Choose one based on the type of release:
major release:
uv run bump-my-version bump major --no-commit --no-tagminor release:
uv run bump-my-version bump minor --no-commit --no-tagpatch release:
uv run bump-my-version bump patch --no-commit --no-tag
This updates the version in all configured files (e.g. pyproject.toml, sphinx/source/conf.py).
4) Read the new version from pyproject.toml
NEW_VERSION="$(python - <<'PY'
import tomllib
with open("pyproject.toml","rb") as f:
print(tomllib.load(f)["project"]["version"])
PY
)"
echo "Releasing $NEW_VERSION"
5) Preview the changelog (no files modified)
uv run towncrier build --draft --version "$NEW_VERSION"
Review the output for wording and grouping. If needed, edit fragments (or add a missing fragment).
6) Build the changelog (writes project CHANGELOG and removes fragments)
uv run towncrier build --version "$NEW_VERSION" --yes
Optional: specify a date explicitly:
uv run towncrier build --version "$NEW_VERSION" --date 2026-02-13 --yes
NOTE: Towncrier must write to the canonical root ./CHANGELOG.md.
7) Commit the release changes
git add pyproject.toml CHANGELOG.md newsfragments/ sphinx/source/conf.py uv.lock
git commit -m "Bump to new version -> v$NEW_VERSION"
8) Push branch
git push -u origin HEAD
9) Create the Codeberg release PR
On Codeberg, create a release PR for tag v$NEW_VERSION from the release branch into main, merge it once CI is green.
Use the CHANGELOG.md section for $NEW_VERSION as the release notes.
10) Tag the release
After PR merged then can tag it.
git checkout main
git pull --ff-only
git tag -a "v$NEW_VERSION" -m "Release v$NEW_VERSION"
git push origin "v$NEW_VERSION"
11) Publish Documentation
If Codeberg/forgejo workflow queues are not clearing quickly then see Docs Release Workflow for steps to take to manually publish the documentation.