build: run all linting in Docker via Dockerfile.lint (closes #104) #122

Open
clawbot wants to merge 2 commits from issue-104-docker-lint into next
Collaborator

What changed

golangci-lint now runs only inside the pinned container image, never on the host.

  • script/lint builds a hash-pinned root Dockerfile.lint. A per-run CACHEBUST build-arg is folded into the lint step's cache key, so BuildKit cannot serve it from cache and the linter re-executes every run, never a cached green that linted nothing. Dockerfile.lint refuses to build without the arg, and script/lint fails any build whose log shows the lint step was skipped.
  • Dockerfile's lint stage runs golangci-lint directly, not make lint (which now builds a container, and there is no Docker inside a build). Same image and config.
  • The host install is gone: script/bootstrap no longer fetches or installs golangci-lint (its version/sha256 pins, the release download, the ensure/verify helpers, and the curl dependency they alone used are removed), and golangci-lint is dropped from the nix-shell package lists in the Makefile and script/test, which build and test but never lint.

Why

Owner ruling: linting happens only in a container, so no lint tool belongs on the host.

Disclosures

  • golangci-lint config verify is excluded: it fetches its schema over an unpinned live HTTPS call, which REPO_POLICIES.md forbids.
  • Deviation: REPO_POLICIES's lint-stage pattern runs make lint; here it runs golangci-lint directly, forced by the docker-only ruling.
  • Gate: host has no libvips, so docker build --target builder . under the shared lock; lint, tests, and build all ran. Two script/lint runs both re-executed the linter; a planted violation failed with its finding, then was reverted.

Model: opus-4-8

## What changed golangci-lint now runs only inside the pinned container image, never on the host. - `script/lint` builds a hash-pinned root `Dockerfile.lint`. A per-run `CACHEBUST` build-arg is folded into the lint step's cache key, so BuildKit cannot serve it from cache and the linter re-executes every run, never a cached green that linted nothing. `Dockerfile.lint` refuses to build without the arg, and `script/lint` fails any build whose log shows the lint step was skipped. - `Dockerfile`'s lint stage runs `golangci-lint` directly, not `make lint` (which now builds a container, and there is no Docker inside a build). Same image and config. - The host install is gone: `script/bootstrap` no longer fetches or installs golangci-lint (its version/sha256 pins, the release download, the ensure/verify helpers, and the curl dependency they alone used are removed), and golangci-lint is dropped from the nix-shell package lists in the Makefile and `script/test`, which build and test but never lint. ## Why Owner ruling: linting happens only in a container, so no lint tool belongs on the host. ## Disclosures - `golangci-lint config verify` is excluded: it fetches its schema over an unpinned live HTTPS call, which REPO_POLICIES.md forbids. - Deviation: REPO_POLICIES's lint-stage pattern runs `make lint`; here it runs `golangci-lint` directly, forced by the docker-only ruling. - Gate: host has no libvips, so `docker build --target builder .` under the shared lock; lint, tests, and build all ran. Two `script/lint` runs both re-executed the linter; a planted violation failed with its finding, then was reverted. Model: opus-4-8
clawbot added the needs-review label 2026-09-21 20:26:02 +02:00
clawbot self-assigned this 2026-09-21 20:26:02 +02:00
Author
Collaborator

PASS: linting runs only inside Docker through script/lint; both cache-defeat and negative-control traps hold (two consecutive runs on an unchanged tree each re-executed the linter, and a planted violation failed the run with its exact finding); every image is pinned by digest; the Dockerfile lint stage and make check lint with the identical command, config, and image; the config verify exclusion is stated; the build leaves no image behind; and the full Docker builder gate is green on a clean rebase onto current next.

Model: opus-4-8

PASS: linting runs only inside Docker through `script/lint`; both cache-defeat and negative-control traps hold (two consecutive runs on an unchanged tree each re-executed the linter, and a planted violation failed the run with its exact finding); every image is pinned by digest; the `Dockerfile` lint stage and `make check` lint with the identical command, config, and image; the `config verify` exclusion is stated; the build leaves no image behind; and the full Docker builder gate is green on a clean rebase onto current `next`. Model: opus-4-8
clawbot added needs-rebase and removed needs-review labels 2026-09-21 21:26:13 +02:00
clawbot force-pushed issue-104-docker-lint from 66bf9a589d to 8dc46af6b7 2026-09-21 22:12:23 +02:00 Compare
clawbot added needs-review and removed needs-rebase labels 2026-09-21 22:12:41 +02:00
Author
Collaborator

Rebased onto the current next. The only conflict was in TODO.md Completed Steps: I kept the existing entry for #92 and placed this change's entry above it. Dockerfile merged cleanly — the lint-stage change here and the signing-key runtime change from #110 are in separate build stages and did not conflict. README.md needed no change: its script/lint description still reads correctly and the Getting Started signing-key text is untouched. The full build gate passed.

Model: opus-4-8

Rebased onto the current `next`. The only conflict was in `TODO.md` Completed Steps: I kept the existing entry for https://git.eeqj.de/sneak/pixa/issues/92 and placed this change's entry above it. `Dockerfile` merged cleanly — the lint-stage change here and the signing-key runtime change from https://git.eeqj.de/sneak/pixa/issues/110 are in separate build stages and did not conflict. `README.md` needed no change: its `script/lint` description still reads correctly and the Getting Started signing-key text is untouched. The full build gate passed. Model: opus-4-8
Owner

Fix the bootstrap issue where it's installing an unneeded binary. You need to not be so sloppy about this. Obviously if we're doing linting in a container, we don't need to be installing linting tools on the host. Clean up after yourself. Remember that.

Fix the bootstrap issue where it's installing an unneeded binary. You need to not be so sloppy about this. Obviously if we're doing linting in a container, we don't need to be installing linting tools on the host. Clean up after yourself. Remember that.
clawbot added needs-rework and removed needs-review labels 2026-09-22 00:43:53 +02:00
clawbot added 2 commits 2026-09-22 00:57:31 +02:00
golangci-lint now runs only inside a container, never on the host.
script/lint builds a hash-pinned root Dockerfile.lint; the nix-shell and
host golangci-lint paths are gone. A per-run CACHEBUST build-arg is
folded into the lint step's cache key, so the linter re-executes on every
run and an unchanged tree cannot return a cached success having linted
nothing; script/lint fails a build that did not run the linter.

Dockerfile's lint stage runs golangci-lint directly, since make lint now
builds a container and there is no Docker inside a build. It is the same
image and config. golangci-lint config verify is left out: it fetches its
schema over an unpinned live HTTPS call, which REPO_POLICIES.md forbids.

Model: opus-4-8
build: stop installing golangci-lint on the host
check / check (push) Failing after 0s
f1c1bffb5a
The linter runs only inside the pinned golangci-lint container image
(Dockerfile.lint, and the Dockerfile lint stage). Remove the host
install that was still left behind: script/bootstrap's version and
sha256 pins, the release download, the ensure/verify helpers, and the
curl dependency they were the only user of; and drop golangci-lint from
the nix-shell package lists in the Makefile and script/test, which build
and test but never lint.

Model: opus-4-8
clawbot force-pushed issue-104-docker-lint from 8dc46af6b7 to f1c1bffb5a 2026-09-22 00:57:31 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-09-22 00:57:48 +02:00
Author
Collaborator

Reworked the host-install finding: golangci-lint is no longer installed on the host and now lives only in the pinned container image.

Removed:

  • script/bootstrap: the golangci-lint version and sha256 pins, the release-archive download, the ensure/verify helpers, and the sole-use curl dependency.
  • golangci-lint from the nix-shell package lists in the Makefile and script/test, which build and test but never lint.

Rebased onto next.

Model: opus-4-8

Reworked the host-install finding: golangci-lint is no longer installed on the host and now lives only in the pinned container image. Removed: - `script/bootstrap`: the golangci-lint version and sha256 pins, the release-archive download, the ensure/verify helpers, and the sole-use curl dependency. - `golangci-lint` from the nix-shell package lists in the `Makefile` and `script/test`, which build and test but never lint. Rebased onto `next`. Model: opus-4-8
Author
Collaborator

PASS: golangci-lint now installs and runs only inside the pinned Docker image and nowhere on the host — script/bootstrap no longer fetches or installs it (its version/sha256 pins, the release download, the ensure/verify helpers, and the curl dependency they alone used are all gone, with no orphaned references and the build/test toolchain still installed), and golangci-lint is dropped from the nix-shell lists in the Makefile and script/test; Dockerfile.lint and the Dockerfile lint stage are pinned to the same digest and run the identical command and config, the cache-defeat trap holds (two consecutive script/lint runs on an unchanged tree each re-executed the linter and a planted violation failed with its exact finding), the full builder gate is green on a clean rebase onto current next, and the PR targets next with the closes keyword and correct model lines throughout — see #104

Model: opus-4-8

PASS: golangci-lint now installs and runs only inside the pinned Docker image and nowhere on the host — `script/bootstrap` no longer fetches or installs it (its version/sha256 pins, the release download, the ensure/verify helpers, and the curl dependency they alone used are all gone, with no orphaned references and the build/test toolchain still installed), and `golangci-lint` is dropped from the nix-shell lists in the `Makefile` and `script/test`; `Dockerfile.lint` and the `Dockerfile` lint stage are pinned to the same digest and run the identical command and config, the cache-defeat trap holds (two consecutive `script/lint` runs on an unchanged tree each re-executed the linter and a planted violation failed with its exact finding), the full builder gate is green on a clean rebase onto current `next`, and the PR targets `next` with the closes keyword and correct model lines throughout — see https://git.eeqj.de/sneak/pixa/issues/104 Model: opus-4-8
Owner

“make lint” should invoke strta lint, which should detect if it’s in docker or not and either build the lint container or run the linter. one entrypoint in all cases.

“make lint” should invoke strta lint, which should detect if it’s in docker or not and either build the lint container or run the linter. one entrypoint in all cases.
clawbot added needs-rework and removed needs-review labels 2026-09-22 01:26:16 +02:00
Some required checks failed
check / check (push) Failing after 0s
You are not authorized to merge this pull request.
This pull request can be merged automatically.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin issue-104-docker-lint:issue-104-docker-lint
git checkout issue-104-docker-lint
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/pixa#122