GitHub Code Quality: code coverage directly in pull requests

GitHub``GitHub Actions``Testing``Code Quality``CI/CD

GitHub added coverage summaries to pull requests through the Code Quality public preview. Here is how to connect Cobertura XML, actions/upload-code-coverage@v1, and keep reviewer signal in the PR

Hook

Coverage is useful only when reviewers see it at decision time. If the number lives in a separate service, a separate tab, or a CI artifact, it is easy to ignore.

On May 26, 2026, GitHub added code coverage directly to pull requests in public preview for GitHub Code Quality. The flow is straightforward: a test job generates Cobertura XML, GitHub Actions uploads it through actions/upload-code-coverage@v1, and the PR gets a summary from github-code-quality[bot].

Problem / Context

Many teams already run tests in CI, but reviewers still do not see a useful coverage signal where they make the merge decision. In the best case, there is a green test check. In the worse case, someone has to open Codecov, Coveralls, an HTML report, or a build artifact.

A green check does not answer a simple question: did the changed code get tested? A PR can pass the whole test suite and still add new logic with no coverage at all. That is where a coverage summary in the PR helps. It does not replace review, but it adds another visible signal.

GitHub does not make this automatic by magic. You need three things:

  • GitHub Code Quality enabled for the repository;
  • a coverage report in Cobertura XML format;
  • a workflow with code-quality: write permission that uploads the report.

Why It Matters

Coverage in the PR reduces context switching. Reviewers are already looking at the diff, comments, checks, and statuses. If the same surface shows aggregate coverage and a per-file breakdown, the team can notice an obvious problem faster: a new file was added, logic changed, and no tests touched it.

This is especially useful for teams already living in GitHub Team or Enterprise Cloud that do not want to maintain a separate coverage service just for a basic reviewer signal. During the public preview, GitHub Code Quality is not billed separately, although the workflow still consumes GitHub Actions minutes.

But it should not be oversold. This is not a complete replacement for every quality platform. If you need deep coverage history, team-level rules, multi-repository analytics, or custom quality gates, a dedicated tool may still be needed. GitHub coverage in PRs is mainly a native signal for everyday review.

How To Do It

1. Check availability

Start with plan and permissions. GitHub describes Code Quality for GitHub Team and GitHub Enterprise Cloud. Repository owners, organization owners, and users with the admin role can enable it.

If the repository is on GitHub Enterprise Server or a plan without Code Quality, do not start with YAML. Confirm availability first, or you will end up with a nice workflow that cannot upload data anywhere.

2. Generate Cobertura XML

GitHub expects the coverage report in Cobertura XML format. The language is not the key point; the important part is that your test framework can create or convert this file.

Examples:

# Python
pytest --cov=. --cov-report=xml

# JavaScript / TypeScript with nyc
nyc report --reporter=cobertura

# Go with coverprofile and a converter
go test -coverprofile=cover.out ./...
gocover-cobertura < cover.out > coverage.xml

Do not start with the upload action. First prove locally or in CI that the file exists, has the expected path, and represents the code that was actually tested.

3. Add the upload step

A minimal GitHub Actions pattern looks like this:

name: Code Coverage

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read
  code-quality: write

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          ref: ${{ github.event.pull_request.head.sha || github.sha }}

      - name: Install dependencies
        run: npm ci

      - name: Run tests with coverage
        run: npm test -- --coverage

      - name: Upload coverage report
        if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
        uses: actions/upload-code-coverage@v1
        with:
          report: coverage/cobertura-coverage.xml
          language: JavaScript
          label: code-coverage/unit

Two details are not decorative.

First, the workflow should run on both push to the default branch and pull_request. GitHub compares the PR branch with the default branch, so it needs a baseline.

Second, code-quality: write is a dedicated fine-grained permission for uploading coverage. Do not grant broader workflow access just because it is quicker.

4. Be careful with forked PRs

The example uses an if condition that skips upload for pull requests from forked repositories. That matters because an external fork should not get the same trust level as a branch inside your own repository.

Tests can still run for forked PRs, but coverage upload to GitHub Code Quality should happen only where you control the workflow source and permissions.

5. Verify the first PR

After the workflow has run on the default branch, open a test PR. When CI finishes, look for a comment from github-code-quality[bot]. It should show aggregate coverage for the PR branch compared with the default branch and a per-file breakdown.

If the comment does not appear, check these in order:

  • Code Quality is actually enabled;
  • Cobertura XML is produced;
  • the report: path is correct;
  • the workflow has code-quality: write;
  • a push baseline on the default branch has already run;
  • the PR is not from a fork where upload is intentionally skipped.

Anti-patterns

Do not add a hard coverage gate too early. Watch a few real PRs first and understand the noise. If you set a strict threshold immediately, the team may start playing the metric instead of improving tests.

Do not confuse coverage with test quality. A high percentage does not mean all important scenarios are checked. It only means the code ran during tests.

Do not keep two coverage upload paths without a reason. If GitHub coverage replaces a third-party basic upload, remove the duplicate so reviewers do not get conflicting comments.

Conclusion

GitHub Code Quality coverage in PRs is a good small rollout for teams that already run tests in GitHub Actions. The best first step is one repository, one test job, Cobertura XML, actions/upload-code-coverage@v1, code-quality: write, and a test PR.

If reviewers actually start using the coverage signal next to the diff, the feature is doing its job. If not, do not add another gate for the sake of having a gate. First find the signal that helps the team merge with more confidence.

Quick checklist

  • Verify that GitHub Code Quality is available for the repository.
  • Enable Code Quality for the repository.
  • Make the test job generate Cobertura XML.
  • Add `permissions: code-quality: write`.
  • Run the workflow on `push` to the default branch and on `pull_request`.
  • Upload coverage with `actions/upload-code-coverage@v1`.
  • Avoid uploading coverage from untrusted forked PRs.
  • Check for the `github-code-quality[bot]` comment in a test PR.

Prompt Pack: add coverage summaries to GitHub PRs

Help prepare a GitHub Actions rollout for pull request coverage summaries through GitHub Code Quality. Input data: - project language and test framework; - current `.github/workflows/ci.yml`; - whether a coverage report exists today; - whether the project can produce Cobertura XML; - default branch; - whether the repository accepts pull requests from forks; - GitHub plan: Team or Enterprise Cloud. Return: 1. whether the repository fits the GitHub Code Quality coverage preview; 2. a minimal YAML diff; 3. where Cobertura XML is generated; 4. which permissions are required; 5. how to handle forked PRs; 6. verification criteria after the first PR. Format: verdict, prerequisites, YAML diff, fork handling, verification checklist.