The pre-commit workflow is failing on main and therefore on every open PR. Noticed while landing PR #1682, whose diff touches zero Dockerfiles yet inherits the red.
Symptom
pre-commit run --all-files (.github/workflows/pre-commit.yml:272) fails on the hadolint-docker hook, after all 3 retry attempts:
Lint Dockerfiles............................................................Failed
- hook id: hadolint-docker
- exit code: 1
Dockerfile:149 DL3066 info: Non-numeric user-id may not be resolvable by host system
Dockerfile:165 DL3025 warning: Use arguments JSON notation for CMD and ENTRYPOINT arguments
Dockerfile.dev:62 DL3066 info: Non-numeric user-id may not be resolvable by host system
Dockerfile.test:21 DL3066 info: Non-numeric user-id may not be resolvable by host system
Verified
- Failing on
main itself, not only on PR branches: the four most recent pre-commit runs on main (a8266881a, 9de48ae74, f6bb36ab4, cd4ee031f, all 2026-08-03) are failure, with byte-identical output.
- Last green on
main was 6ded40125 (2026-07-28).
- Nothing relevant changed in between. The four commits landed since
6ded40125 touch no Dockerfile*, no .hadolint.yaml, and no .pre-commit-config.yaml. Last change to Dockerfile was a840ed1d4 (2026-07-10); .hadolint.yaml has not changed since 505480573 (2026-02-20).
- hadolint is pinned in
.pre-commit-config.yaml at rev: v2.14.0.
So the repository inputs are unchanged across the green-to-red transition.
Likely cause (not yet confirmed)
hadolint-docker runs through pre-commit's Docker image language, so the pinned rev fixes the tag, not the image digest. An upstream rebuild or re-tag of hadolint/hadolint:v2.14.0 would change the ruleset or default failure threshold underneath an unchanged pin. That matches the evidence (inputs unchanged, behaviour changed) but I have not diffed the image digests, so treat it as the leading hypothesis rather than an established root cause.
Worth ruling out first: whether the hook previously resolved to a cached image on the runner and now pulls a fresh one.
Fix direction
Whatever the root cause, the two decisions are separable:
- Restore a green gate. Either fix the four findings in the Dockerfiles (
DL3025 is a genuine correctness nit: exec-form CMD/ENTRYPOINT avoids the shell wrapper and makes signal handling work; DL3066 is about non-numeric USER), or pin the hook by digest so behaviour stops moving on its own.
- Do not suppress. Adding
DL3025/DL3066 to the ignored: list in .hadolint.yaml would turn the gate green without addressing either the findings or the fact that a pinned tool changed behaviour under a pin. If they are genuinely not worth fixing, that should be a recorded decision with a justification, not a quiet ignore entry.
Pinning by digest is the durable half regardless: see the existing pattern in #1297 / #1394 for tool-version alignment across ci.yml, pre-commit.yml and the Makefile.
Blast radius
Every open PR shows a red pre-commit check that is unrelated to its own diff, which trains reviewers to ignore that signal. That is the expensive part.
The
pre-commitworkflow is failing onmainand therefore on every open PR. Noticed while landing PR #1682, whose diff touches zero Dockerfiles yet inherits the red.Symptom
pre-commit run --all-files(.github/workflows/pre-commit.yml:272) fails on thehadolint-dockerhook, after all 3 retry attempts:Verified
mainitself, not only on PR branches: the four most recentpre-commitruns onmain(a8266881a,9de48ae74,f6bb36ab4,cd4ee031f, all 2026-08-03) arefailure, with byte-identical output.mainwas6ded40125(2026-07-28).6ded40125touch noDockerfile*, no.hadolint.yaml, and no.pre-commit-config.yaml. Last change toDockerfilewasa840ed1d4(2026-07-10);.hadolint.yamlhas not changed since505480573(2026-02-20)..pre-commit-config.yamlatrev: v2.14.0.So the repository inputs are unchanged across the green-to-red transition.
Likely cause (not yet confirmed)
hadolint-dockerruns through pre-commit's Docker image language, so the pinnedrevfixes the tag, not the image digest. An upstream rebuild or re-tag ofhadolint/hadolint:v2.14.0would change the ruleset or default failure threshold underneath an unchanged pin. That matches the evidence (inputs unchanged, behaviour changed) but I have not diffed the image digests, so treat it as the leading hypothesis rather than an established root cause.Worth ruling out first: whether the hook previously resolved to a cached image on the runner and now pulls a fresh one.
Fix direction
Whatever the root cause, the two decisions are separable:
DL3025is a genuine correctness nit: exec-formCMD/ENTRYPOINTavoids the shell wrapper and makes signal handling work;DL3066is about non-numericUSER), or pin the hook by digest so behaviour stops moving on its own.DL3025/DL3066to theignored:list in.hadolint.yamlwould turn the gate green without addressing either the findings or the fact that a pinned tool changed behaviour under a pin. If they are genuinely not worth fixing, that should be a recorded decision with a justification, not a quiet ignore entry.Pinning by digest is the durable half regardless: see the existing pattern in #1297 / #1394 for tool-version alignment across
ci.yml,pre-commit.ymland theMakefile.Blast radius
Every open PR shows a red
pre-commitcheck that is unrelated to its own diff, which trains reviewers to ignore that signal. That is the expensive part.