Skip to main content

Prerequisites

Before you start, make sure you have the following installed:
  • Python 3.12
  • uv package manager
  • Git
  • Modal account (for running integration tests remotely) or Apptainer (for local testing)

Setup

Clone the repository and set up your environment:
This installs all dependencies into a virtual environment managed by uv.

Running tests

Tests use pytest with pytest-xdist for parallel execution. Run the full test suite:
Running the full suite requires Modal credentials. Set the MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables before running.
Run tests for a specific model:
Specify a GPU type:

Code quality

Boileroom uses pre-commit hooks that run automatically when you commit. You can also run them manually:
The toolchain includes:
  • ruff for linting and formatting (line length: 120 characters)
  • mypy for type checking
All checks must pass before your PR can be merged.

PR process

  1. Create a branch from main (or the current development branch if one exists).
  2. Make focused changes. Prefer small, reviewable PRs over large ones.
  3. Ensure all CI checks pass (lint, format, tests).
  4. Bump the version in pyproject.toml. This is required by CI and your pipeline will fail without it.
  5. Write a PR description that explains what you changed and why.

Release and versioning

  • Docker image version tags follow project.version in pyproject.toml.
  • Runtime defaults also follow the installed boileroom package version unless you explicitly override the image tag.
  • Merging to main triggers the Docker image workflow, which builds a temporary sha-<commit> validation tag, verifies it, and then promotes it to the current package version on Docker Hub.
  • PyPI publication is separate and only happens when a GitHub release is published.
  • That means Docker Hub can be the earlier staged release channel, while PyPI remains the later Python package release step.
  • If you bump project.version, you are also changing the public versioned Docker tags that will be produced from main.

Project structure

Key conventions

  • Core algorithms are backend-agnostic. They must not import Modal, Apptainer, or any other backend-specific library.
  • Modal imports go at the top of wrapper files (they are needed at import time for decorators).
  • Apptainer imports are lazy (inside elif branches) to avoid requiring Apptainer as a dependency.
  • Output types are dataclasses defined in types.py.
  • Test reference data goes in tests/data/{model}/.

Further reading