feat(coverage-gate): systematic new-code coverage tool [mache-66d8df]#390
Merged
Merged
Conversation
A diff-aware NEW-CODE coverage gate written in pure Go (stdlib only,
no new module deps). Intersects a Go cover profile with a unified diff
and reports any newly-added or modified PROD lines (excluding tests,
testdata, blank lines, comment-only lines) that have zero coverage.
Contract:
coverage-gate <cover.out> <diff.patch>
Inputs:
- cover.out: produced by `go test -coverprofile=cover.out ./...`
- diff.patch: unified diff from `git diff base..HEAD` or `gh pr diff`
Output (on failure):
NEW PROD LINES NOT COVERED:
internal/leyline/socket.go
L189-191
L256-257
4 new prod line(s) uncovered. Either add tests or annotate the
line with `// coverage:ignore`.
Exit codes:
0 — every new prod line is either covered, not a statement, or
explicitly annotated `// coverage:ignore`
1 — at least one new prod line is uncovered; per-file report on stdout
2 — usage / I/O / parse error
Implementation:
- parseProfile: streams the cover profile (file, range, hits)
- normalizeProfilePaths: strips the module prefix (read from ./go.mod)
so profile keys match diff paths (repo-relative)
- parseDiff: walks unified diff hunks, tracks +newstart, records added
.go prod lines (filters _test.go, testdata, non-.go, blank, // and /*)
- intersect: per-file, per-line lookup against cover ranges; "covered
range wins" semantics for overlapping ranges; lines outside any
range are silently skipped (not statements)
- `// coverage:ignore` suffix suppresses a single added line
Self-tests (15, all pass): parse/diff/intersect/overlap/comment-skip/
test-file-skip/testdata-skip/non-go-skip/coverage-ignore/exit-code-zero/
exit-code-one/report-format/normalize-paths/hunk-header-parsing/
stable-sort.
Per-PR verification:
PR #389 (DiscoverOrStart rewrite):
NEW PROD LINES NOT COVERED:
internal/leyline/socket.go
L190-191
L256-257
4 new prod line(s) uncovered. exit 1 OK
PR #388 (download-leyline retarget):
NEW PROD LINES NOT COVERED:
internal/leyline/socket.go
L583
L605
2 new prod line(s) uncovered. exit 1 OK
(these are inside downloadLeyline, exercised only via network)
No edits to Taskfile.yml, .github/workflows/, or other files — this PR
ships ONLY the tool. CI wiring is a deliberate follow-up.
find_smells (advisory)Scoped to files changed in this PR. Rules below run on the standalone (no-LLO) cross-ref tables; fan_out_skew — 1 finding(s) in changed files
Rules: see |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A diff-aware NEW-CODE coverage gate (
tools/coverage-gate/) that enforces"every new prod line is covered" per PR. Pure stdlib Go, no new module deps.
Lives alongside the existing one-off tools in
tools/.This PR ships the tool only. CI wiring (calling it from
task checkor a GHA job) is a deliberate follow-up so the contract can land and be
exercised locally first.
Contract
cover.out— produced bygo test -coverprofile=cover.out ./...diff.patch—git diff base..HEAD > diff.patchorgh pr diff <num> > diff.patchExit codes:
0— every new prod line is either covered, not a statement (decl, blank,comment), or annotated
// coverage:ignore1— at least one new prod line is uncovered; per-file report on stdout2— usage / I/O / parse errorWhat counts as "new prod line":
+-prefixed line in a unified-diff hunk.go, NOT_test.go, NOT under/testdata///or/*(after trim)// coverage:ignoresuffixOutput format (failure)
Contiguous uncovered lines collapse into
Lstart-endblocks. Files sortalphabetically. Total count at the bottom.
Per-PR verification
PR #389 (DiscoverOrStart rewrite)
L190-191 is the stale-managed-daemon reap branch; L256-257 is the
last-chance pre-spawn liveness check + leftover-socket cleanup. Both are
real new prod lines without test coverage — exactly the kind of thing
this gate exists to surface.
PR #388 (download-leyline retarget)
Both are inside
downloadLeyline—assetName := fmt.Sprintf(...)andthe
http.StatusNotFoundbranch. Exercised only via network, henceno automated coverage. Honest report; humans decide whether to backfill
with an
httptest-driven test or annotate// coverage:ignore.Self-tests
15 tests, all pass:
TestParseProfile/TestParseProfileMalformedTestParseDiff/TestParseHunkNewStartTestIgnoreTestFiles/TestIgnoreTestdataAndNonGo/TestIgnoreCommentsTestIntersect/TestIntersectOverlappingCoveredWins/TestIntersectStableSortTestCollapseBlocksTestNormalizeProfilePathsTestExitCodeZeroWhenCovered/TestExitCodeOneWhenUncovered/TestExitCodeOneReportFormat(integration via built binary +
os/exec)task checkclean (fmt + vet + golangci-lint + full test suite +validate + docs:lint).
Test plan
go test ./tools/coverage-gate/passes locally (15 tests)task checkpassestools/coverage-gate/task checkand/or GHA workflowFiles
Single new package, single new directory:
tools/coverage-gate/main.go(~340 LOC)tools/coverage-gate/main_test.go(~290 LOC, 15 tests)