Release Process¶
EpiModel follows Semantic Versioning (SemVer) for version numbering: MAJOR.MINOR.PATCH
Version Guidelines¶
MAJOR version (X.0.0)¶
Incremented for incompatible API changes:
- Breaking changes to public API
- Removal of deprecated features
- Major architectural changes affecting backwards compatibility
- Example: Changing method signatures, removing public methods
MINOR version (0.X.0)¶
Incremented for backwards-compatible new features:
- New functionality added
- New disease states, stratifications, or transition types
- Performance improvements without API changes
- Deprecation notices (without removal)
- Example: Adding new mathematical functions, new model types
PATCH version (0.0.X)¶
Incremented for backwards-compatible bug fixes:
- Bug fixes that don't change the API
- Documentation improvements
- Internal refactoring
- Security patches
- Example: Fixing calculation errors, typos in error messages
Release Workflow¶
Step 1: Prepare the Release¶
1.1 Update Version Numbers¶
Edit the following files:
py-epimodel/pyproject.toml- UpdateversionfieldCargo.toml- Update[workspace.package]version
# py-epimodel/pyproject.toml
[tool.poetry]
version = "1.2.3"
# Cargo.toml
[workspace.package]
version = "1.2.3"
1.2 Update CHANGELOG (if maintained)¶
Document all changes under the new version:
## [1.2.3] - 2024-12-15
### Added
- New mathematical functions for transition rates
- Support for multi-compartment transitions
### Changed
- Improved simulation performance by 20%
### Fixed
- Fixed population conservation bug in stratified models
- Corrected type hints in Simulation class
### Security
- Updated dependencies to patch vulnerabilities
1.3 Run Quality Checks¶
# Python checks
cd py-epimodel
poetry run ruff check .
poetry run ruff format .
poetry run mypy epimodel
poetry run pytest
# Rust checks
cd ..
cargo fmt --all
cargo clippy --all-targets --all-features
cargo test --workspace
1.4 Commit Version Changes¶
git add py-epimodel/pyproject.toml Cargo.toml CHANGELOG.md
git commit -m "chore: bump version to X.Y.Z"
git push origin main
Step 2: Create GitHub Release¶
2.1 Create Tag¶
2.2 Create GitHub Release¶
- Go to Releases page
- Click "Draft a new release"
- Select tag:
vX.Y.Z - Set release title:
Version X.Y.Z - Add release notes:
## What's New in X.Y.Z
### New Features
- Feature 1 description
- Feature 2 description
### Bug Fixes
- Fix 1 description
- Fix 2 description
### Documentation
- Documentation improvements
### Performance
- Performance improvements
## Breaking Changes (for major versions)
- List breaking changes
- Migration guide
## Installation
pip install epimodel==X.Y.Z
## Full Changelog
See [CHANGELOG.md](https://github.com/MUNQU/epimodel/blob/main/CHANGELOG.md)
- Click "Publish release"
Step 3: Automated PyPI Publication¶
Once the release is published, the GitHub Actions workflow automatically:
- Builds wheels for Linux, Windows, and macOS
- Creates source distribution (sdist)
- Publishes to PyPI using trusted publishing
Monitor progress:
- Go to Actions tab
- Watch the "Release to PyPI" workflow
Step 4: Verify the Release¶
4.1 Check PyPI¶
Verify the package appears at: https://pypi.org/project/epimodel/
4.2 Test Installation¶
# Create fresh virtual environment
python -m venv test_env
source test_env/bin/activate # or test_env\Scripts\activate on Windows
# Install the new version
pip install epimodel==X.Y.Z
# Verify it works
python -c "from epimodel import ModelBuilder; print('Success!')"
4.3 Test Functionality¶
from epimodel import ModelBuilder, Simulation
from epimodel.constants import ModelTypes
# Run a quick test
model = (
ModelBuilder(name="Test")
.add_disease_state(id="S", name="Susceptible")
.add_disease_state(id="I", name="Infected")
.add_disease_state(id="R", name="Recovered")
.add_parameter(id="beta", value=0.3)
.add_parameter(id="gamma", value=0.1)
.add_parameter(id="N", value=1000.0)
.add_transition(id="infection", source=["S"], target=["I"], rate="beta * S * I / N")
.add_transition(id="recovery", source=["I"], target=["R"], rate="gamma")
.set_initial_conditions(
population_size=1000,
disease_state_fractions=[
{"disease_state": "S", "fraction": 0.99},
{"disease_state": "I", "fraction": 0.01},
{"disease_state": "R", "fraction": 0.0}
]
)
.build(typology=ModelTypes.DIFFERENCE_EQUATIONS)
)
sim = Simulation(model)
results = sim.run(num_steps=100)
print(f"Final infected: {results['I'][-1]:.0f}")
Step 5: Sync Branches¶
Pre-release Versions¶
For testing before official release:
Alpha Releases¶
# Version: X.Y.Z-alpha.N
git tag -a v1.3.0-alpha.1 -m "Alpha release for testing"
git push origin v1.3.0-alpha.1
Beta Releases¶
# Version: X.Y.Z-beta.N
git tag -a v1.3.0-beta.1 -m "Beta release for testing"
git push origin v1.3.0-beta.1
Release Candidates¶
Important: Mark GitHub releases as "pre-release" to prevent automatic PyPI publication.
Version Support Policy¶
- Latest version: Fully supported with new features and bug fixes
- Older versions: No support, users encouraged to upgrade
PyPI Trusted Publishing Setup¶
To enable automated PyPI publishing, configure trusted publishing:
- Go to PyPI and log in
- Go to your project settings
- Navigate to "Publishing" section
- Add GitHub as a trusted publisher:
- Owner: MUNQU
- Repository: epimodel
- Workflow: release.yml
- Environment: pypi
This allows GitHub Actions to publish without API tokens.
Release Checklist¶
- [ ] Version updated in
pyproject.toml - [ ] Version updated in
Cargo.toml - [ ] CHANGELOG updated with all changes
- [ ] All tests passing locally
- [ ] Version committed and pushed to main
- [ ] Git tag created and pushed
- [ ] GitHub release created with notes
- [ ] CI/CD pipeline completed successfully
- [ ] Package verified on PyPI
- [ ] Installation tested in clean environment
- [ ] Main merged back to develop
- [ ] Release announced (if applicable)
Troubleshooting¶
PyPI Upload Fails¶
- Check GitHub Actions logs
- Verify trusted publishing is configured
- Ensure version number is unique (not already on PyPI)
- Check for artifact build errors
Wheel Build Fails¶
- Check that Rust code compiles on all platforms
- Verify maturin configuration is correct
- Check for platform-specific dependencies
Version Conflicts¶
- Ensure version is updated in all required files
- Use
git tag -d vX.Y.Zto delete incorrect tags locally - Use
git push origin :refs/tags/vX.Y.Zto delete remote tags