Default the User-Agent to <consumer>/<version> fly-go/<version>#254
Merged
Conversation
Both the GraphQL client and flaps client fell back to a User-Agent with no version (just "/" or the literal "fly-go") when a caller didn't supply Name/Version. Resolve the module's own version via runtime/debug.ReadBuildInfo() so unconfigured clients still identify themselves usefully.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves the default User-Agent sent by fly-go’s GraphQL and flaps clients when callers don’t supply an application name/version, making requests attributable to a specific fly-go version via runtime module metadata.
Changes:
- Added
DefaultUserAgent()that resolves the fly-go module version at runtime viaruntime/debug.ReadBuildInfo(). - Updated the GraphQL client transport defaulting logic to use
DefaultUserAgent()when bothClientOptions.NameandClientOptions.Versionare empty. - Updated the flaps client to default to
fly.DefaultUserAgent()instead of the unversioned"fly-go"literal.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| version.go | Introduces DefaultUserAgent() and module version resolution via build info. |
| client.go | Uses DefaultUserAgent() when no caller name/version is provided. |
| flaps/flaps.go | Switches the flaps default UA to fly.DefaultUserAgent(). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Extend DefaultUserAgent so it identifies the consuming binary using its main module's build info, with fly-go's own resolved version appended as a suffix: "<consumer>/<version> fly-go/<version>" (e.g. "flyctl/v1.2.3 fly-go/v0.7.0"). Previously it only reported fly-go's own version, with no indication of which application was making the request. When fly-go itself is the main module, it still collapses to just "fly-go/<version>".
Extract defaultUserAgent(info *debug.BuildInfo) so the formatting logic can be exercised with synthetic build info, covering the main-module, dependency, local-replace, and unknown-path branches that are otherwise hard to reach from a single real build environment.
Add tests for Transport.setDefaults and flaps.NewWithOptions confirming the User-Agent falls back to a "fly-go/"-prefixed string when no name/version is supplied, and still respects an explicit one when given.
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.
Both the GraphQL client and the flaps client fall back to an uninformative User-Agent when a caller doesn't supply a name/version — the GraphQL client sends a bare
/, and flaps sends the unversioned literalfly-go. This makes it hard to tell which application (and which fly-go version) is talking to the API when the embedding application hasn't wired up its own name/version.Context
fly-go is a library, so it can't bake its own version in at build time (no main package, no
-ldflags). The only way for it to know its own version — or the identity of the binary it's embedded in — is to read it back out of the consuming binary's module info at runtime.Details
Added
version.gowithDefaultUserAgent(), which usesruntime/debug.ReadBuildInfo()to derive:info.Main(module path basename + version), andinfo.Deps(handling thereplace-directive case) orinfo.Mainwhen fly-go itself is the main module.The result is
<consumer>/<version> fly-go/<fly-go-version>, e.g.flyctl/v1.2.3 fly-go/v0.7.0. When fly-go is itself the main module (its own tests/binaries), it collapses to justfly-go/<version>. Any piece that can't be resolved falls back tounknown.client.go:Transport.setDefaultsnow usesDefaultUserAgent()when bothClientOptions.NameandVersionare empty.flaps/flaps.go: the defaultuserAgentis nowfly.DefaultUserAgent()instead of the hardcoded"fly-go"literal.Added unit tests for the version-resolution logic (
version_test.go, covering the main-module, dependency, and local-replace branches via synthetic build info), plus integration tests onTransport.setDefaultsandflaps.NewWithOptionsconfirming the default and the explicit-name/version paths both behave correctly.