ci-tools/ — pinned development tools
This is a separate Go module (github.com/genealogix/glx/ci-tools) that pins the versions of selected CI/development tools via the Go 1.24+ tool directive. It does not track every CI tool — only those listed under Tools pinned here; others are intentionally pinned elsewhere (see Tools deliberately NOT here). It is not imported by, and shares no dependency graph with, the main module — so a tool's transitive dependencies never pollute the root go.mod/go.sum and are never inherited by anyone importing github.com/genealogix/glx/go-glx as a library.
Why
ci-tools/and nottools/?tools/already holds the first-partytools/driftcheckpackage, which is part of the main module (it importsgo-glx). Placing this module'sgo.modattools/would have swalloweddriftcheckinto the isolated tool module — breakinggo run ./tools/driftcheck,go test ./tools/..., andmake check-code-drift. Keeping the two concerns in separate top-level directories avoids that collision.
Tools pinned here
| Tool | Package | Used by |
|---|---|---|
| govulncheck | golang.org/x/vuln/cmd/govulncheck | .github/workflows/security.yml, make vulncheck |
Tools deliberately NOT here
- gosec stays on a version-pinned
go installin.github/workflows/security.yml, with the version pinned by the top-level.gosec-versionfile (single source of truth, also consumed bymake gosec). Itsautofixpackage imports the Googlegenerative-ai-goSDK, which transitively pulls the Google Cloud SDK, gRPC, and OpenTelemetry. Committing that graph to a scannedgo.modwould makedependency-reviewblock PRs whenever any of those (unreachable, build-time-only) dependencies picks up a new advisory.go installkeeps gosec reproducible without exposing that tree. Run it locally withmake gosec. Dependabot cannot propose a bump for this pin: itsgomodecosystem only readsgo.modfiles, where gosec deliberately does not appear, and itsgithub-actionsecosystem only readsuses:references, not ago install [email protected]line in arun:block. So the weekly.github/workflows/gosec-pin-currency.ymlworkflow fails when.gosec-versionfalls behind the latest gosec release. It is a standalone workflow rather than a job insecurity.ymlon purpose —security.ymlis the Code Scanning setup for gosec and govulncheck, and any failing job in it marks both tools as "reporting errors" on the tool status page (#1145). - go-licenses stays on a version-pinned
go install github.com/google/go-licenses/[email protected]in.github/workflows/license-compliance.yml(and a matchinggo runinmake license-check). Its tree pullsgo.opencensus.io,golang.org/x/net, andlicenseclassifier— committing that graph here would makedependency-reviewblock PRs on advisories in build-time-only code, the same trade-off as gosec. - golangci-lint is pinned via
.golangci-lint-versionand run throughgolangci-lint-action(foronly-new-issuessupport — see #272). - goreleaser runs through
goreleaser-action.
Running a tool
Invoke from the repository root with -modfile so the tool builds from this module's pinned versions while analyzing the main module's packages:
go tool -modfile=ci-tools/go.mod govulncheck ./...Or use the Makefile wrapper: make vulncheck.
Bumping or adding a tool
cd ci-tools
go get -tool golang.org/x/vuln/cmd/[email protected] # bump
go get -tool example.com/some/new/[email protected] # add
go mod tidyCommit the resulting ci-tools/go.mod and ci-tools/go.sum. The pinned version is the single source of truth for both CI and local runs. Prefer tools with a lean dependency graph here; heavyweight trees belong on a pinned go install (see gosec above) to avoid dependency-review noise.