Enforce a 95% combined coverage floor in CI and local runs.
Test Python Package / unit-tests (pull_request) Failing after 56s
Code Quality Pipeline / code-quality (pull_request) Successful in 1m36s
Test Python Package / integration-tests (pull_request) Failing after 1m14s
Test Python Package / coverage-report (pull_request) Has been skipped
PR Title Check / check-title (pull_request) Successful in 35s

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 <[email protected]>
This commit is contained in:
Brian Bjarke Jensen
2026-07-07 20:27:39 +02:00
co-authored by Cursor
parent e39fc96ac1
commit 5393efc6cd
3 changed files with 31 additions and 3 deletions
+15 -2
View File
@@ -112,8 +112,21 @@ jobs:
- name: Combine coverage report - name: Combine coverage report
run: | run: |
uv run coverage combine coverage-unit/.coverage coverage-integration/.coverage uv run coverage combine coverage-unit/.coverage coverage-integration/.coverage
uv run coverage report -m --include='python_repositories/*' > coverage.txt uv run coverage report -m --include='python_repositories/*' --fail-under=0 > coverage.txt
cat 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 - name: Post coverage summary to PR
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
+8 -1
View File
@@ -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. 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). `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).
+8
View File
@@ -39,6 +39,14 @@ markers = [
"integration: tests requiring Docker containers (deselect with '-m \"not integration\"')", "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] [tool.uv.sources]
python-utils = { index = "gitea" } python-utils = { index = "gitea" }