This document explains how to manage releases for the ECHR Extractor package using automated versioning.
The package now uses setuptools_scm for automatic version management based on Git tags. This eliminates the need to manually update version numbers in multiple files.
- Version Source: Versions are automatically generated from Git tags
- Tag Format: Use semantic versioning tags like
v1.0.45,v1.1.0,v2.0.0 - Automatic Generation: The version is generated at build time from the latest Git tag
- Development Versions: Uncommitted changes get a
.devsuffix
- Release Tag:
v1.0.45→ Version:1.0.45 - Development:
v1.0.45+ uncommitted changes → Version:1.0.46.dev0+gfc123e3.d20251008 - Pre-release:
v1.0.45+ 2 commits → Version:1.0.46.dev2+gfc123e3
When first adopting automated versioning, you need to create a baseline tag:
# Create a tag for the last released version
git tag v1.0.46 <commit-sha>
git push origin v1.0.46This establishes a version baseline for setuptools_scm to calculate subsequent versions from.
# Patch release (1.0.45 → 1.0.46)
python scripts/release.py patch
# Minor release (1.0.45 → 1.1.0)
python scripts/release.py minor
# Major release (1.0.45 → 2.0.0)
python scripts/release.py major
# Specific version
python scripts/release.py 1.2.3# 1. Ensure working directory is clean
git status
# 2. Create and push a tag
git tag -a v1.0.46 -m "Release 1.0.46"
git push origin v1.0.46
# 3. GitHub Actions will automatically:
# - Build the package
# - Upload to PyPI
# - Create a GitHub releaseThe CI/CD pipeline automatically:
- Detects new tags on the main branch
- Builds the package with the correct version
- Uploads to PyPI with the tag version
- Creates GitHub releases with the same version
- Signs packages with Sigstore for security
- Pull Requests: Run tests, linting, and build verification
- Main Branch Push: Run tests, linting, and build verification (no PyPI release)
- Tag Push: Full release pipeline (build, test, upload to PyPI, create release)
- Development: All jobs run on PRs and main branch pushes for testing
- Release: Only tagged commits trigger PyPI publishing and GitHub releases
- Artifacts: Build artifacts are only uploaded for tagged releases
- Version Display: Shows the version that would be built for debugging
# The version is automatically available in your package
from echr_extractor import __version__
print(__version__) # e.g., "1.0.45"
# Or using setuptools_scm directly
import setuptools_scm
version = setuptools_scm.get_version()# Check current version
python -c "import setuptools_scm; print(setuptools_scm.get_version())"
# Check what version would be built
python -c "import setuptools_scm; print(setuptools_scm.get_version(write_to='version.py'))"Follow Semantic Versioning principles:
- MAJOR (2.0.0): Breaking changes, incompatible API changes
- MINOR (1.1.0): New features, backward compatible
- PATCH (1.0.1): Bug fixes, backward compatible
- Bug Fix:
1.0.45→1.0.46(patch) - New Feature:
1.0.45→1.1.0(minor) - Breaking Change:
1.0.45→2.0.0(major)
[project]
name = "echr-extractor"
dynamic = ["version"] # Version is now dynamic
[tool.setuptools_scm]
write_to = "src/echr_extractor/_version.py" # Auto-generate version file- Automatically detects version from Git tags
- No more hardcoded version numbers
- Dynamic release naming
- Always tag from main branch: Tags should be created from the main branch
- Clean working directory: Ensure no uncommitted changes before tagging
- Test before release: Run tests locally before creating a release tag
- Changelog: Consider maintaining a CHANGELOG.md for release notes
- This is expected behavior for PR builds and commits that are not tagged
.devsuffix indicates a development version between releases- To get a clean version without
.dev:- Merge the PR to main
- Create and push a release tag:
git tag v1.0.47 && git push origin v1.0.47 - The tag push will trigger a build with version
1.0.47(no.dev)
- Important: Build artifacts are only uploaded for tagged releases (see CI/CD workflow)
- Ensure you're on the main branch
- Check that the tag was pushed:
git push origin v1.0.46 - Verify GitHub Actions ran successfully
- This is normal for uncommitted changes
- Create a proper release tag for stable versions
- Check that setuptools_scm is installed:
pip install setuptools_scm - Verify pyproject.toml configuration is correct
- Cause: setuptools_scm was generating versions with local identifiers (e.g.,
1.0.47+abc123) - Solution: The configuration now uses
local_scheme = "no-local-version"to prevent this - Prevention: Only build from clean, tagged commits (GitHub Actions now only runs on tags)
- Manual fix: Ensure working directory is clean before creating tags