ci: let Codecov fail a bad change instead of commenting - #340
Conversation
Both statuses were informational, so nothing could fail and the bot narrated every pull request instead. The project status now compares against the base with a 2% allowance, and the patch status wants 70% on includes/ only. maintenance/ is half the tree's lines and carries no unit tests, so it drags the project total down by a point or two whenever a script is added and would fail any patch target outright. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016qiZSGWHrxkjvFxA8swynp
|
Following up on the missing First, a correction to how I reported itMy earlier note said "no
There are no commit statuses on this repository at all — not from Codecov, not from anything. Everything reports through the Checks API. So the finding holds on both surfaces, and it was not an artefact of which list I read. Worth having stated explicitly either way. What the evidence rules out
What is left, and where to lookThe one other consistent symptom: no Codecov comment on this repository has ever included a project-coverage line. #226, #285, #321, #326 and #336 all report diff coverage and a file table, and none of them carries the usual Two candidates, both needing the dashboard —
The single most useful page is the repository's YAML tab —
That page also answers the one thing I could not verify about this PR at all: whether Codecov's parser accepts Consequences either way
One thing I could not check at allWhether the Codecov checks are in the repository's required-checks list. I have no read access to branch protection or rulesets through this session's GitHub app, and a failing check only blocks a merge if it is required. If No repository-side fix to open a PR for — as far as GitHub can show, this is not something Generated by Claude Code |
Project coverage turns out to be a Codecov Pro feature, and this account is not on it — which is why `codecov/project` has never appeared on any pull request here. The block was describing an enforcement that cannot exist, so it goes. `comment: false` and the `patch` status are unchanged. Patch at 70% on `includes/` is the check that actually runs. Follow-up to #340; the full investigation is in [that thread](#340 (comment)). `uv run --frozen --group lint yamllint --strict .` passes. Codecov's own validator is still unreachable from here, so the file is unvalidated against their parser. --- _Generated by [Claude Code](https://claude.ai/code/session_016qiZSGWHrxkjvFxA8swynp)_ Co-authored-by: Claude <noreply@anthropic.com>
Both statuses were
informational: true, which is the "never fail" setting, so the only thing Codecov did was post a comment on every pull request. This turns the comment off and gives both statuses something they can actually fail on.Where the numbers come from
Codecov's app and API are not reachable from here, but the
codecov/patchcheck run records the project total as itsautotarget, so the history is readable off GitHub:0.00% of diff hit (target 13.62%)34.75% of diff hit (target 19.25%)0.00% of diff hit (target 24.90%)So the project total is around 25%, and it moved five points in three days.
maintenance/is 2561 of the 4932 PHP lines outsidetests/, and it is essentially all uncovered — #326 was six lines ofmaintenance/buildTranslations.phpat 0%, and #285's misses were 74 instoreWebfonts.php, 9 inrewriteScripts.php, 2 inbuildScripts.php, 1 inbuild.php. That is what holds the total at 25%, and it is why an absolute project target is the wrong instrument: any number above today's coverage fails immediately, and any number below it stops being a check the moment coverage rises.What the config does now
Project —
target: auto,threshold: 2%. Compare against the pull request's base rather than a fixed line, and allow a two-point dip. The allowance is sized to the thing that legitimately moves the total: a new maintenance script of 200-400 lines at 0% coverage costs roughly 1-2 points with nothing having regressed. A real regression is much larger — dropping the tests for one mid-sized class underincludes/is worth four or five points, well past the allowance. The trade-off is honest: losing coverage of one small class (~40 statements, ~1.8 points) would slip through. Tightening to 1% closes that but fails on the next maintenance script, which is the failure mode you asked me to avoid.Note that
removed_code_behavioris left at itsadjust_basedefault, so deleting covered code does not itself count as a regression.Patch —
target: 70%, scoped toincludes/. A patch target applied to the whole tree can never pass on amaintenance/-only change — #326 would have failed at any target above zero. Restricting the status toincludes/makes it a real bar for the code that is actually unit-testable, and leaves script changes alone (Codecov passes a status whose paths the diff does not touch). Checked against history: #285 would pass, since itsincludes/lines were 42/43 inWebfonts.phpplus 0/5 inWikvenSettings.php, or 87.5%; #326 and #336 touch noincludes/lines and pass trivially. 70% rather than something higher leaves room for a couple of uncovered guard clauses. The known annoyance is a very smallincludes/diff — four lines with two uncovered is 50% and fails — so 60% is the knob if that shows up in practice.I did not add an
ignore:block formaintenance/. It would raise the reported total sharply and make the patch scoping unnecessary, but it also changes what the README badge means, which is a bigger call than this change.The project status has never actually existed
Worth knowing before relying on it:
codecov/projecthas never appeared on this repository, on any surface, at any point since coverage was introduced.Checked both GitHub surfaces, because they are different lists:
GET /commits/{sha}/check-runs) on fix: inline static bundle icons as data URIs so subpages don't 404 #226, feat: carry ULS webfonts in the export, opt in #285, test: cover bundled webfonts with a Khmer page #321, fix: drain translation jobs by hand again, reverting #311 #326, ci: pin yamllint where Dependabot can see it #336 and this pull request:codecov/patchevery time,codecov/projectnever.GET /commits/{sha}/status) on fix: inline static bundle icons as data URIs so subpages don't 404 #226, feat: carry ULS webfonts in the export, opt in #285, fix: drain translation jobs by hand again, reverting #311 #326, ci: pin yamllint where Dependabot can see it #336 and this pull request:total_count: 0— this repository has no commit statuses at all. Codecov here posts through the Checks API only, so nothing was hiding on the other endpoint.What that rules out:
informational. Both statuses carried it, and patch posted anyway.autotarget is the base commit's project coverage, and it has resolved to a real number every time (13.62%, 19.25%, 24.90%). Codecov computes this repository's project coverage on every pull request — it simply never publishes a status for it.fixes:rewrite or the upload shape. Per-file patch coverage resolves to real repository paths, so the path rewrite and the clover upload are both working.codecov/projectis ever created.Also consistent: no Codecov comment on this repository has ever carried a project-coverage line — every one of them reports diff coverage only. Project-level output appears to be switched off account-side rather than repository-side, which would explain the status and the comment together.
That leaves causes outside this file, and both need the Codecov dashboard to confirm — see the review thread. Until then the
projectblock here may simply be inert, andcodecov/patchis the status that actually enforces anything.Verification
uv run --frozen --group lint yamllint --strict .passes.zizmorrun.codecov/patchis green withCoverage not affected— and posted no comment, where fix: inline static bundle icons as data URIs so subpages don't 404 #226, feat: carry ULS webfonts in the export, opt in #285, test: cover bundled webfonts with a Khmer page #321, fix: drain translation jobs by hand again, reverting #311 #326 and ci: pin yamllint where Dependabot can see it #336 each got one. That is the change working, not just parsing.POST https://codecov.io/validate) is blocked by this environment's egress proxy, andapp.codecov.iois unreachable, so the config was never checked against Codecov's parser.