Development Workflow¶
Development Setup¶
EpiModel is built with Rust and Python. To set up your development environment:
1. Install Prerequisites¶
# Install Rust toolchain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install Python 3.11 or higher
# (use your system's package manager)
# Install Poetry
curl -sSL https://install.python-poetry.org | python3 -
2. Clone and Setup¶
git clone https://github.com/MUNQU/epimodel.git
cd epimodel
# Install Python dependencies
cd py-epimodel
poetry install --with dev
# Install pre-commit hooks (optional but recommended)
poetry run pre-commit install
3. Build the Project¶
# Build Rust workspace
cargo build --workspace
# Build Python extension
cd py-epimodel
maturin develop --release
Branching Strategy¶
We use a simplified Git Flow approach:
main: Production-ready code. Protected branch.develop: Integration branch for features. Used for staging releases.feature/*: New features, refactoring, or significant changes (e.g.,feature/add-stochastic-model)fix/*: Bug fixes (e.g.,fix/calculation-error)docs/*: Documentation-only changes (e.g.,docs/update-api-reference)test/*: Test additions or improvements (e.g.,test/add-sir-model-tests)chore/*: Maintenance tasks, dependencies (e.g.,chore/update-dependencies)
Development Process¶
1. Starting New Work¶
# Always start from the latest develop branch
git checkout develop
git pull origin develop
# Create a feature branch
git checkout -b feature/your-feature-name
2. Making Changes¶
# Make your changes to the code
# Run quality checks before committing
cd py-epimodel
poetry run ruff check . --fix # Auto-fix Python linting issues
poetry run ruff format . # Format Python code
poetry run mypy epimodel # Type checking
cd ..
cargo fmt --all # Format Rust code
cargo clippy --all-targets --fix # Fix Rust linting issues
3. Testing Your Changes¶
# Run Python tests
cd py-epimodel
poetry run pytest -v
# Run Rust tests
cd ..
cargo test --workspace
4. Committing Changes¶
We follow Conventional Commits for commit messages:
# Commit format: <type>(<scope>): <description>
git add .
git commit -m "feat(transitions): add support for time-varying rates"
git commit -m "fix(simulation): correct population calculation"
git commit -m "docs(readme): update installation instructions"
git commit -m "test(models): add tests for stratified models"
Commit Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Code style changes (formatting)refactor: Code refactoringtest: Adding or updating testschore: Maintenance tasks, dependenciesperf: Performance improvementsci: CI/CD changesbuild: Build system changes
Branch vs Commit Type:
The branch name indicates the primary purpose of the work, while commit types describe individual changes:
- A
feature/refactor-apibranch may haverefactor,test, anddocscommits - A
test/*branch primarily adds tests but may havefixcommits too - A
docs/*branch is documentation-only, so all commits should usedocstype
5. Pushing and Creating Pull Requests¶
# Push your branch
git push origin feature/your-feature-name
# Create a Pull Request on GitHub
# - Target the 'develop' branch
# - Fill in the PR template with:
# - Description of changes
# - Related issues
# - Testing performed
# - Screenshots (if UI changes)
6. Code Review and CI¶
When you create a PR, automated checks run:
- Code Quality Pipeline: Linting, formatting, type checking for both Python and Rust
- Build Pipeline: Builds on Ubuntu, Windows, and macOS with Python versions
- Test Coverage: Runs all tests and reports coverage
PR Requirements:
- All CI checks must pass
- At least one approving review
- No merge conflicts with target branch
- Code coverage should be >95%
7. Merging to Develop¶
Once approved:
# Merge using "Squash and merge" or "Rebase and merge" on GitHub
# Delete the feature branch after merging
Continuous Integration Pipelines¶
The project uses three main CI/CD pipelines:
1. Code Quality (on every push/PR)¶
- Python: Ruff (linting/formatting), MyPy (type checking), Pytest (testing)
- Rust: rustfmt (formatting), Clippy (linting), cargo test
- Runs on: Ubuntu
- Purpose: Ensure code quality standards
2. Build (on every push/PR)¶
- Builds on: Ubuntu, Windows, macOS
- Python versions: 3.11, 3.12
- Tests: Full test suite on all platforms
- Artifacts: Wheel files for each platform
- Purpose: Ensure cross-platform compatibility
3. Release (on GitHub release)¶
- Builds wheels for all platforms
- Creates source distribution
- Publishes to PyPI using trusted publishing
- Purpose: Automated deployment
Local Development Tips¶
Quick Commands¶
# Run all quality checks (Python)
cd py-epimodel && poetry run ruff check . && poetry run ruff format . && poetry run mypy epimodel && poetry run pytest
# Run all quality checks (Rust)
cargo fmt --all && cargo clippy --all-targets && cargo test --workspace
# Build and test the Python package locally
cd py-epimodel
maturin develop --release
poetry run pytest
Pre-commit Hooks¶
Install pre-commit hooks to automatically check code before committing:
This runs:
- Ruff linting and formatting
- MyPy type checking
- Trailing whitespace removal
- End-of-file fixing
- Poetry lock file validation
- Ensures
poetry.lockstays in sync withpyproject.toml
Keeping poetry.lock in Sync¶
Important: Always ensure poetry.lock is synchronized with pyproject.toml before committing.
Automatic (Recommended)¶
Pre-commit hooks handle this automatically:
cd py-epimodel
poetry run pre-commit install # One-time setup
# Now git commit automatically updates poetry.lock if needed
git add pyproject.toml
git commit -m "chore: update dependencies"
Manual¶
If not using pre-commit hooks:
cd py-epimodel
poetry check # Check if lock file is in sync
poetry lock # Update lock file without changing versions
git add poetry.lock
git commit -m "chore: update poetry.lock"
Why this matters: Out-of-sync lock files cause CI/CD pipeline failures. The pre-commit hook prevents this automatically.
Debugging Rust from Python¶
# Build with debug symbols
maturin develop
# Run Python
cd py-epimodel
poetry run python -m your_test_script.py
Building Documentation¶
The project uses MkDocs Material for documentation:
# Install documentation dependencies
cd py-epimodel
poetry install --with docs
# Serve documentation locally
poetry run mkdocs serve
# Build documentation
poetry run mkdocs build
Visit http://127.0.0.1:8000 to view the documentation locally.
Next Steps¶
- Contributing Guidelines - Best practices for contributions
- Release Process - How releases are managed