From 4d70317d6d745ac5c5cd249faf86b63c93eb0325 Mon Sep 17 00:00:00 2001 From: clawbot Date: Sun, 9 Aug 2026 01:46:38 +0000 Subject: [PATCH] lint: adopt org-standard .golangci.yml and golangci-lint v2.12.2 (closes #14) backend/.golangci.yml declared version: "2" on line 1 but used the golangci-lint v1 schema below it: a top-level linters-settings key and an issues.exclude-use-default key that does not exist in v2. Under v2 that config does not validate, so every threshold in it was inert -- lll fell back to its 120-column default rather than the intended 88, and funlen, cyclop and dupl were not applied at all. The `0 issues.` result the repo has been relying on was therefore meaningless. Replace it with the org-standard file verbatim (sha256 021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb) and repoint the golangci-lint pin in Dockerfile.backend from v2.7.2 to the org-standard v2.12.2. Guard against the config drifting from the standard again by asserting its sha256 as the first step of the backend lint target. The check is a local hash comparison against a constant in the Makefile: it needs no network, fetches nothing, and adds no unpinned external reference to the build path. It also catches a strictly larger class of breakage than schema validation would, since a schema-valid but non-canonical config is exactly how this file got into its broken state. With the config actually loading, lll reports server.go:65 at 93 columns. Fix it, plus the two other over-long lines called out on the issue (server.go:97 at 81 and reportbuf.go:166 at 88) which are inside the 88-column lint limit but over the 77-column hard wrap in the Go styleguide. All three were long //nolint justifications on the code line; move the justification into a preceding comment block and leave a short directive behind. No suppression is added or widened, and .golangci.yml is not touched after the copy. Drop the //nolint:wsl in server.go entirely rather than relocating it. The standard config disables wsl, so the directive suppressed nothing; removing it still yields `0 issues.` Verified: `cd backend && make check` reports `0 issues.` and passes with the network unavailable, root `make check` passes, and `docker build -f Dockerfile.backend .` builds green against the pinned v2.12.2. --- Dockerfile.backend | 4 +-- TODO.md | 33 ++++++++++++++++--------- backend/.golangci.yml | 26 ++++++++++--------- backend/Makefile | 18 ++++++++++++++ backend/internal/reportbuf/reportbuf.go | 4 ++- backend/internal/server/server.go | 7 ++++-- 6 files changed, 64 insertions(+), 28 deletions(-) diff --git a/Dockerfile.backend b/Dockerfile.backend index d97bbbd..e23f124 100644 --- a/Dockerfile.backend +++ b/Dockerfile.backend @@ -3,8 +3,8 @@ FROM golang:1.25-alpine@sha256:f6751d823c26342f9506c03797d2527668d095b0a15f1862c RUN apk add --no-cache git make gcc musl-dev -# golangci-lint v2.7.2 (2026-02-27) -RUN CGO_ENABLED=0 go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@9f61b0f53f80672872fced07b6874397c3ed197b +# golangci-lint v2.12.2 (2026-08-09) +RUN CGO_ENABLED=0 go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@c0d3ddc9cf3faa61a4e378e879ece580256d76e5 WORKDIR /repo/backend COPY backend/go.mod backend/go.sum ./ diff --git a/TODO.md b/TODO.md index 587c805..055d270 100644 --- a/TODO.md +++ b/TODO.md @@ -10,23 +10,31 @@ # Status -pre-1.0. No git tags. Backend work in flight on feat/reportbuf-storage (dirty: -src/main.js). Frontend is functional; backend is new and unmerged. +pre-1.0. No git tags. `feat/reportbuf-storage` is merged; the backend, the CI +workflow, and the backend repo standard files are all on `main`. Frontend and +backend are both functional. Working toward the 1.0.0 milestone by closing the +remaining repo-compliance issues on the tracker. # Next Step -Land feat/reportbuf-storage: finish the in-progress src/main.js change, get make -check green, and merge the branch to main. The branch adds the backend (buffered -zstd-compressed report storage), the CI workflow, and backend repo standard -files, so merging it also closes most compliance gaps. +Compliance top-up as one small commit: add an `.editorconfig` at the repo root. +`backend/.editorconfig` exists but the root has none. (The `hooks` target this +step used to also name is already present in both the root `Makefile` and +`backend/Makefile`.) # Completed Steps +- 2026-08-09: adopted the org-standard `backend/.golangci.yml` verbatim and + bumped the pinned golangci-lint to v2.12.2; the previous config declared + `version: "2"` but used v1 schema keys, so every threshold in it was inert and + its green result was meaningless. `backend/Makefile`'s `lint` target now + asserts the config's sha256 against the canonical file first, so drift from + the org standard fails the build instead of silently degrading to defaults - 2026-07-07 Adopted scripts-to-rule-them-all: `script/` entrypoints, Makefile shims, README Entrypoints section - 2026-02-27: backend with buffered zstd-compressed report storage; CI workflow and backend repo standard files; backend Dockerfile fixed (Go 1.25, - golangci-lint) and moved to repo root (feat/reportbuf-storage, unmerged) + golangci-lint) and moved to repo root (feat/reportbuf-storage) - 2026-02-26: host row layout redesigned with CSS grid; overflow and spacing fixes; nginx config extracted; port hardcoded to 8080 - 2026-02-26: debug log panel, median stats, recovery probe, Docker build fix, @@ -39,9 +47,12 @@ files, so merging it also closes most compliance gaps. # Future Steps -- Compliance top-up as one small commit: add .editorconfig and add the hooks - target to the Makefile -- After merge, confirm .gitea/workflows/check.yml is on main and CI is green - (main always green policy) +- Confirm `.gitea/workflows/check.yml` is on `main` and CI is green (main always + green policy) - Decide what to do with untracked resume.sh: commit it, gitignore it, or delete it +- Upstream fix needed in `sneak/prompts`: the org-standard `.golangci.yml` + enables `gomodguard`, which golangci-lint v2.12.2 reports as deprecated since + v2.12.0 and replaced by `gomodguard_v2`, so every backend lint run prints a + deprecation warning. The file is standardized and must never be edited in this + repo, so nothing can be done here beyond tracking it diff --git a/backend/.golangci.yml b/backend/.golangci.yml index 34a8e31..26b1610 100644 --- a/backend/.golangci.yml +++ b/backend/.golangci.yml @@ -1,5 +1,9 @@ version: "2" +# Config schema uses the golangci-lint v2 layout (settings live under +# linters.settings, not top-level linters-settings) so that the +# thresholds below are actually applied by golangci-lint >= v2. + run: timeout: 5m modules-download-mode: readonly @@ -14,19 +18,17 @@ linters: - wsl # Deprecated, replaced by wsl_v5 - wrapcheck # Too verbose for internal packages - varnamelen # Short names like db, id are idiomatic Go - -linters-settings: - lll: - line-length: 88 - funlen: - lines: 80 - statements: 50 - cyclop: - max-complexity: 15 - dupl: - threshold: 100 + settings: + lll: + line-length: 88 + funlen: + lines: 80 + statements: 50 + cyclop: + max-complexity: 15 + dupl: + threshold: 100 issues: - exclude-use-default: false max-issues-per-linter: 0 max-same-issues: 0 diff --git a/backend/Makefile b/backend/Makefile index 38cebcf..0bca693 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -8,10 +8,20 @@ GOLDFLAGS += -X main.Buildarch=$(BUILDARCH) ifeq ($(UNAME_S),Darwin) GOFLAGS := -ldflags "$(GOLDFLAGS)" + SHA256SUM := shasum -a 256 else GOFLAGS = -ldflags "-linkmode external -extldflags -static $(GOLDFLAGS)" + SHA256SUM := sha256sum endif +# .golangci.yml is standardized org-wide and must never be edited here +# (REPO_POLICIES.md). Its last silent drift replaced the v2 schema with +# v1 keys, which left every threshold in the file inert while the build +# stayed green. The lint target therefore asserts the file still matches +# the canonical copy byte for byte. The check is a local hash comparison: +# no network, no remote schema, nothing unpinned in the build path. +GOLANGCI_CONFIG_SHA256 := 021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb + .PHONY: all build test lint fmt fmt-check check docker hooks run clean all: build @@ -25,6 +35,14 @@ test: timeout 30 go test ./... lint: + @actual=$$($(SHA256SUM) .golangci.yml | cut -d' ' -f1); \ + if [ "$$actual" != "$(GOLANGCI_CONFIG_SHA256)" ]; then \ + echo ".golangci.yml has drifted from the org standard."; \ + echo " expected $(GOLANGCI_CONFIG_SHA256)"; \ + echo " actual $$actual"; \ + echo "Restore it verbatim from sneak/prompts; do not edit it."; \ + exit 1; \ + fi golangci-lint run ./... fmt: diff --git a/backend/internal/reportbuf/reportbuf.go b/backend/internal/reportbuf/reportbuf.go index ff4cbad..adf5614 100644 --- a/backend/internal/reportbuf/reportbuf.go +++ b/backend/internal/reportbuf/reportbuf.go @@ -163,7 +163,9 @@ func (b *Buffer) writeFile(data []byte) { name := fmt.Sprintf("reports-%s.jsonl.zst", ts) path := filepath.Join(b.dataDir, name) - f, err := os.OpenFile( //nolint:gosec // path built from controlled dataDir + timestamp + // path is built from the operator-supplied dataDir plus a + // generated timestamp, so it carries no external input. + f, err := os.OpenFile( //nolint:gosec // see comment above path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, filePerms, diff --git a/backend/internal/server/server.go b/backend/internal/server/server.go index a67bd1e..2535a1b 100644 --- a/backend/internal/server/server.go +++ b/backend/internal/server/server.go @@ -62,7 +62,10 @@ func New( OnStart: func(_ context.Context) error { s.startupTime = time.Now().UTC() - go func() { //nolint:contextcheck // fx OnStart ctx is startup-only; run() creates its own + // The fx OnStart context is scoped to startup and is + // cancelled once the hook returns; run() derives its + // own context instead of inheriting this one. + go func() { //nolint:contextcheck // see comment above s.run() }() @@ -94,7 +97,7 @@ func (s *Server) run() { } func (s *Server) serve() int { - var ctx context.Context //nolint:wsl // ctx must be declared before multi-assign + var ctx context.Context ctx, s.cancelFunc = context.WithCancel( context.Background(), -- 2.49.1