Keep prometheus/client_golang at its v1.24.1 floor and test the latest release in CI
Supersedes #979.
Why not bump to 1.25.0
The SDK is a library, so whatever go/go.mod requires, MVS forces on every app that imports it. client_golang 1.25.0 changes the api/prometheus/v1 signatures (Query, QueryRange, Series, LabelNames, LabelValues, api.Client). The SDK doesn't use that package, but a downstream app that does would break on its next SDK bump. The earlier head of this PR required 1.25.0, and Codex flagged it on go.mod.
So go/go.mod keeps a floor that only the SDK's own use of the dependency decides, and CI tracks the latest release separately.
Change
- Floor: client_golang stays at v1.24.1, the version main ships.
go/go.mod,go/go.sumandgo.work.sumare byte-identical to main, so its indirects (common v0.70.1, procfs v0.21.1, client_model v0.6.2, x/text v0.41.0 from #999) stay where they are. The evidence is below. - New CI job: "Go Tests (latest dependencies)" in
test.yml. Running withGOWORK=off(the module as a consumer resolves it), it doesgo get -t -u ./...(-tso test-only modules like otel/sdk move too),go get github.com/prometheus/client_golang@latestandgo mod tidy, prints what moved, then runsgo build,go vetandgo test ./.... It commits nothing. It leaves outassert-lockfiles-unchanged --verify-cleanon purpose, since rewriting go.mod/go.sum is its job; a comment there says so, and the floor job keeps that guard. It usescache: falseso it doesn't write latest-version modules under the floor job's go.sum cache key. Actions are pinned by SHA, the same as the other jobs. - Dependabot no longer proposes client_golang version updates. This is an
ignoreentry with all threeupdate-typesand noversions, and a comment points at the new job. Security updates are still possible. For security-only runs, dependabot-core keeps only an ignore'sversionsand dropsupdate-types(IgnoreCondition#ignored_versions:return versions if security_updates_only). GitHub's docs say the same forupdate-typesunderallow("update-typesonly affects version updates, not security updates"). Forignore, the docs only mark the option as one that touches security updates, which in practice meansversions. That's why the entry must not get aversionslist. TestExpositionShapenow compares the emitted bytes. It serves the registry throughpromhttp.HandlerFor, withAccept: text/plain; version=0.0.4andAccept-Encoding: identitypinned, and compares the response body byte for byte against the golden string. It also checks status 200, thetext/plain; version=0.0.4content type, and that there's no content encoding.GatherAndCompareparsed the expected text and re-encoded both sides through the same encoder, so an encoder change would have passed it (Codex's second finding).promhttpexists on every version the module supports;testutil.GatherAndFormatdoesn't.
Choosing the floor
These are empirical results, run on Linux amd64 with GOTOOLCHAIN=go1.26.9. For each candidate I started from main's go.mod, dropped the prometheus indirects so tidy re-resolved them at the minimum, then ran go get client_golang@vX, go mod tidy and go test ./pkg/basecamp/prometheus/..., plus govulncheck v1.8.0:
| client_golang | library builds | SDK tests (core + testutil) | govulncheck |
|---|---|---|---|
| v1.11.0 | yes | no | GO-2022-0322 in a required module (not called) |
| v1.11.1 – v1.13.1 | yes | no: testutil.CollectAndCount(reg, …) doesn't accept a *Registry | clean |
| v1.14.0 | yes | yes | clean |
| v1.15.1, v1.17.0, v1.19.1, v1.20.5, v1.21.1, v1.22.0, v1.23.2, v1.24.0 | yes | yes | clean |
| v1.24.1 (floor) | yes | yes | clean |
| v1.25.0 (latest) | yes | yes | clean |
The byte-exact TestExpositionShape passes on v1.14.0, v1.20.5, v1.23.2, v1.24.1 and v1.25.0.
The lowest technically valid floor is v1.14.0: the library alone builds on v1.11.1, and testutil as the tests use it needs 1.14. I kept v1.24.1 because it matches main: this PR then forces nothing on anyone that isn't already forced today, and going lower helps no consumer we know of. basecamp-cli doesn't require client_golang at all, and basecamp-mcp-server already requires 1.25.0. A lower floor also means the floor job tests a client_golang and prometheus/common from 2023, which no supported consumer runs. If you'd rather publish the widest compatible range, v1.14.0 passes every check above. It's a one-line go.mod change. Tidy then lowers common, procfs and client_model; at v1.15.1 it also added golang/protobuf and matttproud/golang_protobuf_extensions as indirects.
For the operator
- Required check: "Go Tests (latest dependencies)" isn't added to the required checks, and whether to add it is your call. The case against: an upstream release can turn it red on a PR that changed nothing, which would block unrelated merges. The case for: without that, a red run is only a signal. It also only runs on PRs, pushes to main and
workflow_dispatch. A weeklyscheduletrigger would notice breakage during quiet weeks, buttest.ymlhas no schedule today, and adding one there would run every job. - #979 (dependabot's 1.25.0 bump) has no further purpose. Close it, or let dependabot close it once this ignore lands.
- The same floor argument applies to the other direct dependencies (otel, coder/websocket, oapi-codegen/runtime, zalando/go-keyring), and dependabot still raises those floors. The latest-deps job already covers them, so extending the ignore is a cheap follow-up if you want it.
Verification
Run on Linux amd64 with GOTOOLCHAIN=go1.26.9 (go/go.mod's toolchain), at this head:
cd go && go build ./...,go vet ./...: okcd go && go test -count=1 ./...andgo test -race -count=1 ./...: passmake conformance-runner-tests-go: pass. Conformance runner: Passed 310, Failed 0, Skipped 2, Total 312cd go && govulncheck ./...(v1.8.0): No vulnerabilities found./scripts/assert-lockfiles-unchanged --verify-clean: Dependency manifests match the committed treegolangci-lint run(go/.golangci.yml, v2.14.0) on the prometheus package: 0 issues.actionlintandzizmor --offlineontest.yml: clean- Latest-deps job simulated with its exact steps: it moved client_golang 1.24.1 → 1.25.0, common → v0.72.1, procfs → v0.22.0, client_model → v0.6.3, x/text → v0.43.0, x/sys → v0.49.0, x/tools → v0.51.0, protobuf → v1.36.12, godbus/dbus → v5.2.4 and others, then build, vet and every test passed.
- Mutations: changing one expected counter value (
1→2) failsTestExpositionShape, and so does inserting one extra space inside a sample line.