From c4982467d7eb08ffe0ef20d4eb69be8b4d081437 Mon Sep 17 00:00:00 2001 From: sneak Date: Thu, 1 Oct 2026 21:40:25 +0000 Subject: [PATCH] fmt: check goimports in fmt-check, run it at its pinned commit (#119) script/fmt-check now runs goimports in list mode and fails naming any file it would change, and checks gofmt with -s, as script/fmt applies it. Both scripts run goimports with `go run` at the commit that script/bootstrap used to install, so a goimports on PATH is never used and bootstrap no longer installs it. The pin is written in both scripts; change them together. The first run on a machine, and every Dockerfile lint stage run, downloads and builds goimports. The Markdown half of the issue (prettier) is not done here: it needs node in the lint image or a separate build, a decision for the owner. Model: opus-5-5 --- README.md | 11 ++++++----- TODO.md | 4 +++- script/bootstrap | 13 ++----------- script/fmt | 8 +++++++- script/fmt-check | 15 ++++++++++++--- 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 058cbe3..4e8c13d 100644 --- a/README.md +++ b/README.md @@ -508,9 +508,8 @@ standard: normalized scripts in `script/` are the entrypoints for the development workflow, and the Makefile targets are thin shims that call them. We provide: -- `script/bootstrap` — install all dependencies (go, pinned goimports, - `go mod download`). It does not install golangci-lint: see - `script/lint` below. +- `script/bootstrap` — install all dependencies (go, `go mod download`). + It does not install golangci-lint: see `script/lint` below. - `script/setup` — make a fresh clone ready for development: bootstrap plus the git pre-commit hook - `script/projectname` — print the project name (used for the Docker @@ -527,8 +526,10 @@ them. We provide: host, and Docker is the only prerequisite. Caching is waived for linting: the lint stage is forced to execute on every run with `--no-cache-filter`, because a cached build lints nothing. -- `script/fmt` — format all code (gofmt -s, goimports) -- `script/fmt-check` — check formatting (read-only) +- `script/fmt` — format all code (gofmt -s, goimports). goimports runs + with `go run` at a pinned commit, never from your `PATH`. +- `script/fmt-check` — check formatting (read-only) with the same tools, + failing on any file `script/fmt` would change - `script/check` — run test, lint, and fmt-check - `script/docker` — build the Docker image tagged via `script/projectname`, with `--no-cache-filter=lint,builder` so the lint stage and the builder stage, diff --git a/TODO.md b/TODO.md index 928baeb..897bda6 100644 --- a/TODO.md +++ b/TODO.md @@ -20,6 +20,8 @@ https://git.eeqj.de/sneak/dnswatcher/issues/149 # Completed Steps +- 2026-10-01: `make fmt-check` fails on a file `goimports` would change; both + format scripts run `goimports` at its pinned commit, not from `PATH` (#119). - 2026-10-01: a hostname is queried at the servers of the zone it is in, found by following delegations for the name, not its last two labels (closes #189). - 2026-10-01: each nameserver's addresses are saved with its domain, and a @@ -112,7 +114,7 @@ https://git.eeqj.de/sneak/dnswatcher/issues/149 - 1.0 readiness: run it with a real config and read the logs: https://git.eeqj.de/sneak/dnswatcher/issues/66 -- `goimports` in `make fmt-check`, Markdown formatting: +- Markdown formatting with prettier: https://git.eeqj.de/sneak/dnswatcher/issues/119 - README accuracy sweep: https://git.eeqj.de/sneak/dnswatcher/issues/108 - README sections required by policy: diff --git a/script/bootstrap b/script/bootstrap index 06da5d0..a463d0a 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -3,9 +3,8 @@ # this repo. Idempotent: every install is guarded by a check so already # installed tools are skipped. Base tooling comes from nix, apt, brew, # or apk (detected in that order); assumes nothing is present. -# goimports is installed via `go install` at a pinned commit (never -# "latest") because script/fmt runs it on the host; script/fmt-check -# does not (it runs gofmt only). +# goimports is not installed here: script/fmt and script/fmt-check run +# it with `go run` at a pinned commit. # The linter is NOT installed here: golangci-lint runs via docker only # (script/lint), pinned by image digest, so its only prerequisite is a # working docker. @@ -13,10 +12,6 @@ set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" -# Pinned version, 2026-08-07 (same pin as the Dockerfile) -# goimports v0.42.0 -GOIMPORTS_REF="golang.org/x/tools/cmd/goimports@009367f5c17a8d4c45a961a3a509277190a9a6f0" - PKGMGR="" SUDO="" APT_UPDATED="" @@ -71,10 +66,6 @@ main() { if missing make; then pkg_install gnumake make make make; fi if missing go; then pkg_install go golang go go; fi - # Format tools, pinned via go install (installs into - # "$(go env GOPATH)/bin"; ensure that is on your PATH). - if missing goimports; then go install "$GOIMPORTS_REF"; fi - # Linting runs via docker only (script/lint). Warn, don't fail: # everything except `make lint` works without it. if missing docker; then diff --git a/script/fmt b/script/fmt index b3235a8..a0b28e6 100755 --- a/script/fmt +++ b/script/fmt @@ -1,13 +1,19 @@ #!/bin/sh # script/fmt: format all files (writes). +# +# goimports runs with `go run` at a pinned commit, never from PATH, so +# every machine formats with the same version and nothing installs it. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" +# goimports v0.42.0, 2026-08-07. Must match script/fmt-check. +GOIMPORTS_REF="golang.org/x/tools/cmd/goimports@009367f5c17a8d4c45a961a3a509277190a9a6f0" + main() { cd "$ROOT" gofmt -s -w . - goimports -w . + go run "$GOIMPORTS_REF" -w . } main "$@" diff --git a/script/fmt-check b/script/fmt-check index b7438ef..40911dd 100755 --- a/script/fmt-check +++ b/script/fmt-check @@ -1,18 +1,27 @@ #!/bin/sh -# script/fmt-check: check formatting (read-only). Same scope as -# script/fmt, but fails instead of writing. +# script/fmt-check: check formatting (read-only). Same tools and scope +# as script/fmt, but fails instead of writing. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" +# goimports v0.42.0, 2026-08-07. Must match script/fmt. +GOIMPORTS_REF="golang.org/x/tools/cmd/goimports@009367f5c17a8d4c45a961a3a509277190a9a6f0" + main() { cd "$ROOT" - files="$(gofmt -l .)" + files="$(gofmt -s -l .)" if [ -n "$files" ]; then echo "gofmt: files not formatted:" >&2 echo "$files" >&2 exit 1 fi + files="$(go run "$GOIMPORTS_REF" -l .)" + if [ -n "$files" ]; then + echo "goimports: files not formatted:" >&2 + echo "$files" >&2 + exit 1 + fi } main "$@"