Skip to content

Releasing

How to cut a release for an OpsDev.nz module. All modules follow the same process — automated, reproducible, and gated through Test PyPI.

Conventions

What Rule
Versioning Semantic VersioningMAJOR.MINOR.PATCH
Tag format v<version> (e.g. v0.1.0, v1.2.3)
Branch main only — tags must point at a commit on main
Trigger Push of a v* tag fires the publish workflow
Auth Trusted Publishing (OIDC) — no API tokens

Release Checklist

1. Prepare the release

On a branch off main:

# Bump version in pyproject.toml
version = "0.1.0"

# Add a changelog entry under [Unreleased], move to new [0.1.0] section

See Keep a Changelog for format.

2. Merge to main

Create a PR, get it reviewed, merge to main.

3. Tag and push

git checkout main
git pull origin main
git tag -s v0.1.0 -m "v0.1.0: first public release"
git push origin v0.1.0

Use -s to sign the tag with your GPG or SSH key.

4. Watch the pipeline

The push triggers .github/workflows/publish.yml. The pipeline runs two jobs:

Job What it does
test-pypi Builds wheel, publishes to Test PyPI, installs from Test PyPI in a clean venv, runs <module> --version as a smoke test
pypi Runs only if test-pypi passes. Builds wheel, publishes to real PyPI

If the Test PyPI publish or smoke test fails, the real PyPI publish is aborted. Fix the issue, bump the patch version, and tag again.

5. Verify

pip install <module>==0.1.0
<module> --version

Module-specific setup

Each module documents its own Trusted Publishing setup in modules/<module>/docs/release-process.md. This includes:

  • Which GitHub environments are configured (test-pypi, pypi)
  • Links to the PyPI project pages for Trusted Publisher configuration
  • Module-specific smoke test expectations

Dry-run releases

To validate the pipeline without publishing to real PyPI, temporarily comment out the pypi job in the publish workflow, tag and push, then restore it after confirming the Test PyPI job succeeds.