Skip to content

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 not tools/? tools/ already holds the first-party tools/driftcheck package, which is part of the main module (it imports go-glx). Placing this module's go.mod at tools/ would have swallowed driftcheck into the isolated tool module — breaking go run ./tools/driftcheck, go test ./tools/..., and make check-code-drift. Keeping the two concerns in separate top-level directories avoids that collision.

Tools pinned here

ToolPackageUsed by
govulncheckgolang.org/x/vuln/cmd/govulncheck.github/workflows/security.yml, make vulncheck

Tools deliberately NOT here

  • gosec stays on a version-pinned go install in .github/workflows/security.yml, with the version pinned by the top-level .gosec-version file (single source of truth, also consumed by make gosec). Its autofix package imports the Google generative-ai-go SDK, which transitively pulls the Google Cloud SDK, gRPC, and OpenTelemetry. Committing that graph to a scanned go.mod would make dependency-review block PRs whenever any of those (unreachable, build-time-only) dependencies picks up a new advisory. go install keeps gosec reproducible without exposing that tree. Run it locally with make gosec. Dependabot cannot propose a bump for this pin: its gomod ecosystem only reads go.mod files, where gosec deliberately does not appear, and its github-actions ecosystem only reads uses: references, not a go install [email protected] line in a run: block. So the weekly .github/workflows/gosec-pin-currency.yml workflow fails when .gosec-version falls behind the latest gosec release. It is a standalone workflow rather than a job in security.yml on purpose — security.yml is 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 matching go run in make license-check). Its tree pulls go.opencensus.io, golang.org/x/net, and licenseclassifier — committing that graph here would make dependency-review block PRs on advisories in build-time-only code, the same trade-off as gosec.
  • golangci-lint is pinned via .golangci-lint-version and run through golangci-lint-action (for only-new-issues support — 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:

bash
go tool -modfile=ci-tools/go.mod govulncheck ./...

Or use the Makefile wrapper: make vulncheck.

Bumping or adding a tool

bash
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 tidy

Commit 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.

Licensed under Apache License 2.0