From 5393efc6cd53d45ebfa0706cd4c5bf8fbed5db7f Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Tue, 7 Jul 2026 20:27:39 +0200 Subject: [PATCH] Enforce a 95% combined coverage floor in CI and local runs. Configure fail_under in pyproject.toml and read it in the coverage-report workflow so the threshold stays in one place. Co-authored-by: Cursor --- .gitea/workflows/test.yml | 17 +++++++++++++++-- README.md | 9 ++++++++- pyproject.toml | 8 ++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index e57424b..371a1d7 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -112,8 +112,21 @@ jobs: - name: Combine coverage report run: | uv run coverage combine coverage-unit/.coverage coverage-integration/.coverage - uv run coverage report -m --include='python_repositories/*' > coverage.txt - cat coverage.txt + uv run coverage report -m --include='python_repositories/*' --fail-under=0 > coverage.txt + + - name: Show coverage report + run: cat coverage.txt + + - name: Enforce coverage floor + run: | + FAIL_UNDER=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['tool']['coverage']['report']['fail_under'])") + echo "Checking combined coverage against ${FAIL_UNDER}% floor..." + if uv run coverage report --fail-under="$FAIL_UNDER" --include='python_repositories/*'; then + echo "Coverage floor met." + else + echo "::error::Combined coverage is below the ${FAIL_UNDER}% floor" + exit 1 + fi - name: Post coverage summary to PR if: github.event_name == 'pull_request' diff --git a/README.md b/README.md index cb93dff..a38bf1d 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,14 @@ uv run pytest -v # full suite (requires Doc Integration tests are marked with `@pytest.mark.integration` and require Docker (testcontainers). Run unit tests alone for quick local feedback. -CI runs unit and integration tests in parallel with coverage, then merges `.coverage` artifacts in a follow-up job (via [christopherhx/gitea-\*-artifact@v4](https://github.com/christopherHX/gitea-upload-artifact) for Gitea 1.26 compatibility). +CI runs unit and integration tests in parallel with coverage, then merges `.coverage` artifacts in a follow-up job (via [christopherhx/gitea-\*-artifact@v4](https://github.com/christopherHX/gitea-upload-artifact) for Gitea 1.26 compatibility). Combined coverage must be at least **95%**; the floor is set by [`fail_under` in `pyproject.toml`](pyproject.toml#L45-L48) and enforced after merging unit and integration coverage, not on unit-only runs. + +To check coverage locally (requires Docker for the full suite): + +```bash +uv run pytest --cov=python_repositories --cov-report= +uv run coverage report +``` `pre-commit` is included in the dev dependency group. `uv sync` installs the CLI, but git does not run hooks until you install them with `pre-commit install` (one time per clone). After that, commits run the checks defined in [`.pre-commit-config.yaml`](.pre-commit-config.yaml) (ruff, mypy, pyupgrade, prettier, and general file hygiene). diff --git a/pyproject.toml b/pyproject.toml index 8735bd0..27359f9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,14 @@ markers = [ "integration: tests requiring Docker containers (deselect with '-m \"not integration\"')", ] +[tool.coverage.run] +source = ["python_repositories"] + +[tool.coverage.report] +fail_under = 95 +show_missing = true +precision = 2 + [tool.uv.sources] python-utils = { index = "gitea" }