Release Process
This document formalizes the release process for Moltres.
Release Checklist
Pre-Release
[ ] All tests pass (
pytest -n 10or your usual matrix)[ ] Type checking passes (
mypy src moltres-core/src)[ ] Linting passes (
ruff check src docs/examples tests moltres-core/srcandruff format --check …)[ ] Documentation is reviewed and updated
[ ] CHANGELOG.md is updated with all changes
[ ] Version number is bumped in
pyproject.toml,moltres-core/pyproject.toml,src/moltres/__init__.py, andmoltres-core/src/moltres_core/__init__.py(all must match the release tag)[ ] Dependencies are reviewed for security issues
[ ] Performance benchmarks are within acceptable ranges
[ ] Breaking changes are documented
[ ] Migration guide is updated (if needed)
Release Steps
Update Version
# Root package # pyproject.toml → version = "X.Y.Z" # src/moltres/__init__.py → __version__ = "X.Y.Z" # Companion core (must match for major releases) # moltres-core/pyproject.toml → version = "X.Y.Z" # moltres-core/src/moltres_core/__init__.py → __version__ = "X.Y.Z"
Update CHANGELOG.md
Move “Unreleased” changes to new version section
Add release date
Categorize changes (Added, Changed, Fixed, Removed, Security). Call out Breaking for major releases.
Commit Changes
git add pyproject.toml moltres-core/pyproject.toml src/moltres/__init__.py moltres-core/src/moltres_core/__init__.py CHANGELOG.md git commit -m "Release X.Y.Z"
Create Tag
git tag vX.Y.Z git push origin main git push origin vX.Y.Z
Publish (automated)
Pushingv*runs.github/workflows/release.yml, which verifies both package versions match the tag, builds moltres-core and moltres, and uploads to PyPI (secretPYPI_API_TOKEN). Publishmoltres-corefirst is required for fresh installs; the workflow does this beforemoltres.Build locally (optional check)
(cd moltres-core && python -m build) python -m build
Test Installation
pip install dist/moltres_core-*.whl dist/moltres-*.whl python -c "import moltres, moltres_core; print(moltres.__version__, moltres_core.__version__)"
Upload to PyPI (manual fallback)
twine upload moltres-core/dist/* twine upload dist/*
Create GitHub Release
Go to GitHub Releases
Create new release from tag vX.Y.Z
Copy relevant CHANGELOG.md section
Publish release
Verify Release
pip install --upgrade moltres
python -c "import moltres; print(moltres.__version__)"
Post-Release
[ ] Monitor PyPI download statistics
[ ] Monitor GitHub issues for release-related problems
[ ] Update documentation if needed
[ ] Announce release (if applicable)
Version Numbering
Follow Semantic Versioning:
MAJOR (X.0.0): Breaking changes
MINOR (0.X.0): New features (backward compatible)
PATCH (0.0.X): Bug fixes (backward compatible)
Examples
0.11.0→0.11.1: Patch release (bug fix)0.11.0→0.12.0: Minor release (new feature)0.11.0→1.0.0: Major release (breaking change)
Release Types
Patch Release (X.Y.Z → X.Y.Z+1)
When: Bug fixes, security patches, documentation updates
Process:
Create branch from main:
git checkout -b release/X.Y.Z+1Make fixes
Update version and CHANGELOG
Merge to main
Tag and release
Minor Release (X.Y.Z → X.Y+1.0)
When: New features, backward-compatible changes
Process:
Create branch from main:
git checkout -b release/X.Y+1.0Add features
Update version and CHANGELOG
Merge to main
Tag and release
Major Release (X.Y.Z → X+1.0.0)
When: Breaking changes
Process:
Create branch from main:
git checkout -b release/X+1.0.0Make breaking changes
Update version and CHANGELOG
Create migration guide
Merge to main
Tag and release
Announce breaking changes
Release Criteria
Must Have
All tests pass
No critical bugs
Documentation is up to date
CHANGELOG is updated
Should Have
Performance benchmarks pass
Security scan passes
Dependencies are up to date
Nice to Have
New features have examples
Migration guides for breaking changes
Performance improvements documented
Rollback Procedure
If a release has critical issues:
Identify Issue
Document the problem
Determine severity
Decide on Rollback
Critical bug affecting many users → Rollback
Minor issue → Hotfix release
Rollback Steps
# Remove PyPI release (if possible) # Note: PyPI doesn't allow deletion, but can yank twine upload --skip-existing --repository pypi dist/* # Create hotfix release git checkout -b hotfix/X.Y.Z+1 # Fix issue git commit -m "Hotfix: Fix critical issue" git tag vX.Y.Z+1 git push origin hotfix/X.Y.Z+1 git push origin vX.Y.Z+1
Communicate
Update GitHub release notes
Notify users if needed
Document issue and fix
Automation
GitHub Actions
The CI workflow automatically:
Runs tests on all supported platforms
Checks code quality
Validates documentation
Release Automation (Future)
Potential automation:
Automatic version bumping
Automatic CHANGELOG generation
Automatic PyPI upload on tag
Automatic GitHub release creation
Release Notes Template
## [X.Y.Z] - YYYY-MM-DD
### Added
- New feature 1
- New feature 2
### Changed
- Changed behavior 1
- Changed behavior 2
### Fixed
- Bug fix 1
- Bug fix 2
### Removed
- Removed feature 1 (if any)
### Security
- Security fix 1 (if any)
Approval Process
Patch Release
Self-approval for maintainers
Quick review for non-maintainers
Minor Release
Review by at least one other maintainer
All tests must pass
Major Release
Review by all maintainers
Discussion of breaking changes
Migration guide required
Communication
Release Announcements
GitHub Release: Always create
Twitter/X: For major releases
Blog Post: For major releases or significant features
Email: For security releases (if applicable)
Release Channels
PyPI: Primary distribution channel
GitHub Releases: Release notes and downloads
Documentation: Update docs site (if applicable)
Emergency Releases
For critical security issues:
Immediate Action
Create security branch
Fix issue
Test thoroughly
Release immediately
Communication
Security advisory on GitHub
Email to users (if applicable)
Update documentation
Follow-up
Post-mortem (if needed)
Prevent similar issues