Get started with coverage

Connect a repository, upload your first report, and see which changed lines need tests.

You’ll need access to install a GitHub App and edit your CI workflow. Supported reports: LCOV, Cobertura XML and JaCoCo XML.

On this page

1. Connect your repository

  1. Install the GitHub App for your account or organization and select the repositories to connect. Organization restrictions may require an administrator.
  2. Sign in, open the organization or repository settings, and copy its upload token. Store it in GitHub Actions secrets as COVERAGE_UPLOAD_TOKEN. Use a repository token for a single project; an organization token can serve multiple projects.

2. Generate and upload a report

Choose your test stack for report-generation commands and a working upload example.

Keep report paths relative to the checkout and upload coverage for the tested commit. Run the workflow on the default branch as well as pull requests so project checks have a matching-format baseline.

Upload from GitHub Actions

Copy an organization or repository upload token from the app and save it in your CI provider as COVERAGE_UPLOAD_TOKEN.

The reusable 9to5 coverage Action uses the default upload endpoint automatically. Set endpoint only when you need to override that target.

- name: Upload coverage
  uses: 9to5/9to5-coverage-action@v1
  with:
    token: ${{ secrets.COVERAGE_UPLOAD_TOKEN }}
    path: coverage/lcov.info

3. Put your coverage to work

Open the repository report and GitHub PR checks. Confirm the commit and baseline, inspect uncovered changed lines, add focused tests, and upload again. You can also connect a coding agent to read coverage context while you work locally.

Understand project and patch checks

Project coverage measures covered lines across the uploaded report. Its check passes when coverage is at least the baseline value; without a baseline it is neutral.

Patch coverage measures covered relevant changed lines divided by all relevant changed lines. The patch check requires 100%. For example, covering 8 of 10 relevant changed lines gives 80%, even if overall project coverage increased.

The baseline first uses a matching-format report for the supplied base SHA, then falls back to the latest matching-format base-branch report. The head commit is excluded. Inspect the recorded baseline rather than assuming it is the current default-branch head.

Coverage depends on the files and lines included by your test runner. Keep source inclusion and exclusion settings consistent. A green coverage check measures execution; it does not prove assertions are useful or that every behavior was tested.

When an upload or check is missing

Missing report
Confirm the test runner wrote the exact upload path. Vitest needs an LCOV reporter; Gradle needs JaCoCo XML enabled.
Missing baseline
Upload the base commit or base branch using the same report format. For an exact comparison, ensure that the base SHA has a report.
Fork pull requests
GitHub normally withholds repository secrets from fork workflows. An unavailable upload token prevents authenticated upload. Do not expose tokens to untrusted code to work around this.
Mismatched paths or multiple formats
Generate reports from the checkout root and inspect reported file paths. MCP clients can select a format explicitly when multiple formats make the result ambiguous.

API reference

Current upload API

Use the reusable GitHub Action for GitHub Actions setup. The same endpoint also supports bearer-token multipart uploads for other CI providers and JSON artifact URL submissions for the Action.

Authentication

Send Authorization: Bearer COVERAGE_UPLOAD_TOKEN. Repository and organization tokens are supported.

Upload endpoint override

POST /api/v1/repos/:owner/:repo/coverage

The GitHub Action's endpoint input is optional and only needed when overriding the default upload host. Multipart fields: commit_sha, branch, and coverage or file.

Artifact JSON

JSON submissions use commit_sha, branch, artifact_url, and coverage_path. Artifact URLs must point to a GitHub Actions artifact for the same repository.

Optional fields

Include base_sha, base_branch, pull_request_number, and run_url for richer pull request reporting.

Success response

Multipart uploads return status, coverage_run_id, project and patch coverage percentages, and project/patch conclusions. Artifact JSON submissions return status: queued, upload_id, and job_id; processing status is visible on the repository page.

Error responses

400: commit SHA, branch, coverage file, or artifact URL is missing or invalid.

401: upload token is invalid for the requested repository.

422: the coverage file cannot be downloaded, found, parsed, or persisted.