CI integration
This guide shows how to integrate coverctl into your CI/CD pipeline.
GitHub Actions
Section titled “GitHub Actions”Basic Setup
Section titled “Basic Setup”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 go.klarlabs.de/coverctl@latest
- name: Run coverage check run: coverctl check --ciWith Caching
Section titled “With Caching”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 go.klarlabs.de/coverctl@latest
- name: Run coverage check run: coverctl check --ci --fail-under 80Pull Request Comments
Section titled “Pull Request Comments”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 go.klarlabs.de/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
With Coverage Comparison
Section titled “With Coverage Comparison”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.outDiff-Based Coverage for PRs
Section titled “Diff-Based Coverage for PRs”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 go.klarlabs.de/coverctl@latest
- name: Run diff coverage run: coverctl check --ci --diff origin/${{ github.base_ref }}Security Scan (SARIF)
Section titled “Security Scan (SARIF)”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.sarifCoverage Badge
Section titled “Coverage Badge”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 go.klarlabs.de/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 pushRecord Coverage History
Section titled “Record Coverage History”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 go.klarlabs.de/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 pushOther CI systems
Section titled “Other CI systems”The same two commands work everywhere: install the binary, then
coverctl check --ci. PR comments auto-detect from provider env vars.
| System | Install + gate | PR comment env |
|---|---|---|
| GitLab CI | go install … && coverctl check --ci |
CI_MERGE_REQUEST_IID |
| CircleCI | same in a Go job step | — |
| Jenkins | same in a golang agent |
— |
| Bitbucket Pipelines | same | BITBUCKET_PR_ID |
Minimal GitLab snippet:
coverage: image: golang:1.25 script: - go install go.klarlabs.de/coverctl@latest - coverctl check --ci --fail-under 80Minimal Bitbucket PR comment:
script: - go install go.klarlabs.de/coverctl@latest - coverctl check - coverctl pr-comment # uses BITBUCKET_PR_IDCI Flags
Section titled “CI Flags”| Flag | Description |
|---|---|
--ci |
CI mode: quiet output + GitHub Actions annotations |
--quiet |
Suppress non-essential output |
--no-color |
Disable colored output |
--fail-under N |
Fail if coverage below N% |
--ratchet |
Fail if coverage decreases |
-o json |
JSON output for parsing |
Best Practices
Section titled “Best Practices”- Use
--ciflag: Enables GitHub Actions annotations - Set
--fail-under: Enforce minimum thresholds - Use
--ratcheton main: Prevent regression - Cache Go modules: Speed up CI runs
- Use diff mode for PRs: Focus on changed code
See Also
Section titled “See Also”- Build Flags - Customize test execution
- Configuration - Policy configuration