| name | release-flow |
| description | Release pipeline patterns — python-semantic-release with conventional commits, PyPI trusted publishing, Docker multi-arch builds with GHCR, GitHub Actions workflows, and version tagging strategy |
Pipeline Overview
Conventional Commits → semantic-release → Tag + Changelog
→ PyPI publish (trusted publishing)
→ Docker build + push (GHCR)
→ GitHub Release with assets
Conventional Commits → Version Bumps
| Prefix | Bump | Example |
|---|
fix: | PATCH | fix(parser): handle empty YAML blocks |
feat: | MINOR | feat(cli): add --json output flag |
feat!: or BREAKING CHANGE: | MAJOR | feat!: restructure artifact schema |
docs:, chore:, refactor:, test: | No bump | docs: update README |
python-semantic-release
Config in pyproject.toml:
[tool.semantic_release]
version_toml = ["pyproject.toml:project.version"]
branch = "main"
commit_message = "chore(release): {version}"
build_command = "uv build"
[tool.semantic_release.changelog]
changelog_file = "CHANGELOG.md"
[tool.semantic_release.remote]
type = "github"
GitHub Actions Release Workflow
Three-job pipeline (release → publish-pypi → publish-docker):
Job 1: Release (version bump + tag)
python-semantic-release/python-semantic-release@v10
- Needs:
contents: write, id-token: write
- Uses
RELEASE_TOKEN (PAT) for pushing tags
- Outputs:
released, version, tag
Job 2: PyPI (trusted publishing)
- Triggered by
needs.release.outputs.released == 'true'
pypa/gh-action-pypi-publish@release/v1
- Uses
id-token: write for OIDC trusted publishing (no API keys)
- Environment:
pypi (configured in repo settings with PyPI project URL)
Job 3: Docker (multi-arch GHCR)
- Checks out at the release tag
- Multi-platform:
linux/amd64,linux/arm64
- Tags:
latest, vX.Y.Z, vX.Y, vX
- Uses GHA cache for layer caching
- Generates build provenance attestation
PyPI Trusted Publishing Setup
- PyPI project settings → "Add a new publisher"
- Set: GitHub owner, repo name, workflow filename, environment name (
pypi)
- No API keys needed — OIDC token from GitHub Actions
Docker Tagging Strategy
For version 3.2.1:
ghcr.io/owner/repo:latest # Rolling latest
ghcr.io/owner/repo:v3.2.1 # Exact version
ghcr.io/owner/repo:v3.2 # Minor (for compat pinning)
ghcr.io/owner/repo:v3 # Major
Version Bump in pyproject.toml
semantic-release handles this automatically. The version in pyproject.toml is the single source of truth. Never edit manually.
Manual/Emergency Release
gh workflow run release.yml -f force=patch
Pre-Release Checklist
- All CI green on main
- Conventional commits since last release
- CHANGELOG reviewed (auto-generated but verify)
- Docker build tested locally:
docker build -t test .
- No uncommitted changes on main