Documentation
¶
Overview ¶
Package buildinfo exposes build-time and runtime metadata for a Go binary — version, its provenance, commit, build time, branch, Go version, OS/arch, dirty flag, and the list of dependency modules.
Values are populated from two inputs, in priority order:
- -ldflags overrides set at build time (highest precedence).
- runtime/debug.ReadBuildInfo (Go 1.18+) — Main.Version for the module version recorded by `go install pkg@version`, plus VCS data for the commit, build time, and dirty flag.
When neither applies, fields fall back to the DevVersion and Unknown sentinels so callers can render them without nil checks.
Provenance ¶
Info.Source reports which input produced Info.Version — SourceLdflags, SourceModule, or SourceUnknown. This matters because the version string alone is ambiguous: a binary reports "dev" both when it was built locally and when a release pipeline failed to pass its ldflags. Displaying the source turns "why does it say dev?" into a self-answering question.
Info.HasCommit and Info.HasVersion express the same distinction as booleans, so callers never compare against the sentinel strings themselves.
Dependencies ¶
The package has zero third-party dependencies. HTTP, OTEL, Zap, and slog integrations live in separate adapter modules under contrib/, so importing this package pulls in nothing but the standard library.
Typical use ¶
info := buildinfo.Get()
log.Printf("starting %s (%s) commit=%s", info.Version, info.Source, info.Commit)
if !info.HasVersion() {
log.Println("warning: unstamped build")
}
Build with version stamping ¶
go build -ldflags="-X github.com/ubgo/buildinfo.Version=1.2.3"
The -X target is this package's path rather than the consumer's main package, so the same flags work unchanged in any project.
Index ¶
Constants ¶
const ( // DevVersion is Info.Version when no -ldflags stamp and no module version // were available, i.e. a plain local build. DevVersion = "dev" // Unknown is the fallback for Commit, BuildTime, and Branch. Unknown = "unknown" )
Sentinel values used when an input supplied nothing. Exported so callers can compare against them instead of hardcoding the literals — a duplicated sentinel in a consumer breaks silently if this package ever changes one.
Variables ¶
var ( // Version is the semver string for this build (e.g. "1.2.3"). Version string // Commit is the VCS commit hash. Commit string // BuildTime is the build timestamp in RFC3339 format. BuildTime string // Branch is the VCS branch name. Branch string )
These variables can be overridden via -ldflags at build time:
-ldflags="-X github.com/ubgo/buildinfo.Version=1.2.3 \
-X github.com/ubgo/buildinfo.Commit=abc123 \
-X github.com/ubgo/buildinfo.BuildTime=2026-04-26T12:00:00Z \
-X github.com/ubgo/buildinfo.Branch=main"
When unset, values fall back to runtime/debug.ReadBuildInfo (Go 1.18+ VCS data) where applicable. ldflags overrides always win.
Functions ¶
Types ¶
type Info ¶
type Info struct {
// Version is the semver string for this build, or DevVersion when nothing
// supplied one. Check Source to find out which.
Version string `json:"version"`
// Source records which input produced Version. See Source.
Source Source `json:"source"`
// Commit is the VCS commit hash, or Unknown.
Commit string `json:"commit"`
// BuildTime is the build timestamp in RFC3339 format, or Unknown.
BuildTime string `json:"build_time"`
// Branch is the VCS branch name, or Unknown. Go records no branch, so this
// is populated only via -ldflags.
Branch string `json:"branch"`
// GoVersion is the toolchain version that produced the binary.
GoVersion string `json:"go_version"`
// GOOS is the target operating system.
GOOS string `json:"goos"`
// GOARCH is the target architecture.
GOARCH string `json:"goarch"`
// Modified reports an uncommitted working tree at build time. Meaningful
// only alongside a real commit — see HasCommit.
Modified bool `json:"modified"`
// Modules lists dependency modules, with any replace directives resolved
// to their targets.
Modules []Module `json:"modules,omitempty"`
}
Info contains build metadata for a Go binary.
String fields default to DevVersion (Version) or Unknown (Commit, BuildTime, Branch) when neither -ldflags nor runtime/debug data populate them, so callers can render them safely without nil checks. Because those defaults are indistinguishable from real values by inspection alone, Source records which input actually won and HasCommit / HasVersion report whether a field holds real data.
func Get ¶
func Get() Info
Get returns the populated Info struct, cached after the first call.
Population precedence (highest first):
- -ldflags overrides set at build time.
- runtime/debug.ReadBuildInfo data — the module version recorded in Main.Version, plus VCS data (vcs.revision, vcs.time, vcs.modified).
- Sentinel defaults (DevVersion for Version, Unknown for Commit / BuildTime / Branch).
Info.Source reports which of those produced Version, so a caller never has to infer provenance from the string itself.
func (Info) HasCommit ¶ added in v0.1.2
HasCommit reports whether Commit holds a real hash rather than the Unknown sentinel.
Needed because Modified is only meaningful alongside a commit: rendering "unknown (dirty)" asserts a dirty checkout for a build that carries no VCS record at all. Prefer this over comparing against Unknown yourself — the sentinel is this package's business, not its callers'.
func (Info) HasVersion ¶ added in v0.1.2
HasVersion reports whether Version came from a real input (an -ldflags stamp or a resolved module version) rather than falling back to DevVersion.
Equivalent to Source != SourceUnknown, and offered because that is the check most callers actually want when deciding whether to display a version at all.
type Module ¶
type Module struct {
Path string `json:"path"`
Version string `json:"version"`
Sum string `json:"sum,omitempty"`
}
Module describes a single dependency module entry from runtime/debug.
type Source ¶ added in v0.1.2
type Source string
Source identifies which input produced Info.Version.
Exists because the version string alone cannot answer the most common question a user asks about a build: "why does it say dev?" A binary reports DevVersion both when it was built locally and when a release pipeline forgot to pass its ldflags, and those need different responses. Surfacing the source makes the difference self-diagnosing rather than a support conversation.
const ( // SourceLdflags means Version was stamped at build time via // -X github.com/ubgo/buildinfo.Version=... — the release path. SourceLdflags Source = "ldflags" // SourceModule means Version came from the module version the Go toolchain // recorded in BuildInfo.Main.Version, i.e. the binary was installed with // `go install <pkg>@<version>`. SourceModule Source = "module" // SourceUnknown means neither input applied and Version is DevVersion: a // plain `go build`, `go run`, or `go test` binary with no release // provenance. SourceUnknown Source = "unknown" )
Directories
¶
| Path | Synopsis |
|---|---|
|
contrib
|
|
|
buildinfo-chi
module
|
|
|
buildinfo-echo
module
|
|
|
buildinfo-fiber
module
|
|
|
buildinfo-gin
module
|
|
|
buildinfo-nethttp
module
|
|
|
buildinfo-otel
module
|
|
|
buildinfo-slog
module
|
|
|
buildinfo-zap
module
|