This document describes the release process for pygenfsm maintainers.
Before releasing, ensure you have:
- Commit access to the main repository
- PyPI account with maintainer access to pygenfsm
- TestPyPI account for testing releases
- uv package manager installed (
curl -LsSf https://astral.sh/uv/install.sh | sh) - GitHub CLI installed (optional, for creating releases manually)
Before creating a release, ensure:
- All tests pass:
uv run pytest - Type checking passes:
uv run pyright - Code is formatted:
uv run ruff format . - Linting passes:
uv run ruff check . - CHANGELOG.md is updated with release notes
- Documentation is up to date
- Dependencies are locked:
uv lock
pygenfsm follows Semantic Versioning with the format: MAJOR.MINOR.PATCH
- MAJOR: Breaking API changes
- MINOR: New features, backwards compatible
- PATCH: Bug fixes, backwards compatible
Pre-release versions:
- Alpha:
X.Y.ZaN(early testing) - Beta:
X.Y.ZbN(feature complete, testing) - Release Candidate:
X.Y.ZrcN(final testing)
For testing and early feedback:
# Update version in pyproject.toml
# For alpha: 0.2.0a1
# For beta: 0.2.0b1
# For RC: 0.2.0rc1
# Commit changes
git add pyproject.toml uv.lock CHANGELOG.md
git commit -m "release: bump version to 0.2.0a1"
git push
# Create and push tag (triggers GitHub Actions)
git tag v0.2.0a1
git push origin v0.2.0a1The GitHub Actions workflow will automatically:
- Build the package
- Run tests on Python 3.11 and 3.12
- Publish to TestPyPI
- Create a GitHub pre-release
For stable releases:
# Update version in pyproject.toml to stable version (e.g., 0.2.0)
# Update CHANGELOG.md
# Document all changes since last release
# Commit changes
git add pyproject.toml uv.lock CHANGELOG.md
git commit -m "release: bump version to 0.2.0"
git push
# Create and push tag (triggers GitHub Actions)
git tag v0.2.0
git push origin v0.2.0The GitHub Actions workflow will automatically:
- Build the package
- Run comprehensive tests
- Publish to PyPI
- Create a GitHub release with artifacts
If GitHub Actions is unavailable, you can release manually:
# Clean previous builds
rm -rf dist/
# Build the package
uv build
# Verify the build
ls -la dist/
# Should contain:
# - pygenfsm-X.Y.Z-py3-none-any.whl
# - pygenfsm-X.Y.Z.tar.gz# Create test environment
uv venv test-env
source test-env/bin/activate # On Windows: test-env\Scripts\activate
# Install from wheel
uv pip install dist/pygenfsm-*.whl
# Test import
python -c "from pygenfsm import FSM; print('Success!')"
# Deactivate test environment
deactivate
rm -rf test-env# Set TestPyPI credentials
export UV_PUBLISH_USERNAME="__token__"
export UV_PUBLISH_PASSWORD="your-testpypi-token"
# Upload to TestPyPI
uv publish --publish-url https://test.pypi.org/legacy/
# Test installation from TestPyPI
uv pip install --index-url https://test.pypi.org/simple/ pygenfsm==X.Y.Z# Set PyPI credentials
export UV_PUBLISH_USERNAME="__token__"
export UV_PUBLISH_PASSWORD="your-pypi-token"
# Upload to PyPI (ONLY for stable releases)
uv publish
# Verify installation
uv pip install pygenfsm==X.Y.ZAfter a successful release:
-
Create GitHub Release (if not auto-created):
gh release create v0.2.0 \ --title "v0.2.0" \ --notes "Release notes here" \ --prerelease # Only for alpha/beta
-
Announce the Release:
- Update README.md if needed
- Post to relevant channels/forums
- Update documentation site
-
Prepare for Next Development:
# Bump to next development version # Update version in pyproject.toml to next alpha (e.g., 0.3.0a0) git add pyproject.toml uv.lock git commit -m "chore: bump version for development" git push
If you get "version already exists" error:
- Check PyPI/TestPyPI for existing version
- Bump to a new version number
- Ensure you're not re-using version numbers
Check the Actions tab for detailed logs:
- Go to https://github.com/serialx/pygenfsm/actions
- Click on the failed workflow run
- Review logs for each job
Common issues:
- Test failures: Fix tests before releasing
- Token issues: Verify PyPI tokens in repository secrets
- Build issues: Test build locally with
uv build
- Verify package metadata in
pyproject.toml - Check that all required files are included
- Test local installation:
uv pip install dist/*.whl - Check PyPI page for package details
If a bad release is published:
- Cannot delete from PyPI - versions are immutable
- Yank the release on PyPI (marks as broken)
- Release a patch version with fixes immediately
- Update documentation to skip the bad version
- Go to your repository Settings → Secrets and variables → Actions
- Add the following secrets:
PYPI_API_TOKEN: Your PyPI API tokenTESTPYPI_API_TOKEN: Your TestPyPI API token (optional)
- Go to https://test.pypi.org/manage/account/token/
- Create token named "pygenfsm-github-actions"
- Copy the token (starts with
pypi-)
- Go to https://pypi.org/manage/account/token/
- Create token named "pygenfsm-github-actions"
- Copy the token (starts with
pypi-)
# Check current version
grep version pyproject.toml
# Run all quality checks
uv run ruff format . && uv run ruff check . && uv run pyright . && uv run pytest
# Build package
uv build
# Create and push tag
git tag v$(grep version pyproject.toml | cut -d'"' -f2)
git push origin v$(grep version pyproject.toml | cut -d'"' -f2)