--- name: check-patch-coverage description: >- Verify approximate Go patch coverage meets the repo's Codecov patch gate: 80% target, 75% enforced floor (5% threshold). Use after writing or updating Go production code — before committing — to catch coverage gaps that would fail the codecov/patch status check. --- # Check Patch Coverage Verify that new or changed Go production code meets the Codecov **patch coverage** gate in [`.codecov.yml`](../../.codecov.yml) before committing. The **target is 80%** with a **5% threshold**, so `codecov/patch` passes at **≥ 75%**. Codecov PR comments still mark ✗ below 80% even when that status check is green. Target 80% locally to stay above both signals. ## When to use - After implementing or modifying Go production code under `cmd/` or `internal/` (files that are **not** `_test.go`). - After adding tests for new code — to confirm coverage is sufficient. - When the fix agent is addressing a coverage-related failure. ## When to skip - Test-only changes (no production `.go` files modified). - Documentation, config, or generated-code-only changes. - Files listed in `.codecov.yml` `ignore:` — these are excluded from coverage enforcement. ## Procedure ### 1. Identify changed production files Determine which non-test Go files you changed relative to the target branch. **Stage new files first** (`git add`) — `git diff --name-only` only sees tracked or staged files, so an unstaged new file would be invisible and the check would silently skip it. ```bash CHANGED_GO=$(git diff --name-only main -- '*.go' | grep -v '_test.go') echo "$CHANGED_GO" ``` If the list is empty, patch coverage does not apply — stop here. ### 2. Determine affected packages ```bash PKGS=$(echo "$CHANGED_GO" | xargs -I{} dirname {} | sort -u | sed 's|^|./|') echo "$PKGS" ``` ### 3. Check for packages with no test files Before running coverage, check whether each affected package actually contains test files. Go's `go test -coverprofile` only attributes coverage to the package under test — a package with zero `_test.go` files produces no coverage data at all, and Codecov will report 0% for every changed line. ```bash MISSING_TESTS="" for pkg_dir in $PKGS; do dir="${pkg_dir#./}" if ! ls "$dir"/*_test.go >/dev/null 2>&1; then echo "⚠ Package $dir has no test files — codecov/patch will report 0% coverage." echo " Create a _test.go file with direct unit tests for new/modified exported functions." MISSING_TESTS="$MISSING_TESTS $dir" fi done ``` If any packages were flagged: **stop and create test files** in those packages before continuing. The 75% enforced floor cannot be met when no coverage profile is generated for a package. Treat this as a coverage gap regardless of the threshold — add at least one `_test.go` file with direct unit tests for the new or modified exported functions, then re-run from step 1. ### 4. Run tests with a cover profile ```bash go test -coverprofile=coverage.out -count=1 $PKGS ``` If tests fail, fix them first — coverage is meaningless on broken code. ### 5. Check per-function coverage on changed files For each changed file, inspect coverage: ```bash for f in $CHANGED_GO; do echo "=== $f ===" go tool cover -func=coverage.out | grep "$f" \ || echo "⚠ No coverage data for $f — this file's package may lack test files. See step 3." done ``` If any file shows no coverage data, go back to step 3 and verify the package has test files. A `(no coverage data)` result means Codecov will report 0% for that file's changed lines. Each output line shows `file:line: function coverage%`. ### 6. Assess against the 80% target (75% floor) Look at the functions you added or modified: - **All functions ≥ 80%:** Coverage is sufficient. Proceed to commit. - **Some functions below 80%:** Add or extend `_test.go` files to cover the missing lines. Focus on: - New functions you added (these must be tested) - Modified functions where you added new branches or error paths - Functions at 0% that contain logic (not just simple getters/setters) After adding tests, re-run from step 4 and re-check. ### 7. Visual inspection (optional, for complex cases) If function-level coverage is borderline or the function has complex branching: ```bash go tool cover -html=coverage.out ``` This opens an HTML view showing exactly which lines are covered (green) and which are not (red). Use this to target your test additions. ## Understanding the approximation This procedure approximates Codecov's **line-level patch coverage** using Go's **function-level coverage** (`go tool cover -func`). The local check is coarser — Codecov counts individual lines in the diff, while `go tool cover -func` reports per-function percentages. The `codecov/patch` status check **enforces 75%** (80% target minus the 5% threshold in `.codecov.yml`). Codecov PR comments still mark ✗ when coverage is below the **80% target**, even if the status check is green. Aim for **≥ 80%** on touched functions so both the comment glyph and the status check stay consistent, and to cover the approximation gap between function-level and line-level metrics. ## Thresholds reference From [`.codecov.yml`](../../.codecov.yml): - **Patch coverage target:** 80% - **Enforced floor (`codecov/patch` status check):** 75% (5% threshold) - **Codecov PR comment glyph:** ✗ below the 80% target, even if the status check passes - **Project coverage:** must not drop more than 1% below base branch