Release Workflow
April 28, 2026 ยท View on GitHub
Goal
This page describes how to prepare and publish a CANarchy release, with TestPyPI recommended before the first real PyPI publication and for any release workflow changes.
Prerequisites
Before publishing, confirm:
- package metadata in
pyproject.tomlis complete and correct src/canarchy/__init__.pycontains the intended release versionCHANGELOG.mdhas anUnreleasedsection and the upcoming release is summarized clearlyREADME.mdrenders correctly as the long project description
Publishing credentials:
- preferred: PyPI trusted publishing via GitHub Actions OIDC
- fallback: a scoped PyPI API token stored as a GitHub Actions secret
For the first public release, use TestPyPI first.
Recommended Release Order
- Update version metadata in
src/canarchy/__init__.py. - Move relevant entries from
CHANGELOG.mdUnreleasedinto a new versioned release section. - Commit the release preparation changes.
- Tag the release with
vX.Y.Z. - Build and verify artifacts locally from the release version.
- Publish to TestPyPI first if this is the first release or if the release workflow changed.
- Publish to PyPI from the same release version or tag.
- Create the GitHub release notes from the full versioned changelog section for
X.Y.Z; do not summarize or shorten the release notes. - After the release is cut and the release artifacts are published, advance
src/canarchy/__init__.pyonmainto the next development version in a follow-up commit.
Development Version Naming
After cutting release X.Y.Z, main shall advance to X.Y.(Z+1).dev0 in the follow-up commit that reopens development after the release artifacts are built and published, unless a different next-version target is explicitly planned and documented before or as part of the release.
Examples:
- after
0.4.0, setsrc/canarchy/__init__.pyto0.4.1.dev0 - after
1.2.3, setsrc/canarchy/__init__.pyto1.2.4.dev0
Rules:
- keep release tags on the stable version only, such as
v0.4.0 - keep unreleased work on
mainon a.devNversion string - build and publish release artifacts from the stable release version, not from the post-release
.dev0version - update the version metadata in the same commit or immediate follow-up commit that reopens development on
mainafter the release artifacts are published - if the next planned release target is a minor or major bump instead of the next patch version, document that decision explicitly and set the
.dev0version accordingly
Local Verification
Build artifacts:
uv build
Check package metadata rendering:
uvx twine check dist/*
Verify the wheel installs and the entry point works:
tmpdir=$(mktemp -d)
uv venv "$tmpdir/.venv"
uv pip install --python "$tmpdir/.venv/bin/python" dist/*.whl
"$tmpdir/.venv/bin/canarchy" --version
Recommended additional checks:
uv run pytest
uv run --group docs mkdocs build --strict
TestPyPI First-Publish Flow
Recommended for the first public release:
- Publish the built artifacts to TestPyPI.
- Create a clean virtual environment.
- Install from TestPyPI.
- Verify
canarchy --versionand a small representative command such ascanarchy config show --json. - Only then publish the same release to PyPI.
GitHub Actions Publish Workflow
The repository includes a manual GitHub Actions workflow at .github/workflows/publish.yml.
How to use it:
- Open the
publishworkflow in GitHub Actions. - Run it manually with
repository=testpypifor the first dry run. - Verify the published package from TestPyPI.
- Run it again with
repository=pypifor the real publication.
Workflow behavior:
- builds sdist and wheel artifacts with
uv build - runs
twine checkbefore any upload - publishes to separate GitHub environments for
testpypiandpypi - is structured for PyPI trusted publishing via GitHub OIDC
Trusted Publishing
Preferred long-term setup:
- configure a PyPI project for CANarchy
- enable trusted publishing from the GitHub repository
- restrict publication to the intended release workflow and branch/tag conditions
If trusted publishing is not ready yet, use an API token with the narrowest possible scope and store it only in GitHub Actions secrets.
Notes
- Release tags should match the package version exactly, prefixed with
v. - GitHub release notes should use the complete text from the matching
CHANGELOG.mdversion section verbatim. - If the release introduces breaking CLI or output-contract changes, bump the major version according to the documented SemVer policy.
- If publication metadata or workflow changes, repeat the TestPyPI path before the next real PyPI release.