Check Code Coverage in Pull Requests and Merge Requests

This guide helps you set up CodeScene Code Coverage gates in your CI workflow.

By the end of this guide, you will have:

  1. Generated coverage reports in CI.

  2. Added CodeScene’s coverage check to a GitHub Actions workflow.

  3. Enabled Code Coverage gates in CodeScene.

  4. Verified the result as a pull request status check.

Attention: Code Coverage gates are currently available for GitHub. For other platforms, contact your CodeScene Account Executive for availability and roadmap information.

What Code Coverage gates do

Code Coverage gates let CodeScene check coverage directly in your pull request workflow.

CodeScene supports two complementary gates:

  • New and Changed Code: checks coverage for executable lines added or changed in the pull request.

  • Overall Code Coverage: checks that the project’s total coverage does not fall below the configured threshold.

CodeScene posts the result as a pull request status check. Your GitHub branch protection rules can then require that check before a pull request is merged.

Coverage gates vs coverage uploads

Code Coverage gates are separate from the coverage upload flow used for visualization in CodeScene.

Use coverage uploads when you want to visualize coverage trends, hotspots, and file-level coverage in the CodeScene UI.

Use coverage gates when you want CI to check whether a pull request passes your coverage thresholds.

You do not need to upload coverage reports to CodeScene to use the Code Coverage gates. The gates are evaluated by the cs-coverage check command in CI.

Recommended setup

CodeScene recommends using the New and Changed Code gate as the default starting point.

This gate is usually the most actionable because it checks the code changed in the pull request. It helps teams improve coverage over time without forcing the entire repository to reach a high coverage level immediately.

The Overall Code Coverage gate can also be useful, but it may be noisier in pull request workflows unless the project already has a strict and consistent coverage baseline.

Before you start

Make sure you have:

  • A GitHub repository connected to a CodeScene project.

  • A CI workflow that runs tests.

  • A test setup that generates coverage reports in a supported format, such as LCOV, JaCoCo, Cobertura, or OpenCover.

  • A CodeScene Personal Access Token available as a GitHub secret.

  • Your CodeScene URL available as a GitHub secret.

  • Full Git history available in the workflow checkout step.

The full Git history is required so CodeScene can identify the merge base for the pull request.

Step 1: Generate coverage reports in CI

First, make sure your CI workflow runs tests and generates a coverage report.

The exact command depends on your language, framework, and coverage tooling.

Examples:

  • JavaScript/TypeScript projects often generate LCOV reports.

  • Java projects often generate JaCoCo XML reports.

  • .NET projects may generate OpenCover reports.

  • Larger repositories may generate multiple coverage reports from multiple test suites or components.

After the report is generated, the later CodeScene step needs access to the file path.

Step 2: Add the CodeScene coverage check to GitHub Actions

The example below shows a simple end-to-end GitHub Actions workflow.

Adjust the test command, coverage file path, format, and metric to match your project.

name: Code Coverage Gates

on:
  pull_request:
    branches:
      - main
  workflow_dispatch:

jobs:
  coverage-gates:
    runs-on: ubuntu-latest

    steps:
      - name: Check out repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Run tests and generate coverage
        run: |
          # Replace this with your project's actual test command.
          # The command must generate a supported coverage report.
          echo "Run tests here and generate coverage"

      - name: Install CodeScene Coverage CLI
        run: curl https://downloads.codescene.io/enterprise/cli/install-cs-coverage-tool.sh | bash -s -- -y

      - name: Check Code Coverage gates
        run: cs-coverage check --coverage-files "coverage/code-coverage.lcov"
        env:
          CS_ONPREM_URL: ${{ secrets.CS_ONPREM_URL }}
          CS_ACCESS_TOKEN: ${{ secrets.CS_ACCESS_TOKEN }}

Important GitHub Actions settings

Use fetch-depth: 0 in the checkout step. Without full Git history, CodeScene may not be able to identify the merge base for the pull request.

Store the CodeScene URL and access token as GitHub secrets, for example:

  • CS_ONPREM_URL

  • CS_ACCESS_TOKEN

Step 3: Enable Code Coverage gates in CodeScene

After the CI workflow can generate coverage and run cs-coverage check, enable the gates in CodeScene.

