Release Workflow

This workflow describes how to create a Buffalo Wings release as a maintainer. It covers the version bump, changelog generation, release commit, release tag, and the follow-up publication steps.

Goal

The goal is to produce:

  • one release commit containing the version updates and changelog,

  • one git tag in the form vX.Y.Z,

  • and one releasable project state that can then be published to PyPI and the documentation site.

This workflow uses Towncrier to build CHANGELOG.md from newsfragments/, and Bump My Version to update the project version.

Prerequisites

Before starting, make sure:

  • you are working in the canonical project repository rather than a fork,

  • you have permission to push branches and tags,

  • the working tree is clean,

  • the repository is up to date with main,

  • you know whether this release is patch, minor, or major,

  • the news fragments are present and readable,

  • and the release environment has uv, towncrier, and bump-my-version available.

Pre-Release Checks

Before beginning the formal release steps, confirm:

  • tests are passing,

  • the documentation builds successfully,

  • examples still run correctly,

  • and any breaking changes are clearly described in the release notes and fragments.

1. Sync And Create A Release Branch

Start from an up-to-date main branch and create a release branch:

git checkout main
git pull --ff-only
git checkout -b release/next

2. Verify The News Fragments

Check that the Towncrier fragments are valid:

uv run towncrier check

This should report no problems. If it does, add or fix fragments in newsfragments/ before continuing.

3. Confirm A Clean Repository State

Make sure the repository is clean before changing the version:

git status --porcelain

If this prints anything, resolve it before continuing.

4. Bump The Version

Choose the appropriate release type and update the version without creating a commit or tag yet:

  • major release: uv run bump-my-version bump major --no-commit --no-tag

  • minor release: uv run bump-my-version bump minor --no-commit --no-tag

  • patch release: uv run bump-my-version bump patch --no-commit --no-tag

This updates the configured version files, such as pyproject.toml and sphinx/source/conf.py.

5. Read The New Version

Read the updated version from pyproject.toml:

VERSION="$(uv run python - <<'PY'
import tomllib
with open("pyproject.toml", "rb") as f:
    print(tomllib.load(f)["project"]["version"])
PY
)"
VERSION_TAG="v${VERSION}"
echo "Releasing ${VERSION_TAG}"

6. Preview The Changelog

Preview the changelog without modifying files:

uv run towncrier build --draft --version "${VERSION}"

Review the generated text for wording, grouping, and missing items. If needed, edit the fragments before continuing. For externally consumed releases, confirm the preview communicates:

  • what changed in user-visible terms,

  • what is considered stable now,

  • and what remains actively evolving.

7. Build The Changelog

Write the final changelog and remove the consumed fragments:

uv run towncrier build --version "${VERSION}" --yes

If you need to set the changelog date explicitly, use:

uv run towncrier build --version "${VERSION}" --date 2026-02-13 --yes

Towncrier must write to the canonical root CHANGELOG.md.

8. Run The Full Project Checks

Run the standard full check suite before committing the release:

./scripts/run_checks.sh

This should pass cleanly before you continue.

9. Commit The Release Changes

Stage the expected release-related files and create the release commit:

git add .copier-answers.yml CITATION.cff src/buffalo_wings/__init__.py \
        pyproject.toml CHANGELOG.md newsfragments/ sphinx/source/conf.py uv.lock
git commit -m "Bump to new version -> ${VERSION_TAG}"

Review the staged files before committing to make sure no unrelated changes are included.

10. Push The Release Branch

Push the release branch to the remote:

git push -u origin HEAD

11. Open And Merge The Release PR

On Codeberg, open a pull request from the release branch into main. Use the CHANGELOG.md section for ${VERSION} as the release notes, and merge the PR once CI is green. For first external releases, include a short release summary in the PR body that highlights current subsystem maturity and known limitations.

12. Tag The Release

After the release PR has been merged, create and push the release tag:

git checkout main
git pull --ff-only
git tag -a "${VERSION_TAG}" -m "Release ${VERSION_TAG}"
git push origin "${VERSION_TAG}"

13. Publish The Package

If package publication does not happen automatically, follow the PyPI Release Workflow.

14. Publish The Documentation

If documentation publication does not happen automatically, follow the Documentation Release Workflow.