Comments Python coverage on a pull request, marks the lines it added that never ran, and fails the build when too few of them are covered.
It runs on Node. There is no container to build, so the step starts straight away instead of pulling and building an image on every job.
- run: uv run pytest --cov
- run: uv run coverage json
- uses: simlab-vs/python-coverage-action@v1.0.0
with:
minimumPatchCoverage: 85Hand it the JSON that coverage json writes. Everything else has a default.
| Input | Required | Default | Description |
|---|---|---|---|
githubToken |
no | ${{ github.token }} |
Token used to read the diff and write the comment. |
coverageFile |
no | coverage.json |
Path to the JSON report written by coverage json. |
minimumPatchCoverage |
no | Fail when less than this percentage of the lines the pull request adds is covered. Blank asks for no gate. | |
minimumProjectCoverage |
no | Fail when project coverage is below this percentage. Blank asks for no gate. | |
annotateMissingLines |
no | true |
Mark added lines that never ran, so they show up on the diff. |
comment |
no | true |
Post the summary as a pull request comment, editing the previous one. |
| Output | Description |
|---|---|
projectCoverage |
Percentage of the project's statements that ran. |
patchCoverage |
Percentage of the lines the pull request adds that ran. Empty when it adds none. |
Patch coverage looks only at the lines coverage.py measured. Blank lines,
comments and docstrings are neither covered nor missing, so adding them moves
nothing. Files the report never mentions are skipped, which is how tests,
configuration and anything under omit stay out of the number.
Plenty of pull requests add no measurable line at all. Those get an empty
patchCoverage and pass the gate. Failing a build over a percentage that does
not exist helps nobody.
permissions:
contents: read
pull-requests: write # only for the commentReading the diff needs nothing beyond the default token. Drop
pull-requests: write if you set comment: false.
Coverage actions tend to ship as containers, which means the runner builds a Docker image before the step can even start. On a self-hosted runner with a throwaway image store there is no layer cache to help, so that base image gets pulled again on every single job. This action does the few things one project actually used out of that: a comment, annotations, and a patch coverage gate.
The idea comes from py-cov-action/python-coverage-comment-action by Joachim Jablon and its contributors, which is what this repository replaced and what taught it what a coverage comment should say. That action does considerably more: a coverage badge, an HTML dashboard, stored history. If you want any of that, reach for it instead. No code was copied here, and both are MIT licensed. Thanks for the original.