Skip to content

Maintenance & Quality

This page documents how gwmock is kept correct and healthy over time: the test suite, the automated dependency-management policies, and the release process — the information a user needs to judge whether they can depend on the package.

Testing and continuous integration

Every pull request and every push to main runs the full CI workflow:

  • Test matrix — the pytest suite (under tests/, mirroring the source layout) runs on Ubuntu and macOS across Python 3.12, 3.13, and 3.14.
  • Lowest-resolution job — one job installs every direct dependency at its minimum declared version (uv sync --resolution lowest-direct) on the oldest supported Python. This proves the version floors in pyproject.toml are real, not aspirational — a floor that breaks the test suite cannot ship.
  • Coverage — results are uploaded to Codecov on every run, so coverage changes are visible per pull request.

Static checks run alongside the tests:

  • pre-commit — formatting and lint hooks (including Ruff) run on every commit locally and are enforced on every pull request by pre-commit.ci.
  • CodeQL — GitHub's static security analysis runs on the repository.

To run the suite locally:

uv sync --group dev
uv run pytest

Dependency management

Dependency maintenance is deliberately split into two automated systems with disjoint responsibilities, so each version constraint has exactly one owner:

Version floors: the SPEC 0 policy

gwmock follows Scientific Python SPEC 0: support for a Python version is dropped 3 years (36 months) after its initial release, and support for a dependency's minor series 2 years (24 months) after its first stable release. SPEC 0 defines this window for the core scientific ecosystem (NumPy, SciPy, Astropy, …); gwmock applies the same 24-month window to all of its runtime dependencies, so its supported range stays compatible with the packages it builds on.

The policy is enforced mechanically, not by hand:

  • The policy is declared in pyproject.toml under [tool.dependency-support-policy] (policy = "spec0").
  • A scheduled workflow (support_floor_update.yml) runs monthly, recomputes the SPEC 0 floors, and opens an auto-merging pull request raising the lower bounds in pyproject.toml.
  • The CI lowest-resolution job (above) then verifies the package actually works at those floors before the pull request can merge.

A floor may sit above the SPEC 0 minimum when a feature requires it; such exceptions are annotated inline in pyproject.toml with the reason and the SPEC 0 floor they supersede.

The ecosystem sibling packages (gwmock-signal, gwmock-noise, gwmock-pop) are excluded from the SPEC 0 mechanism and are instead kept current by Renovate, since they evolve in lock-step with gwmock itself.

Everything else: Renovate

Renovate (configured in renovate.json, extending config:recommended and config:best-practices) automates all remaining dependency chores:

What Policy
Runtime patch & minor updates Grouped, auto-merged after a 3-day minimum release age, gated on CI
Runtime major updates Never automated — always require human review
Lock file (uv.lock) maintenance Refreshed weekly (Monday before 04:00 UTC), auto-merged
GitHub Actions Grouped weekly, pinned to commit digests, auto-merged after 3 days
pre-commit hooks Auto-merged

Every automated merge still has to pass the full CI matrix, including the lowest-resolution job. A Dependency Dashboard issue tracks all pending and blocked updates.

Releases

Releases are scheduled and automated rather than ad hoc:

  • Cadence — a release is cut every Tuesday at 00:00 UTC whenever new commits have landed since the previous release (scheduled_release.yml). Emergency bugfix releases can be triggered manually.
  • Versioning — versions are derived from git tags via uv-dynamic-versioning; there is no hand-edited version string. Pull request titles follow Conventional Commits (enforced by a PR-title check), which drives the version bump and the changelog.
  • Changelog — generated with git-cliff from the commit history. A rolling draft release on the GitHub Releases page always previews what the next release will contain.
  • Publishing — each release is published to PyPI (with TestPyPI used for release rehearsal) and archived on Zenodo with a citable DOI (10.5281/zenodo.17925458).

Where to look

Concern File / location
Test suite tests/
CI matrix .github/workflows/ci.yml
SPEC 0 policy pyproject.toml [tool.dependency-support-policy], .github/workflows/support_floor_update.yml
Renovate policy renovate.json
Release automation .github/workflows/scheduled_release.yml, draft_release.yml, publish.yml
Lint & format config .pre-commit-config.yaml, pyproject.toml (Ruff)
Contribution process Contributing