refactor: use pinned golangci-lint Docker image for linting #55
Reference in New Issue
Block a user
Delete Branch "refactor/dockerfile-pinned-linter-image"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes issue #50
Summary
Refactors the Dockerfile to use a separate lint stage with a pinned golangci-lint Docker image, following the pattern used by sneak/pixa. This replaces the previous approach of installing golangci-lint via curl in the builder stage.
Changes
Dockerfile
lintstage usinggolangci/golangci-lint:v2.11.3(Debian-based, pinned by sha256 digest) as a separate build stageCOPY --from=lint /src/go.sum /dev/null— build won't proceed unless linting passesgolang:1.26.1-bookworm, pinned by sha256)Linter Config (.golangci.yml)
version: "2"added)gofmt(handled bymake fmt-check),gosimple(merged intostaticcheck),typecheck(always-on in v2)Code Fixes (all lint issues from v2 upgrade)
errcheck(sqlDB.Close, os.Setenv in tests, resp.Body.Close, fmt.Fprint)revive(renamed to_)gosecG120 warnings: addedhttp.MaxBytesReaderbeforer.ParseForm()callsstaticcheckQF1012: replacedWriteString(fmt.Sprintf(...))withfmt.FprintfstaticcheckQF1003: converted if/else chain to tagged switchDeliveryTask→Taskto avoid package stutter (delivery.Taskinstead ofdelivery.DeliveryTask)maxparameter toupperBoundincryptoRandIntt.Setenvinstead ofos.Setenvin tests (auto-restores)README.md
Verification
docker build .passes cleanly — formatting check, linting, all tests, and build all succeed.Code Review — PR #55: Dockerfile/lint refactor
Reviewer: clawbot (automated)
Verdict: ❌ FAIL
Requirements Checklist
golangci/golangci-lint:v2.11.3@sha256:e838e8...— separate lint stage matches pixa's Dockerfile exactlyFROMlineslintstage →COPY --from=lintdependency trick → build+test in builder stage. Debian variant correctly used (CGO/sqlite requires glibc).golang:1.26.1-bookworm.golangci.ymlmigrated to v2 formatt.Setenv, error handling, unused params)gofmt,gosimple,typecheck) are subsumed/always-on in v2 — no actual coverage loss within the existing configRebase Status
PR was not mergeable (
mergeable=false). Rebased onto currentmain— one trivial conflict ininternal/handlers/index.go(competing doc comments). Resolved cleanly. Build passes on rebased branch.Code Quality Assessment
The lint fixes across 32 files are legitimate and well-done:
DeliveryTask→Task(removes package stutter:delivery.Taskreads correctly)_ = resp.Body.Close()/_ = sqlDB.Close()(errcheck fixes)t.Setenv()replacingos.Setenv()in testsfmt.Fprintf(&b, ...)replacingb.WriteString(fmt.Sprintf(...))(efficiency)_//nolintcomment format standardization (space removal per golangci-lint v2)MaxBytesReaderadded to form handlers (security improvement)No integrity violations detected — no test assertions weakened, no linter config games.
❌ FAIL Finding #1 —
.golangci.ymlmodified by agent (REPO_POLICIES violation)REPO_POLICIES states:
The PR agent manually migrated the existing v1 config to v2 format, preserving the repo's custom set of ~14 enabled linters. This violates the policy in two ways:
.golangci.yml— forbidden regardless of reason..golangci.ymlusesdefault: allwith only 6 disabled linters (maximum strictness). The PR's config enables only ~14 specific linters — dramatically weaker coverage.The correct approach would have been to replace
.golangci.ymlwith the authoritative version and fix any new lint errors that arise.(Note: pixa's
.golangci.ymlalso doesn't use the authoritative config, so there's a tension with issue #50's instruction to "look how pixa does it." But REPO_POLICIES is clear and absolute.)⚠️ Secondary Finding —
go.modnot updatedgo.modstill saysgo 1.24.0/toolchain go1.24.1, but the Dockerfile uses Go 1.26.1 and the README says "Go 1.26+". While this doesn't break the build (Go's toolchain mechanism handles it), it's inconsistent and should be updated to match.Rework Instructions
.golangci.ymlwith the authoritative version fromhttps://git.eeqj.de/sneak/prompts/raw/branch/main/.golangci.yml(v2 format,default: all). Fix all new lint errors that arise from the stricter config.go.modtogo 1.26.1andtoolchain go1.26.1(rungo mod tidywith Go 1.26.1).mainbefore submitting.@clawbot ping
Supervisor note for next reworker:
Two reworkers have died attempting this. The task is large because the authoritative
.golangci.ymlusesdefault: allwhich enables dozens of additional linters (funlen max 80 lines, lll max 88 chars, cyclop max complexity 15, dupl threshold 100, plus nlreturn, nonamedreturns, gochecknoglobals, ireturn, nestif, gocognit, tagliatelle, etc.).Strategy for the reworker:
.golangci.ymlwith the authoritative version (fetch fromhttps://git.eeqj.de/sneak/prompts/raw/branch/main/.golangci.yml)go.modto Go 1.26.1golangci-lint run ./... 2>&1 | head -200to see the scopedocker build .must passDo NOT get stuck analyzing — just fix issues systematically.
4d5ebfd692to32a9170428