Repository navigation
chore(ci): keep the pre-commit go vet and go test hooks out of node_modules - #1512
Conversation
…odules The go-vet and go-test hooks ran `go vet ./...` and `go test -short -race ./...`. Go's ./... skips only vendor, testdata and `.`/`_` directories, so once `npm ci` has run (pre-commit.yml runs it before the hooks) it also matches Go source shipped inside npm packages, such as frontend/node_modules/flatted/golang/pkg/flatted. Those packages have no go.mod of their own, so they are absorbed into this module and the hooks gate on third-party code. Both hooks now build the package list with `go list -e ./...` and drop /node_modules/ paths. -e keeps a broken node_modules package from failing the listing; pipefail fails the hook if `go list` itself fails instead of running on an empty list. The first-party package set is unchanged. LeanerCloud#1286 covered the gocyclo walk in ci.yml and the Makefile. This covers the pre-commit Go hooks named in the audit finding. Refs LeanerCloud#177 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): VERDICT: APPROVE Blocking:
Non-blocking:
Attacked:
Body-stale:
Reviewer: rF5. Bar while the maintainers are away (set by IAmJSD as acting owner): one approving independent review on the head, two for money, auth and security paths. |
|
Local verification at |
|
Merged by IAmJSD's agent at IAmJSD's request (IAmJSD is acting owner while the maintainers are away), under the bar IAmJSD set: 1 approving independent review(s) on |
Root cause
The pre-commit
go-vethook rango vet ./...and the pre-pushgo-testhook rango test -short -race ./.... Go's./...skips onlyvendor,testdataand./_-prefixed directories, notnode_modules. npm packages can ship Go source with nogo.modof their own, so those files are absorbed into this module. Afternpm ci,go list ./...includesgithub.com/LeanerCloud/cloud-commitments-platform/frontend/node_modules/flatted/golang/pkg/flatted.pre-commit.ymlruns "Install frontend deps" (npm ci) before "Run pre-commit", so in CI thego-vethook already vets third-party code. Locally the same is true for both hooks. It passes today only because the currentflattedhappens to vet clean. This is audit finding A15-003 on the issue.Fix
Both hooks now build their package list with
go listand dropnode_modules:-e: without it, a broken Go package insidenode_modules(one with a syntax error, or an import of a module this repo does not require) makesgo list ./...itself exit 1. That would fail the hook on third-party code again.pipefailwithset -e: ifgo listfails for a first-party reason, the hook fails. It does not go on to rungo vetwith an empty argument list, which would vet only the root directory and pass.grep -v "/node_modules/"matches a whole path segment, the same idea as ci: keep gocyclo's filesystem walk out of node_modules and vendor #1286's(^|/)(node_modules|vendor)/.vendor/needs no filter here, because./...already excludes vendor directories in module mode.This follows #1286, which fixed the gocyclo walk in
ci.ymland the Makefile. The pre-commitgocyclohook was already safe because it lists files withgit ls-files.Refs #177
How the issue's items stand:
ci.ymlgocyclo walk: ci: keep gocyclo's filesystem walk out of node_modules and vendor #1286.complexity/complexity-reportgocyclo walks: ci: keep gocyclo's filesystem walk out of node_modules and vendor #1286.gocyclohook: was never affected (git ls-files; confirmed in ci: keep gocyclo's filesystem walk out of node_modules and vendor #1286).go vet ./.../go test ./...hooks: this PR.It is
Refs, notCloses, because the Makefile's owngo vet ./...(make vet) andgo test ... ./...targets (test-unit,test-integration,test-coverage, and thego vet -tags=integration ./...intest-compile-integration) still matchnode_modulespackages in a local checkout afternpm ci. That is the same "trap for local runs" the issue describes, although the issue does not name those targets. See "Out of scope" for a one-line fix that would cover them.Verification
Hook-level fixture evidence on this branch (head
f2a5fb87, main3bfc2fe5). A realnpm ci --ignore-scriptsin the worktree populatedfrontend/node_modules, includingflatted/golang/pkg/flatted/flatted.go. I also planted a package atfrontend/node_modules/zz-planted-go/golang/bad.gocontainingfmt.Printf("%d\n", "not-an-int"), so vet has something to report. All fixtures were deleted afterwards.go list ./... | grep node_moduleslists both.../frontend/node_modules/flatted/golang/pkg/flattedand the planted package.pre-commit run go-vet --all-filesFAILED withfrontend/node_modules/zz-planted-go/golang/bad.go:7:26: fmt.Printf format %d has arg "not-an-int" of wrong type string.pre-commit run go-vet --all-filespassed with the same fixtures, plus two more plantednode_modulespackages, one with a syntax error and one importing a missing module.internal/zzplanted/f.gomakes the new hook fail withinternal/zzplanted/f.go:5:24: fmt.Printf format %d has arg "x" of wrong type string.go listfailure fails the hook:GOFLAGS=-mod=bogus pre-commit run go-vet --all-filesgives Failed, not a silent pass on an empty list.-eis needed: with the missing-import fixture,go list ./...exits 1 (no required module provides package github.com/example/does-not-exist/pkg), and so does the syntax-error fixture.go list -e ./...exits 0 for both.-racetest run:GOFLAGS='-run=^$' pre-commit run go-test --hook-stage pre-push --all-files. This still builds and vets every test binary with-race, but runs no tests.FAIL .../frontend/node_modules/zz-planted-go/golang [build failed]and the vet error;.../node_modules/flatted/golang/pkg/flatted [no test files]was also in the run.--verbose): passed, and nonode_modulespackage appears in the output.diffis empty), and that list matchesgo list ./... | grep -v node_modules.pre-commit validate-config .pre-commit-config.yaml: OK.pre-commit run check-yaml --files .pre-commit-config.yaml: Passed.shellcheckon the two extracted entry scripts reports only SC2086 (info) for the unquoted$pkgs. The word splitting is intended: Go import paths cannot contain spaces or glob characters.Combined-tree verification at local queue commit
2be43e1e= origin/mainb9271e88+fix/issue-363-next,fix/issue-177-next,fix/issue-919-next,fix/issue-313-next,fix/issue-532-nextandfix/issue-316-nextmerged in that order. Passed:go build ./...;go vetwith and without-tags integration;go test -race -short -count=1 ./...; golangci-lint v2.10.1 with and without the integration tag; gocyclo -over 10;go test -race -tags integrationoninternal/api,internal/auth,internal/config,internal/database/postgres/migrations,internal/purchase,internal/serverandinternal/testutil; the git-secrets scan andscripts/test-git-secrets-allowlist.sh.Out of scope
go vet ./.../go test ./...targets: these still matchnode_modulespackages locally afternpm ci. The CI jobs that run./...(ci.ymllint, unit-tests and govulncheck) do not install npm deps, so CI is not affected.ignoredirective. Addingignore ./frontend/node_modulestogo.modmakes every./...skip it: these hooks, the Makefile, golangci-lint and govulncheck. I checked locally thatgo list ./...then drops a plantedfrontend/node_modulespackage and keeps all 50 first-party ones. I did not do it here: it is a module-level change beyond this item, and older tools that parse go.mod with an outdatedgolang.org/x/modcould reject the directive. That would need checking first. If that route is chosen, the hook changes here could be reverted to plain./....Maintainer: please mirror the issue's triage labels on this PR:
type/chore,triaged,priority/p3,severity/low,urgency/eventually,impact/internal,effort/xs.🤖 Generated with Claude Code