Send a real User-Agent on API requests - #79
Open
Kevin-Chant wants to merge 3 commits into
Open
Kevin-Chant wants to merge 3 commits into
Kevin-Chant wants to merge 3 commits into
Conversation
The generated SDK sent Speakeasy's default, which carries the generator's version rather than the CLI's, so GrowthBook could only identify CLI traffic by the Go module path buried in it. Sends `growthbook-cli/<version> (<go version>; <os>/<arch>)`, taking the version from `customcfg.Version` — `internal/cli` imports this package, so its `Version` isn't reachable from here. The wrapper sits outside the diagnostics client so `--debug` prints what actually goes on the wire. The one-line hook in the generated client.go is rebuilt into its existing patch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
15 tasks
Self-review follow-up. customcfg.Version is only stamped by goreleaser, so anything built with `go install module@vX` reported "dev" despite knowing its own version. Read it from the module build info when ldflags left the sentinel behind. A `go build` from a checkout still reports "dev", since build info has no version to give there either. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Forcing the User-Agent made `-H "User-Agent: ..."` silently do nothing, so a documented global flag stopped working for that one header. The back-end classifies first-party clients with an anchored regex (`/^growthbook-(cli|mcp|skills|coderefs)\/(\S+)/i` in api-client.util.ts) and records the raw User-Agent alongside the bucket. RFC 9110 User-Agent is a space-separated list of product tokens, most significant first, so prepending ours satisfies the regex while leaving the caller's token on the wire: a proxy or wrapper can still identify itself, and CLI attribution cannot be lost. The compat check in updatecheck.go bypasses the SDK client, so it went out as Go's default User-Agent and landed in the back-end's generic `go` bucket - CLI traffic mislabelled as someone's Go integration. It now sets the same header. `UserAgent()` moved to customcfg because internal/client already imports that package for `Version`; the reverse direction would cycle. The `-H` help text is amended from custom_startup.go rather than by widening the root.go patch, which stays one line. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Features and Changes
We send Speakeasy's default
User-Agent, which reads as a library and carries the generator's version (0.0.1) rather than ours — GrowthBook can only spot CLI traffic by the Go module path buried in it. growthbook/growthbook#7038 adds per-client API usage tracking and this is the half that makes the CLI visible to it.Requests now send
growthbook-cli/<version> (<go version>; <os>/<arch>). The version comes fromcustomcfg.Versionrather thancli.Version, becauseinternal/cliimports this package. goreleaser stamps that via ldflags; when it's unstamped we read the module version out of the build info, sogo installed binaries report their real version too. Only ago buildfrom a checkout still reportsdev, which has no version to report anyway.The wrapper goes outside the diagnostics client so
--debugprints what actually goes on the wire.WrapClientForUserAgentlives in a hand-writtencustom_useragent.go; the one-line hook in the generatedclient.gois folded into that file's existing patch.Testing
growthbook projects listagainst a local GrowthBook -> server logsclient: "cli",clientVersion: "dev"-X ...customcfg.Version=2.6.0->clientVersion: "2.6.0"--debug-> prints the real User-Agent, not the SDK defaultclient.goand reproduces the working file exactly