Skip to content

ci: pre-commit red on main since 2026-08-03 (hadolint), blocking every open PR #1695

Closed as not planned

Description

@cristim

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:

  1. 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.
  2. 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.

Activity

  1. cristim commented on Aug 3, 2026

    @cristim
    MemberAuthor

    Duplicate of #1696, which was filed first for the same problem and is fixed by PR #1697 (merged).

    The root cause turned out to be sharper than this issue states: hadolint's own .pre-commit-hooks.yaml at rev: v2.14.0 declares entry: ghcr.io/hadolint/hadolint hadolint with no image tag, so Docker resolves :latest (currently 2.15.1). The rev: pin only fixes which commit of the hook definition is used, never the image it runs — so this was not a digest that drifted, it was a hook that was never image-pinned in the first place. Verified: docker run ghcr.io/hadolint/hadolint:v2.14.0 hadolint --version -> 2.14.0; :latest -> 2.15.1.

    No Dockerfile changes were needed or made. All four findings were new-rule noise from 2.15.x: DL3066 fires on any named USER (all three are legitimate non-root switches after adduser/addgroup), and DL3025 fired on HEALTHCHECK's embedded CMD sub-clause rather than the real ENTRYPOINT/CMD (already exec-form). Converting that to JSON form is not even possible without breaking the || exit 1 fallback, so editing the Dockerfiles would have introduced a bug for no gain.

    Closing as duplicate. The stray branch chore/1695-hadolint-digest-pin has no PR against it and can be deleted at leisure.

  2. added 3 commits that reference this issue on Aug 3, 2026
    bd4aad3
    d7f6a6a
    1e1e7e4
  3. added a commit that references this issue on Sep 27, 2026
    1f70316
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions