8.2 KiB
8.2 KiB
Backend Coverage Alignment + Buffer Plan
Date: 2026-02-16 Owner: Planning Agent Status: Active (unit tests + coverage only)
1) Goal and Scope
Goal:
- Determine why local backend coverage and CI/Codecov differ.
- Add enough backend unit tests to create a reliable buffer above the 85% gate.
In scope:
- Backend unit tests only.
- Coverage measurement/parsing validation.
- CI-parity validation steps.
Out of scope:
- E2E/Playwright.
- Integration tests.
- Runtime/security feature changes unrelated to unit coverage.
2) Research Findings (Current Repo)
2.1 CI vs local execution path
- CI backend coverage path uses
codecov-upload.yml→bash scripts/go-test-coverage.sh→ uploadsbackend/coverage.txtwith Codecov flagbackend. - Local recommended path (
test-backend-coverageskill) runs the same script.
2.2 Metric-basis mismatch (explicit)
scripts/go-test-coverage.shcomputes the percentage fromgo tool cover -func, whose summary line istotal: (statements) XX.X%.codecov.ymlproject status for backend is configured withonly: lines.- Therefore:
- Local script output is statement coverage.
- CI gate shown by Codecov is line coverage.
- These are related but not identical metrics and can diverge by about ~0.5-1.5 points in practice.
2.3 Likely mismatch drivers in this repo
- Coverage metric basis:
- Local script: statements.
- Codecov status: lines.
- Exclusion filter differences:
- Script excludes only
internal/traceandintegrationpackages. - Codecov ignore list also excludes extra backend paths/files (for example logger/metrics and Docker-only files).
- Different include/exclude sets can shift aggregate percentages.
- Package-set differences in developer workflows:
- Some local checks use
go test ./... -cover(package percentages) instead of the CI-equivalent script with filtering and upload behavior.
- Cache/artifact variance:
- Go test cache and Codecov carryforward behavior can hide small swings between runs if not cleaned/verified.
3) EARS Requirements
- WHEN backend coverage is evaluated locally, THE SYSTEM SHALL report both statement coverage (from
go tool cover) and CI-relevant line coverage context (Codecov config basis). - WHEN coverage remediation is implemented, THE SYSTEM SHALL prioritize deterministic unit tests in existing test files before adding new complex harnesses.
- WHEN validation is performed, THE SYSTEM SHALL execute the same backend coverage script used by CI and verify output artifacts (
backend/coverage.txt,backend/test-output.txt). - IF local statement coverage is within 0-1 points of the threshold, THEN THE SYSTEM SHALL require additional backend unit tests to produce a safety buffer targeting >=86% CI backend line coverage.
- WHEN evaluating pass/fail semantics, THE SYSTEM SHALL distinguish the effective Codecov pass condition from the engineering buffer target: with
target: 85%andthreshold: 1%incodecov.yml, CI may pass below 85% lines depending on Codecov threshold/rounding logic.
4) Highest-Yield Backend Test Targets (+1% with minimal risk)
Priority 1 (low risk, deterministic, existing test suites):
backend/internal/util/permissions.go
- Boost tests around:
CheckPathPermissionserror branches (permission denied, non-existent path, non-dir path).MapSaveErrorCodeand SQLite-path helpers edge mapping.
- Why high-yield: package currently low (~71% statements) and logic is pure/deterministic.
backend/internal/api/handlers/security_notifications.go
- Extend
security_notifications_test.gofornormalizeEmailRecipientsbranch matrix:- whitespace-only entries,
- duplicate/mixed-case addresses,
- invalid plus valid mixed payloads,
- empty input handling.
- Why high-yield: currently very low function coverage (~17.6%) and no external runtime dependency.
Priority 2 (moderate risk, still unit-level):
backend/internal/api/handlers/system_permissions_handler.go
- Add focused tests around
logAuditnon-happy paths (missing actor, nil audit service, error/no-op branches). - Why: currently low (~25%) and can be exercised with request context + mocks.
backend/internal/api/handlers/backup_handler.go
- Add restore-path negative tests in
backup_handler_test.gousing temp files and invalid backup payloads. - Why: function
Restoreis partially covered (~27.6%); additional branch coverage is feasible without integration env.
Do not prioritize for this +1% buffer:
- CrowdSec deep workflows requiring process/network/file orchestration for marginal gain-per-effort.
- Docker-dependent paths already treated as CI-excluded in Codecov config.
5) Implementation Tasks
Phase A — Baseline and mismatch confirmation
- Capture baseline using CI-equivalent script:
bash scripts/go-test-coverage.sh
- Record:
- Script summary line (
total: (statements) ...). - Computed local statement percentage.
- Existing backend Codecov line percentage from PR check.
- Document delta (statement vs line) for this branch.
Phase B — Add targeted backend unit tests
- Expand tests in:
backend/internal/util/permissions_test.gobackend/internal/api/handlers/security_notifications_test.go
- If additional buffer needed, expand:
backend/internal/api/handlers/system_permissions_handler_test.gobackend/internal/api/handlers/backup_handler_test.go
- Keep changes test-only; no production logic changes unless a test reveals a real bug.
Phase C — Validate against CI-equivalent flow
bash scripts/go-test-coverage.sh | tee backend/test-output.txtgo tool cover -func=backend/coverage.txt | tail -n 1(record statement total).- Confirm no backend test failures in output (
FAILlines). - Push branch and verify Codecov backend status (lines) in PR checks.
6) Exact Validation Sequence (mirror CI as closely as possible)
Run from repository root:
- Environment parity:
export GOTOOLCHAIN=autoexport CGO_ENABLED=1- CI Go-version parity check (must match
.github/workflows/codecov-upload.yml):CI_GO_VERSION=$(grep -E "^ GO_VERSION:" .github/workflows/codecov-upload.yml | sed -E "s/.*'([^']+)'.*/\1/") LOCAL_GO_VERSION=$(go version | awk '{print $3}' | sed 's/^go//') if [ "$LOCAL_GO_VERSION" != "$CI_GO_VERSION" ]; then echo "Go version mismatch: local=$LOCAL_GO_VERSION ci=$CI_GO_VERSION" exit 1 fi
- Clean stale local artifacts:
rm -f backend/coverage.txt backend/test-output.txt
- Execute CI-equivalent backend coverage command:
bash scripts/go-test-coverage.sh 2>&1 | tee backend/test-output.txt
- Verify script metric type and value:
grep -n 'total:' backend/test-output.txtgo tool cover -func=backend/coverage.txt | tail -n 1
- Verify test pass state explicitly:
-
if grep -qE '^FAIL[[:space:]]' backend/test-output.txt; then echo 'unexpected fails' exit 1 fi
- CI confirmation:
- Open PR and check Codecov backend status (lines) for final gate outcome.
7) Risks and Mitigations
Risk 1: Statement/line mismatch remains misunderstood.
- Mitigation: Always record both local statement summary and Codecov line status in remediation PR notes.
Risk 2: Added tests increase flakiness.
- Mitigation: prioritize deterministic pure/helper paths first (
internal/util, parsing/normalization helpers).
Risk 3: Buffer too small for CI variance.
- Mitigation: target >=86.0 backend in CI line metric rather than barely crossing 85.0.
8) Acceptance Criteria
- Investigation completeness:
- Plan documents likely mismatch causes: metric basis, exclusions, package-set differences, cache/artifact variance.
- Metric clarity:
- Plan explicitly states: local script reads Go statement coverage; CI gate evaluates Codecov lines.
- Test scope:
- Only backend unit tests are changed.
- No E2E/integration additions.
- Coverage result:
- Backend Codecov project status passes with practical buffer target >=86.0% lines (engineering target).
- Effective Codecov pass condition is governed by
target: 85%withthreshold: 1%, so CI may pass below 85.0% lines depending on Codecov threshold/rounding behavior.
- Validation parity:
- CI-equivalent script sequence executed and results captured (
backend/coverage.txt,backend/test-output.txt).