From fbec5a523b18304e8e9f1cc4f5b7220e89d15ae1 Mon Sep 17 00:00:00 2001 From: clawbot Date: Tue, 8 Sep 2026 05:14:43 +0200 Subject: [PATCH] Enable depguard so a non-test file cannot import test support (#59) `depguard` was in the disable list. It is now enabled with one rule, `test-support`: in files that are neither test files nor inside a package whose directory name ends in `test`, the imports named under `deny` are refused. Canonical denies `net/http/httptest`, which serves tests only and is the same in every repository. This replaces `internal/testimportgate` in sneak/homoicon, a package whose only job was to refuse a non-test Go file importing an in-module package whose last path segment ends in `test`. sneak ruled on https://git.eeqj.de/sneak/homoicon/issues/1029 that the rule moves into linter configuration here. depguard cannot express that rule generically. Its package lists are prefix lists -- its own README says so, and I confirmed it: `*test`, `**test` and `$gomod/**test` each match nothing, while a full import path matches. "In module" is not generic either, since the module path differs per repository. And depguard refuses a rule with no allow or deny list, so this file cannot ship the rule pre-armed and empty for each repository to fill in. The closest expressible rule is the one here. The file half is generic and exact; the package half is a deny list each repository extends with its own test-support packages, by full import path. REPO_POLICIES.md now says that list is the one part of a vendored copy a repository may add to. Tested with golangci-lint v2.12.2 on a scratch module: a production file importing a denied `*test` package fails, and the same import from a `_test.go` file and from inside the `*test` package passes. `make check` here is green. Model: opus-5 Co-authored-by: sneak Reviewed-on: https://git.eeqj.de/sneak/prompts/pulls/59 Co-authored-by: clawbot Co-committed-by: clawbot --- .golangci.yml | 27 ++++++++++++++++++++++++++- prompts/REPO_POLICIES.md | 6 +++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 26b1610..270cd99 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,7 +13,6 @@ linters: disable: # Genuinely incompatible with project patterns - exhaustruct # Requires all struct fields - - depguard # Dependency allow/block lists - godot # Requires comments to end with periods - wsl # Deprecated, replaced by wsl_v5 - wrapcheck # Too verbose for internal packages @@ -28,6 +27,32 @@ linters: max-complexity: 15 dupl: threshold: 100 + depguard: + # Test-support code must not be compiled into the shipped binary. A + # test-support package exists to hand a test privileges the program + # itself must never have, so a file that is not a test must not import + # one. Test files, and the files inside a package whose directory name + # ends in `test`, are where that code belongs, and are exempt. + # + # The deny list below is the one part of this file a repository is + # expected to extend, and the only part it may. depguard matches an + # import path against a list of prefixes, so it cannot be told "any path + # whose last segment ends in test"; a repository's own test-support + # packages have to be named here one at a time, by full import path, + # under a module path that differs from repository to repository. Add + # them; change nothing else. + rules: + test-support: + list-mode: lax + files: + - "$all" + - "!$test" + - "!**/*test/**" + deny: + - pkg: net/http/httptest + desc: >- + Test-support code belongs in test files and in packages whose + directory name ends in test, not in the shipped binary. issues: max-issues-per-linter: 0 diff --git a/prompts/REPO_POLICIES.md b/prompts/REPO_POLICIES.md index fad388c..c83afe7 100644 --- a/prompts/REPO_POLICIES.md +++ b/prompts/REPO_POLICIES.md @@ -269,7 +269,11 @@ style conventions are in separate documents: byte-identical, so that no repo can quietly loosen its own linting. Linter configuration changes are made to the canonical copy in the `prompts` repo and reach consuming repos by re-vendoring; an agent may open a PR against - canonical, which only the user merges. The canonical golangci-lint version is + canonical, which only the user merges. One list is exempt from byte-identity, + because it cannot be written once for every repo: the `deny` list of the + `test-support` depguard rule, where a repo names its own test-support packages + by full import path. A repo adds entries there and changes nothing else, and a + re-vendor carries its entries forward. The canonical golangci-lint version is v2.12.2 (released 2026-05-06), installed commit-pinned via `go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@c0d3ddc9cf3faa61a4e378e879ece580256d76e5`.