diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 57e464a9..5c06d8de 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -34,7 +34,12 @@ builds: - amd64 - arm64 ldflags: - - -s -w -X github.com/psviderski/uncloud/internal/version.version={{ .Version }} + - -s -w + -X github.com/psviderski/uncloud/internal/version.version={{.Version}} + -X github.com/psviderski/uncloud/internal/version.commit={{.Commit}} + -X github.com/psviderski/uncloud/internal/version.dirty={{.IsGitDirty}} + -X github.com/psviderski/uncloud/internal/version.date={{.CommitDate}} + -X github.com/psviderski/uncloud/internal/version.builtBy=goreleaser - id: uncloudd main: ./cmd/uncloudd @@ -47,7 +52,12 @@ builds: - amd64 - arm64 ldflags: - - -s -w -X github.com/psviderski/uncloud/internal/version.version={{ .Version }} + - -s -w + -X github.com/psviderski/uncloud/internal/version.version={{.Version}} + -X github.com/psviderski/uncloud/internal/version.commit={{.Commit}} + -X github.com/psviderski/uncloud/internal/version.dirty={{.IsGitDirty}} + -X github.com/psviderski/uncloud/internal/version.date={{.CommitDate}} + -X github.com/psviderski/uncloud/internal/version.builtBy=goreleaser archives: - id: uncloud diff --git a/go.mod b/go.mod index a3936afc..afc16191 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/Masterminds/semver v1.5.0 github.com/Masterminds/squirrel v1.5.4 github.com/alecthomas/chroma/v2 v2.20.0 + github.com/caarlos0/go-version v0.2.2 github.com/caddyserver/caddy/v2 v2.8.4 github.com/cenkalti/backoff/v4 v4.3.0 github.com/charmbracelet/colorprofile v0.4.2 diff --git a/go.sum b/go.sum index b3291e3b..1a55b4bb 100644 --- a/go.sum +++ b/go.sum @@ -138,6 +138,8 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembj github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/caarlos0/go-version v0.2.2 h1:5r+nlrg4H2wOVwWjqRqRRIRbZ7ytRmjC9xoMIP0a5kQ= +github.com/caarlos0/go-version v0.2.2/go.mod h1:X+rI5VAtJDpcjCjeEIXpxGa5+rTcgur1FK66wS0/944= github.com/caddyserver/caddy/v2 v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk= github.com/caddyserver/caddy/v2 v2.8.4/go.mod h1:vmDAHp3d05JIvuhc24LmnxVlsZmWnUwbP5WMjzcMPWw= github.com/caddyserver/certmagic v0.21.4 h1:e7VobB8rffHv8ZZpSiZtEwnLDHUwLVYLWzWSa1FfKI0= diff --git a/internal/version/version.go b/internal/version/version.go index 8b5850d9..6fb82c7d 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -1,6 +1,13 @@ package version -var version string +import ( + "encoding/json" + "fmt" + "strings" + "text/tabwriter" + + goversion "github.com/caarlos0/go-version" +) func String() string { if version == "" { @@ -8,3 +15,83 @@ func String() string { } return version } + +// Build-time metadata injected via -ldflags by GoReleaser (see .goreleaser.yaml). +// These are package-level so the same paths can be referenced from any binary's ldflags. +var ( + version string + commit string + dirty string + date string + builtBy string +) + +// Info holds version and build metadata for an Uncloud binary. +type Info struct { + Version string + GitCommit string + GitState string + BuildDate string + BuiltBy string + GoVersion string + Platform string +} + +// String returns the human-readable representation of Info as a tab-aligned key-value block. +func (i Info) String() string { + var b strings.Builder + w := tabwriter.NewWriter(&b, 0, 0, 2, ' ', 0) + fmt.Fprintf(w, "Version:\t%s\n", i.Version) + fmt.Fprintf(w, "Git commit:\t%s\n", i.GitCommit) + fmt.Fprintf(w, "Git state:\t%s\n", i.GitState) + fmt.Fprintf(w, "Build date:\t%s\n", i.BuildDate) + fmt.Fprintf(w, "Built by:\t%s\n", i.BuiltBy) + fmt.Fprintf(w, "Go version:\t%s\n", i.GoVersion) + fmt.Fprintf(w, "Platform:\t%s\n", i.Platform) + _ = w.Flush() + return b.String() +} + +// JSONString returns the JSON-encoded representation of Info, indented for human readability. +func (i Info) JSONString() (string, error) { + b, err := json.MarshalIndent(i, "", " ") + if err != nil { + return "", fmt.Errorf("marshal info: %w", err) + } + return string(b), nil +} + +// GetInfo returns version and build metadata for the current binary. Values injected at build time via +// -ldflags take precedence over the runtime/debug.BuildInfo fields. +func GetInfo() Info { + vi := goversion.GetVersionInfo( + func(i *goversion.Info) { + i.GitVersion = String() + if commit != "" { + i.GitCommit = commit + } + // The ldflag value is the raw goreleaser {{.IsGitDirty}} boolean string ("true"/"false"). + switch dirty { + case "true": + i.GitTreeState = "dirty" + case "false": + i.GitTreeState = "clean" + } + if date != "" { + i.BuildDate = date + } + if builtBy != "" { + i.BuiltBy = builtBy + } + }, + ) + return Info{ + Version: vi.GitVersion, + GitCommit: vi.GitCommit, + GitState: vi.GitTreeState, + BuildDate: vi.BuildDate, + BuiltBy: vi.BuiltBy, + GoVersion: vi.GoVersion, + Platform: vi.Platform, + } +}