CodeScene lets you configure gates at two levels:

  1. Organization-level configuration: define the default coverage gates and thresholds for all projects.

  2. Project-level configuration: override the defaults for a specific project when needed.

Enable the gates that match your team’s workflow.

Recommended starting point:

  • Enable New and Changed Code.

  • Set a high threshold, for example 90% or higher.

  • Enable Overall Code Coverage only if the project already has a stable coverage baseline and the team wants to enforce it.

Step 4: Open a pull request and verify the result

Open a pull request after the workflow has been added.

CodeScene should post a status check on the pull request with the coverage result.

If your GitHub branch protection rules require the CodeScene check, GitHub can block the merge until the gate passes.

How the gates work

New and Changed Code

The New and Changed Code gate checks executable lines added or modified in the pull request.

CodeScene identifies those lines by comparing the pull request branch with its merge base.

The gate only considers executable lines. Changes to comments or other non-executable content do not affect the result.

This gate is designed to be actionable: when it fails, the recommended fix is usually to add or adjust tests for the code changed in the pull request.

Overall Code Coverage

The Overall Code Coverage gate checks whether the project’s total coverage stays above the configured threshold.

This can be useful for projects with an established coverage target, but it may be less actionable in individual pull requests because the failure can be caused by the repository’s broader coverage level rather than only the current changes.

Multiple source components or coverage reports

Large repositories may have multiple source components, languages, or test suites.

In that case:

  • Generate coverage reports for each component that is built and tested.

  • Make the reports available to the CodeScene coverage check step.

  • Run cs-coverage check once and pass the relevant coverage files to that check.

If only some source components are built in a pull request, the scope of the Overall Code Coverage gate adapts to the tested components. The pull request comment should show the scope used for the result.

Not using pull requests?

You can also use Code Coverage gates in a build step without pull requests.

In that setup, the process is similar, but you do not enable the pull request check in CodeScene’s UI configuration.

For the New and Changed Code gate in a build context, CodeScene treats the content of the latest commit as the changed code.

Troubleshooting

The check cannot identify the merge base

Make sure the GitHub Actions checkout step uses full Git history:

- name: Check out repository 
  uses: actions/checkout@v4 
  with: 
    fetch-depth: 0 

Without this setting, the workflow may not have enough Git history for CodeScene to compare the pull request branch with its merge base.

The coverage gate fails

When a gate fails, check the CodeScene pull request comment or status output for the reason.

Common fixes include:

  • Add tests for the changed code.

  • Make sure the generated coverage report includes the files changed in the pull request.

  • Check that the coverage report path passed to cs-coverage check is correct.

  • Review exclusions if generated files, test files, or unsupported areas should not be part of the gate.

The workflow cannot find the coverage report

Check that:

  • the test step generated the report successfully,

  • the file path passed to cs-coverage check is correct,

  • the report is available in the same job or downloaded as an artifact before the check runs.

The gate is too noisy

Start with the New and Changed Code gate before enabling Overall Code Coverage.

If needed, adjust thresholds or exclude files and folders that should not be part of the gate.

Debugging with verbose logs

Use the verbose option to get more details from the coverage check:

cs-coverage check --verbose --coverage-files "coverage/code-coverage.lcov" 

FAQ

Which gate should we start with?

Start with New and Changed Code. It focuses on the code changed in the pull request and is usually the most actionable gate.

What threshold should we use?

A high threshold is recommended for New and Changed Code. A threshold of 90% or higher is a good starting point for many teams.

Do we need to upload coverage reports to CodeScene for PR gates?

No. Coverage gates are independent of the coverage upload flow used for visualization in the CodeScene UI.

Can we exclude files or folders from coverage gates?

Yes. Exclusions can be configured in CodeScene. Use this for files or folders that should not be evaluated by the coverage gates.

Are PR/MR coverage gates available for GitLab, Azure DevOps, or Jenkins?

The documented PR/MR coverage gates are currently available for GitHub. For other platforms, contact your CodeScene Account Executive for availability and roadmap information.

Related guide

For visualizing coverage trends, hotspots, and file-level coverage in CodeScene, use the separate guide for uploading coverage data with the Coverage CLI.