CLI reference¶
The CLI uploads one coverage file per invocation, auto-detecting everything it can: the format from the file's
content, and repo, commit, branch and PR id from Bitbucket Pipelines, GitHub Actions or GitLab CI environment
variables, falling back to git.
Installing¶
- GitHub Actions and Bitbucket Pipelines have wrappers that install it for you.
- Prebuilt binaries for every platform are on GitHub Releases — see Other CI systems for a pinned, checksum-verified download recipe.
- With a Go toolchain:
go run github.com/gocov/gocov/cmd/gocov@latest upload …
Flags¶
| flag | default | meaning |
|---|---|---|
-token |
$GOCOV_TOKEN |
the workspace/repo upload token. Optional when the CI job can mint an OIDC identity token, or in a GitHub Actions pull_request run — see without a token |
-server |
$GOCOV_SERVER, else the hosted service |
the gocov instance to upload to — only needed when self-hosting |
-repo |
auto-detect | repo slug, workspace/repo |
-commit |
auto-detect | commit SHA. The one value that has no fallback: if detection fails, the upload asks for it |
-branch |
auto-detect | branch name |
-pr |
auto-detect | pull request id; enables diff coverage |
-format |
detect from content | go, lcov, jacoco, cobertura, clover or simplecov |
-path-prefix |
from go.mod for Go profiles |
prefix mapping profile paths to repo paths, e.g. the Go module path — see below |
-part |
$GOCOV_PART, else default |
names this slice of the commit's coverage when several jobs upload — see Parts |
-ignore |
$GOCOV_IGNORE, else none |
leave matching files out of the report, e.g. cmd/preview/**; repeatable or comma-separated — see Ignoring files |
-fail-on-gate |
off | exit non-zero when the server reports a failed coverage gate |
Environment variables¶
| variable | equivalent flag |
|---|---|
GOCOV_TOKEN |
-token |
GOCOV_SERVER |
-server |
GOCOV_PART |
-part |
GOCOV_IGNORE |
-ignore |
GOCOV_PART is handy for matrix jobs that already expose the variant in the environment. GOCOV_IGNORE takes
several patterns separated by commas or newlines. Flags win over the environment.
Uploading without a token¶
When no -token/$GOCOV_TOKEN is set, the CLI tries two secret-free paths in order before giving up:
- OIDC. If the CI job can provide an OIDC identity token — GitHub Actions with
permissions: id-token: write, Bitbucket Pipelines withoidc.audiences, or GitLab CI with anid_tokensentry namedGOCOV_ID_TOKEN— the CLI sends it in place of the token, scoped to the gocov server's audience. The server verifies the forge's signature and the repository the token names, so the upload is fully verified — not marked unverified. The repository's workspace must be connected to its forge with a connection that still works; otherwise the upload is refused withoidc_not_connectedand the reason. This is the recommended setup for a repo's ownpushand same-repo PR builds; see GitHub Actions, Bitbucket Pipelines and GitLab CI. - Tokenless fork-PR (below), for the fork pull request that has neither a secret nor an
id-token.
An explicit token always wins, so existing setups are untouched. A rejected OIDC upload does not fail the
build: the CLI prints one line with the server's reason (gocov: OIDC upload rejected — …) and exits 0.
Tokenless fork-PR uploads¶
In a GitHub Actions pull_request workflow with no token set — the fork-PR situation, where secrets are withheld —
the CLI uploads tokenless: it sends the workflow run's identity (run id, attempt, PR number, head SHA, fork) and the
server verifies the run with GitHub through the repo's App installation.
Works on public repos with the gocov GitHub App connected; anywhere else a missing token stays an error.
In tokenless mode an upload that is refused or fails does not fail the build: the CLI prints one line with the
server's reason (gocov: tokenless upload rejected — …) and exits 0.
-path-prefix¶
Diff coverage matches the paths in the profile against the paths in the PR's diff. When the profile records paths
under a prefix the repo doesn't have — a Go module path, a CI checkout directory — set -path-prefix to that prefix
so the two line up. For Go profiles the CLI fills it from go.mod automatically; JaCoCo's package-qualified paths are
matched by suffix and usually need nothing. Symptoms and details:
Why coverage changed.
Output and exit code¶
A successful upload prints the totals the server computed — coverage, delta, how many files the
ignore patterns dropped (when any did), diff coverage, and the status of each forge surface
(build status, pr comment, code insights: posted, or skipped with the reason) plus the gate verdict:
uploaded: 82.0% (1230/1500 statements), delta +0.4%
ignored: 3 files
diff coverage: 91.7% (22/24 changed lines)
build status: posted
pr comment: posted
gate: passed
When the commit's coverage arrives in parts, the totals are the commit's merged report, not the one file this step uploaded. The output names the part it uploaded and the parts the figure was merged from so far, so the first part to land doesn't read as the commit's final coverage:
uploaded part: web
commit coverage: 95.0% (1158/1219 statements), delta +10.3%
merged from 1 part so far: web
When the last part lands, its step prints the complete figure (merged from 2 parts so far: go, web). Uploads without
a -part print the single uploaded: line above.
When the server built the commit's merged report with a caveat — two parts that disagree on a PR's
changed lines, whose diff coverage is then merged as a safe lower bound — a warning: line under the totals says so.
A warning never fails the step.
The exit code is non-zero on any upload error, and — only with -fail-on-gate — on a failed gate, which is how a
pipeline step turns the gate into a hard failure even without forge-side merge blocking.
The raw HTTP endpoint underneath, for anything the CLI doesn't cover, is documented in API & badge.