Split the Dockerfile into a dedicated lint stage using the pre-built golangci/golangci-lint image, so lint and formatting failures surface much faster without downloading golangci-lint on every build.
Pattern
# Stage 1: Lint (pre-built image, fast)FROMgolangci/golangci-lint@sha256:... AS lintWORKDIR/srcCOPY go.mod go.sum ./RUN go mod downloadCOPY . .RUN make fmt-checkRUN make lint# Stage 2: Test + BuildFROMgolang@sha256:... AS builder# Force BuildKit to run lint stageCOPY --from=lint /src/go.sum /dev/null...RUN make testRUN make build
## Goal
Split the Dockerfile into a dedicated lint stage using the pre-built `golangci/golangci-lint` image, so lint and formatting failures surface much faster without downloading golangci-lint on every build.
## Pattern
```dockerfile
# Stage 1: Lint (pre-built image, fast)
FROM golangci/golangci-lint@sha256:... AS lint
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN make fmt-check
RUN make lint
# Stage 2: Test + Build
FROM golang@sha256:... AS builder
# Force BuildKit to run lint stage
COPY --from=lint /src/go.sum /dev/null
...
RUN make test
RUN make build
```
## Key details
- All images pinned by sha256 per REPO_POLICIES
- `COPY --from=lint` creates BuildKit stage dependency (without this, lint stage is silently skipped)
- Reference implementation: [sneak/upaas Dockerfile](https://git.eeqj.de/sneak/upaas/src/branch/main/Dockerfile)
Tracked from [sdlc-manager#6](https://git.eeqj.de/clawbot/sdlc-manager/issues/6).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Goal
Split the Dockerfile into a dedicated lint stage using the pre-built
golangci/golangci-lintimage, so lint and formatting failures surface much faster without downloading golangci-lint on every build.Pattern
Key details
COPY --from=lintcreates BuildKit stage dependency (without this, lint stage is silently skipped)Tracked from sdlc-manager#6.