ci(coverage): enforce PR coverage floor in pytest, not via Codecov (LAB-3609) - #291
Conversation
…AB-3609) Add --cov-fail-under=82 to the final PR pytest invocation so the combined unit+critical total is gated inside the job, independent of the Codecov upload succeeding. A dropped/degraded upload (fork-PR tokenless 429, Codecov outage) can no longer answer the total-coverage question with a stale carryforward. Codecov keeps the finer-grained new-code (patch) status. - .github/workflows/ci.yml: floor on the --cov-append final run; residual-risk comment rewritten (total floor now local; Codecov owns patch). - Makefile: test-cov floor 60 -> 82, mirrors CI (full suite clears it). - CONTRIBUTING.md: document the enforced total floor. 82 = current main PR-path cumulative TOTAL 84.20% (py3.12, only PR matrix version) minus codecov.yml declared 2% tolerance, floored.
Kody Review CompleteGreat news! 🎉 Keep up the excellent work! 🚀 Kody Guide: Usage and ConfigurationInteracting with Kody
Current Kody ConfigurationReview OptionsThe following review options are enabled or disabled:
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Team Run ID: 📒 Files selected for processing (3)
Included review availability: 1 review is currently available. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour. WalkthroughThe pull request raises the enforced total pytest coverage threshold from 60% to 82% in local and CI commands. It also documents the distinction between pytest total coverage enforcement and Codecov patch coverage reporting. ChangesCoverage threshold enforcement
Priority: ⬇️ Low Estimated code review effort: 1 (Trivial) | ~5 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to The 82% total-coverage floor is consistently enforced in pull-request CI and the local coverage target, with no actionable merge-blocking risk identified. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
What & why
The PR coverage floor cachekit-py declares (
codecov.yml: projectauto± 2%, patch 80%,carryforward: trueon every flag) is computed only fromcoverage.xmlreaching Codecov. Any path where that upload is dropped or skipped (a fork PR's tokenless 429, a Codecov/keybase outage) leaves the declared floor stale-green or absent — on exactly the least-trusted contributions.This moves the total-coverage floor into the test job itself:
--cov-fail-under=82on the final PR pytest invocation. A PR whose combined coverage falls below the floor now fails theTestsjob inside pytest, with no dependency on the Codecov upload. Codecov keeps the finer-grained new-code (patch) status as a reporting-only signal.Closes LAB-3609.
The floor:
--cov-fail-under=82Placed on the final
--cov-appendinvocation (tests/critical/) so it evaluates the combinedtests/unit+tests/criticalcumulative total, not the first sub-suite alone. (Confirmed in the run below: the unit-only intermediate TOTAL is 82.70%, the combined--cov-appendTOTAL is 84.50% — a config-level[tool.coverage.report] fail_underwould gate the 82.70% intermediate at the wrong point, which is why the flag lives on the final invocation.)Derivation
Rule (mirrors
codecov.yml's declared 2% project tolerance, not a new number): PR-run floor = lowest cumulative TOTAL across the PR matrix on a same-repo PR run, minus 2, floored to a whole percent. The PR matrix is Python 3.12 only (ci.yml:pull_request→["3.12"]), so the "matrix" is one version.--cov-appendTOTAL (unit + critical)floor(84.50 − 2) = floor(82.50) = 82.Proof of failure (floor above measured → red inside pytest)
Local reproduction of the exact PR path (unit, then critical
--cov-append) on py3.12, with the floor set above the measured total:pytest exits non-zero with
FAIL Required test coverage of N% not reached, in the test step — before theUpload coverage to Codecovstep would run.Proof of pass
This PR's own CI is green on every Python version in the PR matrix (3.12) with
--cov-fail-under=82in place — Tests (Python 3.12), 2m10s,Required test coverage of 82% reached. Total coverage: 84.50%.Floor independent of Codecov
The coverage pass/fail is decided in the
Run tests (PRs)step, which runs beforeUpload coverage to Codecovin the same job (verified in the run log's step order). With the upload step's outcome held constant, the job's red/green on coverage is already settled by the pytest--cov-fail-understep; the upload's success no longer gates the floor.Other changes
Makefiletest-cov: floor60 → 82, mirroring the CI floor. That target runs the full suite (≥ the PR path's unit+critical coverage), so it clears the floor with margin; a comment records the contract to keep the two literals in step.ci.ymlresidual-risk comment: rewritten — the total floor is now enforced locally; Codecov solely owns the patch (new-code) status, which stays carryforward-capable (the narrowed, accepted residual). The old "the real fix … tracked separately" pointer is removed now that the fix has landed.CONTRIBUTING.md: documents the enforced total floor. The literal itself is not repeated in the doc (it points atci.yml), so the value has exactly two authoritative homes —ci.ymland theMakefile— both under the "keep in step" contract.Scope
Total-coverage safety net only. Patch-level (diff) coverage stays a Codecov patch status (not enforced locally — out of scope).
codecov.ymltargets/flags/carryforward untouched. The push-to-mainfull-suite path is not a PR gate and is left uncapped.