Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

coverage-summary-action

Renders a coverage report into a GitHub Actions job summary, and optionally uploads the report as an artifact.

Reads Cobertura XML (coverage.py, pytest-cov) or istanbul coverage-summary.json (jest, vitest), plus optional JUnit XML or jest/vitest JSON test results for a pass/fail table.

This lives in a public repo for one reason: a public repository cannot resolve an action from a private one. Runpod consumes this from both public and private repos, so it has to be here.

Usage

- name: Coverage summary
  if: always()
  uses: runpod/coverage-summary-action@<full-commit-sha>
  with:
    format: cobertura
    coverage-file: coverage.xml
    results: pytest-results.xml
    artifact-name: coverage

Pin a full commit SHA, not a tag. A tag can be repointed at new code by whoever owns it; a SHA cannot. It also means a change here cannot reach your CI until someone bumps the pin deliberately.

Inputs

Input Required Default Description
format yes cobertura or json-summary
coverage-file yes Coverage report path, relative to working-directory
results no Test results for the pass/fail table. Cobertura takes a space-separated list of JUnit XML globs; json-summary takes a jest/vitest JSON file
artifact-name no Artifact name for the uploaded report. Empty skips the upload entirely
artifact-path no coverage-file What to upload, when it differs from the file being summarised
overwrite no true Replace an existing artifact of the same name rather than failing
if-no-files-found no warn warn or error
working-directory no . Directory the paths above are relative to
title no Coverage Report Heading for the summary section
max-rows no 300 Cap on per-file rows, to stay under GitHub's 1 MiB summary limit

Design rules

The script follows three rules, and the test suite exists to hold it to them:

  1. Never raise. It is meant to run under if: always(), so throwing here would stack a second, misleading failure on top of whatever actually went wrong. Every parse path degrades to a message instead.
  2. Never claim a pass without evidence. A suite that dies at import reports zero failures. Status is computed from positive evidence — something ran, nothing failed, every requested report was found and parsed — so a crashed run renders as ⚠️ Unknown, not ✅ Passed.
  3. Say when a report was unreadable. A missing file and a corrupt file are reported differently, because they mean different things.

Line coverage goes in the job summary headline; statement, function and branch figures go in the body table. A metric with a zero denominator is omitted rather than shown as 0%.

Notes on correctness

  • lcov totals are unioned, not summed. Adding per-file LF/LH records across sharded reports double-counts the denominator — a sharded suite that is genuinely at 100% reads as 50%. Line hits are merged by (file, line) first.
  • Secondary metrics are only reported from a single artifact. Function and branch counts cannot be unioned from summary records, so they are skipped rather than approximated when more than one report is present.

Development

The script is stdlib-only, so there is nothing to install:

python3 -m unittest discover -p 'test_*.py' -v

59 unit tests, plus a smoke job that drives the action end to end — including a truncated report, a missing report, an unreadable results file, and a consumer whose paths sit in a subdirectory.

The script is a real file rather than an inline heredoc specifically so it can be linted, reviewed and tested. Four crash paths survived the heredoc era because none of that was possible.

License

MIT

About

GitHub Action that renders a coverage report into a job summary and optionally uploads it as an artifact. Reads Cobertura XML (coverage.py, pytest-cov) and istanbul coverage-summary.json (jest, vitest). Stdlib-only, no install step.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages