Run golangci-lint only in docker, on every run (closes #55)
check / check (push) Successful in 1m26s
check / check (push) Successful in 1m26s
script/lint builds the new Dockerfile.lint, where golangci-lint runs as a build step. The lint stage is rebuilt on every run, so an unchanged tree is linted too; the module download stays cached. script/bootstrap no longer installs golangci-lint. The Dockerfile lint stage calls golangci-lint directly, since make lint now starts a docker build. golangci-lint config verify is not run: it fetches its schema live over unpinned HTTPS. Model: opus-5-5
This commit is contained in:
+2
-1
@@ -9,7 +9,8 @@ RUN go mod download
|
|||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN make fmt-check
|
RUN make fmt-check
|
||||||
RUN make lint
|
# Not make lint: script/lint is a docker build, which cannot run in here.
|
||||||
|
RUN golangci-lint run --config .golangci.yml ./...
|
||||||
|
|
||||||
# Build stage — tests and compilation
|
# Build stage — tests and compilation
|
||||||
# golang 1.24.13-alpine (2026-03-10)
|
# golang 1.24.13-alpine (2026-03-10)
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Lint image, built by script/lint: golangci-lint runs as a build step, so a
|
||||||
|
# successful build is a clean lint. Works where the docker daemon is remote
|
||||||
|
# and bind mounts are impossible.
|
||||||
|
|
||||||
|
# golangci/golangci-lint:v2.12.2 (Debian-based), 2026-08-07
|
||||||
|
FROM golangci/golangci-lint:v2.12.2@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240 AS deps
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
# script/lint rebuilds this stage on every run, by this name; the module
|
||||||
|
# download above stays cached.
|
||||||
|
FROM deps AS lint
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN golangci-lint run --config .golangci.yml ./...
|
||||||
@@ -496,15 +496,18 @@ standard: normalized scripts in `script/` are the entrypoints for the
|
|||||||
development workflow, and the Makefile targets are thin shims that call
|
development workflow, and the Makefile targets are thin shims that call
|
||||||
them. We provide:
|
them. We provide:
|
||||||
|
|
||||||
- `script/bootstrap` — install all dependencies (Go, golangci-lint, Go
|
- `script/bootstrap` — install all dependencies (Go, Go module
|
||||||
module download), idempotently
|
download), idempotently; golangci-lint is not installed, it runs in
|
||||||
|
docker
|
||||||
- `script/setup` — make a fresh clone ready for development: runs
|
- `script/setup` — make a fresh clone ready for development: runs
|
||||||
`script/bootstrap`, then `script/install-precommit`
|
`script/bootstrap`, then `script/install-precommit`
|
||||||
- `script/projectname` — output the project name (`secret`); used by
|
- `script/projectname` — output the project name (`secret`); used by
|
||||||
other scripts such as `script/docker`
|
other scripts such as `script/docker`
|
||||||
- `script/test` — run `go vet` and the test suite (verbose rerun on
|
- `script/test` — run `go vet` and the test suite (verbose rerun on
|
||||||
failure)
|
failure)
|
||||||
- `script/lint` — run `golangci-lint`
|
- `script/lint` — run `golangci-lint` in docker only: builds
|
||||||
|
`Dockerfile.lint`, where the linter is a build step that runs on every
|
||||||
|
call, also on an unchanged tree
|
||||||
- `script/fmt` — format all Go code (writes)
|
- `script/fmt` — format all Go code (writes)
|
||||||
- `script/fmt-check` — check formatting without writing
|
- `script/fmt-check` — check formatting without writing
|
||||||
- `script/check` — run `script/test`, `script/lint`, and
|
- `script/check` — run `script/test`, `script/lint`, and
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ Bring the repo into policy compliance in one commit:
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- 2026-10-04: Lint runs only in docker: `script/lint` builds
|
||||||
|
`Dockerfile.lint`, where golangci-lint is a build step rebuilt on
|
||||||
|
every run (`--no-cache-filter`), so an unchanged tree is linted too;
|
||||||
|
the module download stays cached. `script/bootstrap` no longer
|
||||||
|
installs golangci-lint, and the `Dockerfile` lint stage calls it
|
||||||
|
directly instead of `make lint`. `golangci-lint config verify` is not
|
||||||
|
run: it fetches its schema live over unpinned HTTPS.
|
||||||
- 2026-10-03: `secret mv` rejects a move whose destination is the
|
- 2026-10-03: `secret mv` rejects a move whose destination is the
|
||||||
source (`mv --force x x`, `mv --force work:x work:`, or an empty
|
source (`mv --force x x`, `mv --force work:x work:`, or an empty
|
||||||
destination, which defaults to the source name) before changing
|
destination, which defaults to the source name) before changing
|
||||||
|
|||||||
+1
-6
@@ -6,6 +6,7 @@
|
|||||||
# make, node, yarn, go, or python). Node is used directly if installed;
|
# make, node, yarn, go, or python). Node is used directly if installed;
|
||||||
# otherwise a pinned version is installed via nvm (installing nvm
|
# otherwise a pinned version is installed via nvm (installing nvm
|
||||||
# itself first, from a hash-verified release archive, never curl | sh).
|
# itself first, from a hash-verified release archive, never curl | sh).
|
||||||
|
# golangci-lint is never installed: script/lint runs it in docker.
|
||||||
#
|
#
|
||||||
# Uncomment the language sections in main() that apply to this repo.
|
# Uncomment the language sections in main() that apply to this repo.
|
||||||
set -eu
|
set -eu
|
||||||
@@ -136,12 +137,6 @@ main() {
|
|||||||
|
|
||||||
# ---- Go repos ----
|
# ---- Go repos ----
|
||||||
if missing go; then pkg_install go golang go go; fi
|
if missing go; then pkg_install go golang go go; fi
|
||||||
# golangci-lint: packaged in nix, brew, and apk. On apt there is no
|
|
||||||
# package: download a specific release archive from GitHub and
|
|
||||||
# verify its hash (verify_sha256), never curl | sh.
|
|
||||||
if missing golangci-lint; then
|
|
||||||
pkg_install golangci-lint golangci-lint golangci-lint golangci-lint
|
|
||||||
fi
|
|
||||||
go mod download
|
go mod download
|
||||||
|
|
||||||
# ---- Python repos ----
|
# ---- Python repos ----
|
||||||
|
|||||||
+14
-4
@@ -1,14 +1,24 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# script/lint: run the linter.
|
# script/lint: run the linter, in docker only. Builds Dockerfile.lint,
|
||||||
|
# where golangci-lint runs as a build step.
|
||||||
|
#
|
||||||
|
# A cached build lints nothing, so --no-cache-filter rebuilds the lint
|
||||||
|
# stage on every run, an unchanged tree included. It ignores a stage name
|
||||||
|
# that does not exist, so --target names the same stage: a rename then
|
||||||
|
# fails the build instead of serving the lint from cache. cacheonly keeps
|
||||||
|
# no image; only the build's success matters.
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
# CGO is required (Makefile exports this too)
|
docker build \
|
||||||
export CGO_ENABLED=1
|
--progress=plain \
|
||||||
golangci-lint run --timeout 5m
|
--target lint \
|
||||||
|
--no-cache-filter=lint \
|
||||||
|
--output=type=cacheonly \
|
||||||
|
-f Dockerfile.lint .
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user