Skip to content

ci: pin yamllint where Dependabot can see it - #336

Merged
lens0021 merged 1 commit into
mainfrom
claude/yamllint-uv
Aug 15, 2026
Merged

ci: pin yamllint where Dependabot can see it#336
lens0021 merged 1 commit into
mainfrom
claude/yamllint-uv

Conversation

@lens0021

Copy link
Copy Markdown
Collaborator

Applies chaotic-ground/setup-mago#14 here — the same pipx install yamllint==1.38.0 line was in lint.yml.

-      - run: pipx install yamllint==1.38.0
-      - run: yamllint --strict .
+      - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d  # v10.0.1
+      - run: uv run --frozen --group lint yamllint --strict .

The version moves into pyproject.toml, which Dependabot's uv ecosystem reads. uv.lock comes with it, so yamllint's own dependencies (pyyaml, pathspec) are pinned too — pipx install resolved those fresh on every run. setup-uv is v10.0.1 rather than setup-mago's v9.0.0; Dependabot will converge them.

The pin inventory this came out of

Looking for others like it, six versions in this repo are invisible to a package manager:

pin where tracked by
SifterSearch v0.6.1 Dockerfile ARG updatecli
mago 1.46.0 composer.json extra updatecli
biome 2.5.8 biome.json $schema updatecli
yamllint 1.38.0 lint.yml pipx install Dependabot, after this
taplo 0.10.0 lint.yml with: nothing
updatecli v0.120.1 updatecli.yml with: nothing

TRANSLATE_VERSION and ULS_VERSION are REL1_46, a MediaWiki release branch being followed on purpose, so they are not pins.

Why taplo and updatecli stay manual

Both live in a workflow with: input, which needs updatecli's yaml target — and that target reformats the whole file. Applied to lint.yml it drops every blank line and halves the two spaces before each # vX comment, which yamllint --strict then rejects:

18:73  warning  too few spaces before comment: expected 2  (comments)
… 18 of them, exit 2

Same failure mode as the json target on composer.json (#334). This is not a local quirk: the official ghcr.io/updatecli/policies/updatecli/githubaction policy uses exactly that yaml target, so the published policy for updatecli's own pin would break this repo too.

A file-target regex would work — backreferences are supported — but it has to anchor across the indentation and the # v2 comment to stay unique, which is the kind of brittle hand-written pattern worth avoiding for two pins that move about twice a year.

Verified locally

  • uv lock resolves 4 packages; uv run --frozen --group lint yamllint --version reports 1.38.0, and yamllint --strict . passes on the tree.
  • taplo fmt --check and taplo check pass with pyproject.toml added. uv.lock is not matched by taplo's **/*.toml include, so it is not linted.
  • biome ci is unchanged — its one warning is pre-existing, in CSS this branch does not touch.
  • .venv/ is gitignored.

Generated by Claude Code

The version sat in a pipx install line, which no package manager reads,
so it was one of the pins nothing was watching. A uv dependency group is
a manifest Dependabot already knows how to bump, and the lockfile pins
yamllint's own dependencies too, which the pipx install resolved fresh
on every run.

Follows chaotic-ground/setup-mago#14. The other two loose pins, taplo
and updatecli, stay manual: both live in a workflow "with:" input, and
updatecli's yaml target reformats the file it edits -- it drops blank
lines and halves the space before a comment, which yamllint --strict
then rejects.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016qiZSGWHrxkjvFxA8swynp
@codecov

codecov Bot commented Aug 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@lens0021
lens0021 marked this pull request as ready for review August 15, 2026 13:11
@lens0021
lens0021 merged commit 34e12dd into main Aug 15, 2026
20 checks passed
@lens0021
lens0021 deleted the claude/yamllint-uv branch August 15, 2026 13:11
lens0021 added a commit that referenced this pull request Aug 15, 2026
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/patch` check run records the project total as its `auto`
target, so the history is readable off GitHub:

| PR | date | check output |
|---|---|---|
| [#226](#226) | 2026-07-19
| `0.00% of diff hit (target 13.62%)` |
| [#285](#285) | 2026-08-12
| `34.75% of diff hit (target 19.25%)` |
| [#326](#326) | 2026-08-15
| `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 outside `tests/`, and
it is essentially all uncovered — #326 was six lines of
`maintenance/buildTranslations.php` at 0%, and #285's misses were 74 in
`storeWebfonts.php`, 9 in `rewriteScripts.php`, 2 in `buildScripts.php`,
1 in `build.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 under `includes/` 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_behavior` is left at its `adjust_base` default,
so deleting covered code does not itself count as a regression.

**Patch — `target: 70%`, scoped to `includes/`.** A patch target applied
to the whole tree can never pass on a `maintenance/`-only change — #326
would have failed at any target above zero. Restricting the status to
`includes/` 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 its `includes/` lines were 42/43 in `Webfonts.php`
plus 0/5 in `WikvenSettings.php`, or 87.5%; #326 and #336 touch no
`includes/` lines and pass trivially. 70% rather than something higher
leaves room for a couple of uncovered guard clauses. The known annoyance
is a very small `includes/` 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 for `maintenance/`. 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/project` has never
appeared on this repository**, on any surface, at any point since
coverage was introduced.

Checked both GitHub surfaces, because they are different lists:

- **Check runs** (`GET /commits/{sha}/check-runs`) on #226, #285, #321,
#326, #336 and this pull request: `codecov/patch` every time,
`codecov/project` never.
- **Commit statuses** (`GET /commits/{sha}/status`) on #226, #285, #326,
#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:

- **Not `informational`.** Both statuses carried it, and patch posted
anyway.
- **Not a missing base report or an unresolvable total.** The patch
status's `auto` target *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.
- **Not the `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.
- **Not branch protection.** Protection can require or hide a check, but
it cannot stop one being created, and no `codecov/project` is 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 `project`
block here may simply be inert, and `codecov/patch` is the status that
actually enforces anything.

## Verification

- `uv run --frozen --group lint yamllint --strict .` passes.
- No workflow touched, so no `zizmor` run.
- **The comment is gone.** Codecov reported on this pull request —
`codecov/patch` is green with `Coverage not affected` — and posted no
comment, where #226, #285, #321, #326 and #336 each got one. That is the
change working, not just parsing.
- **Not verified: the targets themselves.** This pull request changes no
PHP, so nothing exercised the 2% threshold or the 70% patch bar. Codecov
also generally reads its config from the base branch for a comparison,
so the numbers are unproven until something with PHP in it lands on top
of this.
- **Not verified: the schema.** Codecov's own validator (`POST
https://codecov.io/validate`) is blocked by this environment's egress
proxy, and `app.codecov.io` is unreachable, so the config was never
checked against Codecov's parser.

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants