Skip to content

Default the User-Agent to <consumer>/<version> fly-go/<version>#254

Merged
dangra merged 4 commits into
mainfrom
default-user-agent-version
Jul 6, 2026
Merged

Default the User-Agent to <consumer>/<version> fly-go/<version>#254
dangra merged 4 commits into
mainfrom
default-user-agent-version

Conversation

@dangra

@dangra dangra commented Jul 6, 2026

Copy link
Copy Markdown
Member

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 literal fly-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.go with DefaultUserAgent(), which uses runtime/debug.ReadBuildInfo() to derive:

    • the consuming binary's identity from info.Main (module path basename + version), and
    • fly-go's own resolved version, found via info.Deps (handling the replace-directive case) or info.Main when 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 just fly-go/<version>. Any piece that can't be resolved falls back to unknown.

  • client.go: Transport.setDefaults now uses DefaultUserAgent() when both ClientOptions.Name and Version are empty.

  • flaps/flaps.go: the default userAgent is now fly.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 on Transport.setDefaults and flaps.NewWithOptions confirming the default and the explicit-name/version paths both behave correctly.

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.
Copilot AI review requested due to automatic review settings July 6, 2026 14:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 via runtime/debug.ReadBuildInfo().
  • Updated the GraphQL client transport defaulting logic to use DefaultUserAgent() when both ClientOptions.Name and ClientOptions.Version are 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.

Comment thread client.go
Comment thread flaps/flaps.go
dangra added 3 commits July 6, 2026 11:58
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.
@dangra dangra changed the title Default the User-Agent to fly-go/<version> instead of a bare name Default the User-Agent to <consumer>/<version> fly-go/<version> Jul 6, 2026
@dangra dangra merged commit 50643b1 into main Jul 6, 2026
5 checks passed
@dangra dangra deleted the default-user-agent-version branch July 6, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants