# Dockerfile.lint: the one and only path that runs golangci-lint. # # golangci-lint is never installed on the host; it runs only inside this # build. A clean build of this file therefore IS a clean lint over the # whole tree. It runs the same linter and config as Dockerfile's lint # stage, pinned to the same image so the two cannot drift to different # linter versions. # # golangci/golangci-lint:v2.12.2-alpine, 2026-08-07 FROM golangci/golangci-lint:v2.12.2-alpine@sha256:91b27804074a0bacea298707f016911e60cf0cdbc6c7bf5ccacb5f0606d18d60 # pixa is CGO/libvips: the type-aware linters compile every package, so # this image needs the same C libraries the build does. RUN apk add --no-cache build-base vips-dev libheif-dev pkgconfig WORKDIR /src # Modules first for layer caching; go.mod/go.sum settle this layer's # result, so it may safely be reused between runs. COPY go.mod go.sum ./ RUN go mod download COPY . . # Caching is deliberately waived for the lint step: an unchanged tree # must still run the linter, not return a cached success in well under a # second having linted nothing. CACHEBUST carries a value that differs # on every run (script/lint supplies it and refuses to build without # one). The lint RUN below references it, so BuildKit cannot serve that # step from cache. Keep the ${CACHEBUST} reference on that step: dropping # it lets the linter cache again and report a green that linted nothing. ARG CACHEBUST RUN test -n "${CACHEBUST}" || { \ echo "Dockerfile.lint requires the CACHEBUST build-arg; build it via script/lint." >&2; \ exit 1; } # `golangci-lint config verify` is deliberately not run: it fetches its # JSON schema over an unpinned live HTTPS call, which REPO_POLICIES.md # forbids for external references. RUN echo "pixa-lint: running golangci-lint (${CACHEBUST})" && \ golangci-lint run --config .golangci.yml ./...