Repository navigation
lint go: every lane enters each command that is a module of its own - #650
Merged
Merged
Conversation
The Go lanes ran at the repository root, and golangci-lint, vet, the tidiness check, go-licenses, NilAway, deadcode and govulncheck all stop at a nested go.mod: a command that is a module of its own, the shape build go builds from inside (cmd/<name>/go.mod), was never linted or scanned by the shared lanes. limen linted its own cmd/limen-lint-go through five lines in its root justfile, and any other repository with such a command linted it not at all. The list is one statement, the root then each cmd/<name> carrying a go.mod, built into an array; a tool module under .limen/tools is not project code and is not on it. lib.just holds it as go_modules_init for the commands handed to _per-platform, and a recipe body writes it out, since the shell lane lints a body with its interpolations opaque and must see the assignment the loop reads; a test holds the copies to the variable. Every lint lane, the vulnerability scan and the fix lane (the fixers, the formatter's convergence loop, tidiness) loop over it from inside each module, and _golangci-config renders one configuration per module, the baseline with that module's own .lint-go.yaml when it has one (the root's at golangci.yml as before, a command's beside it by name), so a command's carve-outs are its own. NilAway reads its flags and its mode per module. A lane names the module it enters, so a finding's relative path is locatable. _per-platform exports a leg's environment instead of prefixing it: a prefix binds to a simple command alone, and a leg's command is now a loop; the recipe is its own process, so nothing outlives it. The two one-line recipes, the formatter's check and deadcode, become bash blocks: the loop is bash, and a plain recipe line runs under sh. Found on the way: the mod lanes ended on the loop over the isolated tool modules, whose body was `[ -f ] && go ...`, so a repository with no such module ended the recipe on 1; `continue` instead. limen's root justfile loses lint-lint-go; its tests of the nested module stay, since the test lane still runs the root alone. book/linting-go.md states the rule and drops the "never enters" clause; book/errors-go.md's clause narrows to the modules the lane still does not enter. Tests, black-box through just on a fixture with a root module and a command module: a malformed build constraint in the command fails `lint go vet` naming cmd/nested; a sound command passes vet and mod. limen's own `just lint` now lints cmd/limen-lint-go through the shared lanes, on its own overlay. Closes #505 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: closer-claudio <claudio@farcloser.world>
closer-claudio
force-pushed
the
claudio/20261110-lint-nested-modules
branch
from
November 10, 2026 08:52
5cced96 to
3a9341b
Compare
apostasie
approved these changes
Nov 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Go lanes ran at the repository root, and golangci-lint, vet, the
tidiness check, go-licenses, NilAway and deadcode all stop at a nested
go.mod: a command that is a module of its own, the shape build go builds
from inside (cmd//go.mod), was never linted by the shared lanes.
limen linted its own cmd/limen-lint-go through five lines in its root
justfile, and any other repository with such a command linted it not at
all.
The list is one statement, the root then each cmd/ carrying a
go.mod, built into an array; a tool module under .limen/tools is not
project code and is not on it. lib.just holds it as go_modules_init for
the commands handed to _per-platform, and a recipe body writes it out,
since the shell lane lints a body with its interpolations opaque and must
see the assignment the loop reads. Every lane loops over it from inside
the module, and _golangci-config renders one configuration per module,
the baseline with that module's own .lint-go.yaml when it has one (the
root's at golangci.yml as before, a command's beside it by name), so a
command's carve-outs are its own. NilAway reads its flags and its mode
per module. The fix lane follows the same list, for the fixers, the
formatter's convergence loop and tidiness, since lint would otherwise
refuse what fix cannot repair. _per-platform exports a leg's environment
in a subshell instead of prefixing it: a prefix binds to a simple command
alone, and a leg's command is now a loop. A lane names the module it
enters, so a finding's relative path is locatable. The two one-line
recipes, the formatter's check and deadcode, become bash blocks: the loop
is bash, and a plain recipe line runs under sh.
Found on the way: the mod lanes ended on the loop over the isolated tool
modules, whose body was
[ -f ] && go ..., so a repository with no suchmodule ended the recipe on 1;
continueinstead. limen's root justfileloses lint-lint-go; its tests of the nested module stay, since the test
lane still stops at the root. book/linting-go.md states the rule and
drops the "never enters" clause.
Tests, black-box through just on a fixture with a root module and a
command module: a malformed build constraint in the command fails
lint go vetnaming cmd/nested; a sound command passes vet and mod. limen'sown
just lintnow lints cmd/limen-lint-go through the shared lanes, onits own overlay.
Closes #505
Evidence.
just linton this branch enterscmd/limen-lint-gothrough the shared lanes (the lane prints the module it enters) and is green, with limen's own hand-written lint of that module removed;just do fix goconverges per module;just testgreen, 446 tests, the two new ones black-box throughjuston a fixture repository.For a consumer: a repository with a command that is a module of its own gets that module linted at its next limen bump, on the baseline with the module's own
.lint-go.yamlif it has one, andjust do fix goformats it. Findings there are new findings, not a changed rule.