Skip to content

CI Integration

This guide shows how to integrate coverctl into your CI/CD pipeline.

.github/workflows/coverage.yml
name: Coverage
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Install coverctl
run: go install github.com/felixgeelhaar/coverctl@latest
- name: Run coverage check
run: coverctl check --ci
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.25'
cache: true
- name: Install coverctl
run: go install github.com/felixgeelhaar/coverctl@latest
- name: Run coverage check
run: coverctl check --ci --fail-under 80

Post coverage results as PR comments using the built-in pr-comment command:

jobs:
coverage:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Install coverctl
run: go install github.com/felixgeelhaar/coverctl@latest
- name: Run coverage and post comment
if: github.event_name == 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
coverctl check
coverctl pr-comment --pr ${{ github.event.pull_request.number }}

The pr-comment command automatically:

  • Detects GitHub from environment variables
  • Generates a formatted coverage report
  • Updates existing comments instead of creating duplicates

Compare against the base branch for delta reporting:

- name: Checkout base branch coverage
if: github.event_name == 'pull_request'
run: |
git fetch origin ${{ github.base_ref }}
git checkout origin/${{ github.base_ref }} -- .cover/coverage.out || true
mv .cover/coverage.out base-coverage.out 2>/dev/null || true
- name: Run coverage with comparison
if: github.event_name == 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
coverctl check
coverctl pr-comment --pr ${{ github.event.pull_request.number }} --base-profile base-coverage.out

Only check coverage on changed files:

jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for diff
- uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Install coverctl
run: go install github.com/felixgeelhaar/coverctl@latest
- name: Run diff coverage
run: coverctl check --ci --diff origin/${{ github.base_ref }}

Run nox and upload SARIF to GitHub code scanning:

jobs:
security:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- name: Install nox
run: |
curl -sL https://github.com/nox-hq/nox/releases/download/v0.7.0/nox_0.7.0_linux_amd64.tar.gz | tar xz -C /usr/local/bin nox
- name: Run nox (SARIF)
run: nox -format sarif -output . scan . || true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarif

Generate and commit a coverage badge:

jobs:
badge:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Install coverctl
run: go install github.com/felixgeelhaar/coverctl@latest
- name: Generate badge
run: |
coverctl run
coverctl badge -o docs/coverage.svg
- name: Commit badge
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git add docs/coverage.svg
git diff --quiet --cached || git commit -m "Update coverage badge"
git push

Track coverage over time:

jobs:
coverage:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Install coverctl
run: go install github.com/felixgeelhaar/coverctl@latest
- name: Run and record coverage
run: |
coverctl check
coverctl record --commit ${{ github.sha }} --branch main
- name: Commit history
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git add .cover/history.json
git diff --quiet --cached || git commit -m "Update coverage history"
git push
.gitlab-ci.yml
coverage:
image: golang:1.25
script:
- go install github.com/felixgeelhaar/coverctl@latest
- coverctl check --ci --fail-under 80
coverage: '/Overall\s+(\d+\.\d+)%/'
# Post MR comments (merge requests)
coverage:mr-comment:
image: golang:1.25
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
script:
- go install github.com/felixgeelhaar/coverctl@latest
- coverctl check
# MR number auto-detected from CI_MERGE_REQUEST_IID
- coverctl pr-comment
FlagDescription
--ciCI mode: quiet output + GitHub Actions annotations
--quietSuppress non-essential output
--no-colorDisable colored output
--fail-under NFail if coverage below N%
--ratchetFail if coverage decreases
-o jsonJSON output for parsing
  1. Use --ci flag: Enables GitHub Actions annotations
  2. Set --fail-under: Enforce minimum thresholds
  3. Use --ratchet on main: Prevent regression
  4. Cache Go modules: Speed up CI runs
  5. Use diff mode for PRs: Focus on changed code