Run all linting in Docker via Dockerfile.lint + script/lint #109

Open
opened 2026-08-10 13:14:12 +02:00 by clawbot · 0 comments
Collaborator

Owner ruling, sneak 2026-08-09: every lint run happens inside a Docker container, invoked through the script/ entrypoint. Docker is always available. Linting runs independently and does not need a cache. He has directed a PR for every repo not already set up this way.

Reference implementation is sneak/homoicon, which already does exactly this — copy its shape.

Dockerfile.lint at the repo root:

FROM golangci/golangci-lint:v2.12.2@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240

WORKDIR /src

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN golangci-lint run --config .golangci.yml ./...

script/lint becomes a thin wrapper that builds it. Linting as a build step means a successful build IS a clean lint, and it works even where the docker daemon is remote and bind mounts are impossible.

Two things to get right, both of which would otherwise ship a false green:

  1. A cached build lints nothing. docker build -f Dockerfile.lint . on an unchanged tree returns success in well under a second having run no linter. Since caching is explicitly waived here, force the lint layers to execute.
  2. golangci-lint config verify fetches its JSON schema over an unpinned live HTTPS call. If you include that step it makes linting network-dependent and breaks hash-pinning. Decide deliberately.

Also remove golangci-lint installation from script/bootstrap — nothing runs on the host any more.

This is directly relevant here: several PRs in this repo rested on host lint results, and the host linter in this repo has differed from the pinned one.

Definition of done

  • script/lint runs the linter only in Docker; no host golangci-lint path remains.
  • Two consecutive script/lint runs on an unchanged tree both demonstrably execute the linter.
  • Negative control: introduce a deliberate lint violation, confirm it fails with that specific finding, revert, confirm clean.
  • make check still green.

Canonical tracking issue: sneak/prompts#40

Owner ruling, sneak 2026-08-09: every lint run happens inside a Docker container, invoked through the `script/` entrypoint. Docker is always available. Linting runs independently and does not need a cache. He has directed a PR for every repo not already set up this way. Reference implementation is `sneak/homoicon`, which already does exactly this — copy its shape. `Dockerfile.lint` at the repo root: ```dockerfile FROM golangci/golangci-lint:v2.12.2@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240 WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . RUN golangci-lint run --config .golangci.yml ./... ``` `script/lint` becomes a thin wrapper that builds it. Linting as a build step means a successful build IS a clean lint, and it works even where the docker daemon is remote and bind mounts are impossible. Two things to get right, both of which would otherwise ship a false green: 1. **A cached build lints nothing.** `docker build -f Dockerfile.lint .` on an unchanged tree returns success in well under a second having run no linter. Since caching is explicitly waived here, force the lint layers to execute. 2. **`golangci-lint config verify` fetches its JSON schema over an unpinned live HTTPS call.** If you include that step it makes linting network-dependent and breaks hash-pinning. Decide deliberately. Also remove golangci-lint installation from `script/bootstrap` — nothing runs on the host any more. This is directly relevant here: several PRs in this repo rested on host lint results, and the host linter in this repo has differed from the pinned one. ## Definition of done - `script/lint` runs the linter only in Docker; no host golangci-lint path remains. - Two consecutive `script/lint` runs on an unchanged tree both demonstrably execute the linter. - Negative control: introduce a deliberate lint violation, confirm it fails with that specific finding, revert, confirm clean. - `make check` still green. Canonical tracking issue: https://git.eeqj.de/sneak/prompts/issues/40
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#109