Open source AGPL-3.0 Single binary + Postgres

Coverage in every pull request.

Diff coverage and merge gates on Bitbucket, GitHub and GitLab — plus line annotations right in the Bitbucket and GitHub diff view. Self-host it free, or let us run it.

Bitbucket · GitHub · GitLab

Free for public repos · self-host in a minute: docker compose up — migrations apply themselves.

gocov coverage — check run · pull request #142 Gate passed
84.2% +0.6% diff coverage 91.7% changed lines 110 / 120 covered
internal/billing/invoice.go — 2 uncovered changed lines
87
	if err := tx.Commit(); err != nil {
88
		return fmt.Errorf("commit: %w", err)
89
	}
One endpoint, format auto-detected Go cover profiles JS / TS LCOV — Jest, Vitest, nyc Java / Kotlin JaCoCo XML Python Cobertura — coverage.py PHP Clover — PHPUnit Ruby SimpleCov .NET / C++ Cobertura XML

Up and running in three steps

The CI step is the same either way.

  1. Sign in at app.gocov.dev

    Nothing to install and no server to run. Sign in with the forge you already use.

  2. Connect your workspace

    On GitHub, installing the app picks the organization and its repositories in one grant. On Bitbucket and GitLab you pick a workspace or group you already belong to.

  3. Add gocov to CI

    No secret to paste: the job proves which repository it is with a short-lived identity token from your forge, and repositories register themselves on first upload.

    OIDC nothing to create, nothing to rotate
# .github/workflows/test.yml permissions: id-token: write # a signed identity token instead of a secret - run: go test ./... -coverprofile=coverage.out - uses: gocov/gocov-action@v1 with: files: coverage.out
# .github/workflows/test.yml permissions: id-token: write # a signed identity token instead of a secret - run: go test ./... -coverprofile=coverage.out - uses: gocov/gocov-action@v1 with: files: coverage.out server: ${{ vars.GOCOV_SERVER }}
# bitbucket-pipelines.yml - step: oidc: audiences: [https://app.gocov.dev] # identity token, no secret script: - go test ./... -coverprofile=coverage.out - pipe: docker://gocov/upload-pipe:0 variables: FILES: coverage.out
# bitbucket-pipelines.yml - step: oidc: audiences: [https://gocov.example.com] # your server URL script: - go test ./... -coverprofile=coverage.out - pipe: docker://gocov/upload-pipe:0 variables: FILES: coverage.out SERVER: $GOCOV_SERVER
# .gitlab-ci.yml include: - component: gitlab.com/gocov/gocov/upload@1 inputs: files: coverage.out needs: [test] test: script: go test ./... -coverprofile=coverage.out artifacts: paths: [coverage.out]
# .gitlab-ci.yml include: - component: gitlab.com/gocov/gocov/upload@1 inputs: files: coverage.out needs: [test] server: https://gocov.example.com test: script: go test ./... -coverprofile=coverage.out artifacts: paths: [coverage.out]
# any runner, no Docker required; OIDC where the runner offers it, else $GOCOV_TOKEN $ go run github.com/gocov/gocov/cmd/gocov@latest \ upload coverage.out
# any runner, no Docker required; OIDC where the runner offers it, else $GOCOV_TOKEN $ go run github.com/gocov/gocov/cmd/gocov@latest \ upload coverage.out \ --server $GOCOV_SERVER
No secret to paste: the job sends a short-lived OIDC token the server verifies against your forge (a GOCOV_TOKEN secret still works, and is the way in for CI systems without OIDC). The action, the pipe and the GitLab component pin the CLI to a fixed version, so a release can't change your build.
GOCOV_SERVER points CI at your own instance. Everything else matches the hosted setup.

Your coverage tool treats you like an edge case.

Codecov and Coveralls are GitHub-first. Anywhere else you get the side-port: no per-line annotations in the diff view and a thinner integration. Bitbucket Cloud has no native coverage view either — the request below has been open since 2022.

As of August 2026, gocov is the only coverage product that posts per-line annotations inside the Bitbucket Cloud PR diff.
+ BCLOUD-22379 · Bitbucket Cloud · public issue tracker

Show code coverage in the pull request diff view

Gathering Interest since 2022 77 votes 47 watchers

Switching from Codecov or Coveralls?

The migration guide maps your codecov.yml, action inputs and Coveralls thresholds onto gocov’s gate and parts, swaps the required check and the badge, and gives the order that keeps the old tool running until the numbers agree. No history import; no token to paste either.

Read the migration guide

Coverage where reviewers already look

Not another dashboard to check — results land inside the pull request.

Diff coverage PR comments

Changed lines are intersected with coverage; a comment lists what's untested. Re-uploads update the same comment — no stacking. Fork PRs get coverage with no token at all: uploads are verified through the GitHub App.

Gates that block merges

Per-repo minimums for total and diff coverage plus a drop tolerance. Violations fail the commit status, so branch protection can block the PR.

Native in-PR reports

GitHub check runs, Bitbucket Code Insights report cards and diff-coverage comments on GitLab merge requests — with inline annotations on uncovered changed lines right in the GitHub and Bitbucket diff views.

Line-by-line source view

Every file renders with coverage overlay and hit counts, fetched from the forge at the exact commit and cached immutably.

Trends and badges

A coverage trend chart per branch — rendered server-side, no JS chart library — and an SVG badge per repo for your README.

OAuth sign-in, no passwords

Web UI sign-in with Bitbucket, GitHub and GitLab, restricted to members of the orgs you track. No passwords ever stored. One-click workspace connect.

Run it yourself, or let us run it

Same product either way — pick the operations model that fits.

Self-hosted

$0 forever
  • AGPL-3.0 — full product, no feature gates
  • Your infra, your data
  • Community support
Deploy from GitHub

Public repos are free on hosted, forever — fair use, no upload limits. An active committer is anyone who commits to a covered private repo in the last 30 days.

Self-host and nothing leaves your infra

gocov is a single Go binary in front of Postgres. Run it yourself and no vendor gets your source, your coverage, or your commit metadata. On hosted we store coverage and commit metadata — never your source. The architecture is deliberately extensible: formats, forges and blob storage sit behind interfaces.

AGPL-3.0 licensed — fork it, patch it, ship it docker compose up — production-shaped from day one Bitbucket + GitHub + GitLab — one instance, all three forges Unlimited repos and users — it's your server