Version¶
pkg/version provides semantic version handling for GTB-based tools: storing
build-time version information, comparing versions for update checks, and
detecting development builds.
The Version Interface¶
type Version interface {
GetVersion() string // Semver string, e.g. "v1.2.3"
GetCommit() string // Git commit hash or "none"
GetDate() string // Build date string
String() string // "v1.2.3 (abc1234)" or "v1.2.3"
Compare(other string) int // -1, 0, or 1 (semver comparison)
IsDevelopment() bool // true if version is a dev/dirty build
}
Info Struct¶
Info is the concrete implementation of Version. It is populated at build
time via ldflags:
type Info struct {
Version string `json:"version" yaml:"version"`
Commit string `json:"commit" yaml:"commit"`
Date string `json:"date" yaml:"date"`
}
func NewInfo(version, commit, date string) Info
Usage in a Go binary:
// main.go
var (
version = "dev"
commit = "none"
date = "unknown"
)
func main() {
v := version.NewInfo(version, commit, date)
props := &props.Props{
Version: v,
// ...
}
root.Execute(props)
}
Setting with GoReleaser / ldflags:
# .goreleaser.yaml
builds:
- ldflags:
- -s -w
- -X main.version={{.Version}}
- -X main.commit={{.Commit}}
- -X main.date={{.Date}}
Version Comparison¶
CompareVersions compares two version strings using golang.org/x/mod/semver.
Both v-prefixed and bare versions are accepted.
import "gitlab.com/phpboyscout/go-tool-base/pkg/version"
result := version.CompareVersions("1.2.3", "v1.3.0")
// result == -1 (1.2.3 < 1.3.0 โ update available)
result = version.CompareVersions("v2.0.0", "1.9.9")
// result == 1 (2.0.0 > 1.9.9 โ already ahead)
result = version.CompareVersions("v1.0.0", "1.0.0")
// result == 0 (equal)
Return values follow Go convention: -1 (less than), 0 (equal), 1 (greater than).
The Info.Compare(other string) int method compares the current build version
against a remote version string:
if props.Version.Compare(latestRelease) < 0 {
p.Logger.Warn("update available", "latest", latestRelease)
}
Version Formatting¶
FormatVersionString normalises version strings by adding or removing the v
prefix:
version.FormatVersionString("1.2.3", true) // "v1.2.3"
version.FormatVersionString("v1.2.3", true) // "v1.2.3" (idempotent)
version.FormatVersionString("v1.2.3", false) // "1.2.3"
version.FormatVersionString("", true) // "" (empty string preserved)
Development Build Detection¶
IsDevelopment() returns true when:
- The version string is not a valid semver (e.g.
"dev","unknown") - The version contains
-devor-dirtysuffixes
version.NewInfo("dev", "none", "unknown").IsDevelopment() // true
version.NewInfo("v0.0.0", "abc", "2026-01-01").IsDevelopment() // true (invalid semver)
version.NewInfo("v1.2.3", "abc", "2026-01-01").IsDevelopment() // false
version.NewInfo("v1.2.3-dev", "abc", "2026-01-01").IsDevelopment() // true
The self-updater uses this to require --force when updating from a
development build, preventing accidental overwriting of local builds.
Integration with Props¶
Props.Version holds the build version:
p := &props.Props{
Version: version.NewInfo(buildVersion, buildCommit, buildDate),
}
// In a version command
func runVersionCmd(p *props.Props) {
p.Logger.Print(p.Version.String())
// prints: "v1.2.3 (abc1234)"
}
Related Documentation¶
- Props โ dependency injection container
- Setup โ self-updater that uses version comparison
- Auto-Update Lifecycle โ how update checks use version info