Merge pull request #226 from safing/migrate-build-info

Migrate to runtime/debug.BuildInfo for most VCS information
This commit is contained in:
Patrick Pacher 2024-03-27 13:48:20 +01:00 committed by GitHub
commit a90357bbc2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 66 additions and 68 deletions

View file

@ -5,21 +5,19 @@ import (
"fmt" "fmt"
"os" "os"
"runtime" "runtime"
"runtime/debug"
"strings" "strings"
"sync"
) )
var ( var (
name = "[NAME]" name string
version = "[version unknown]" version = "dev build"
commit = "[commit unknown]"
license = "[license unknown]"
buildOptions = "[options unknown]"
buildUser = "[user unknown]"
buildHost = "[host unknown]"
buildDate = "[date unknown]"
buildSource = "[source unknown]" buildSource = "[source unknown]"
license = "[license unknown]"
compareVersion bool info *Info
loadInfo sync.Once
) )
// Info holds the programs meta information. // Info holds the programs meta information.
@ -28,11 +26,11 @@ type Info struct {
Version string Version string
License string License string
Commit string Commit string
BuildOptions string Time string
BuildUser string Source string
BuildHost string Dirty bool
BuildDate string
BuildSource string debug.BuildInfo
} }
// Set sets meta information via the main routine. This should be the first thing your program calls. // Set sets meta information via the main routine. This should be the first thing your program calls.
@ -40,47 +38,56 @@ func Set(setName string, setVersion string, setLicenseName string, compareVersio
name = setName name = setName
version = setVersion version = setVersion
license = setLicenseName license = setLicenseName
compareVersion = compareVersionToTag
} }
// GetInfo returns all the meta information about the program. // GetInfo returns all the meta information about the program.
func GetInfo() *Info { func GetInfo() *Info {
return &Info{ loadInfo.Do(func() {
buildInfo, _ := debug.ReadBuildInfo()
buildSettings := make(map[string]string)
for _, setting := range buildInfo.Settings {
buildSettings[setting.Key] = setting.Value
}
info = &Info{
Name: name, Name: name,
Version: version, Version: version,
Commit: commit,
License: license, License: license,
BuildOptions: buildOptions, BuildInfo: *buildInfo,
BuildUser: buildUser, Source: buildSource,
BuildHost: buildHost, Commit: buildSettings["vcs.revision"],
BuildDate: buildDate, Time: buildSettings["vcs.time"],
BuildSource: buildSource, Dirty: buildSettings["vcs.modified"] == "true",
} }
})
return info
} }
// Version returns the short version string. // Version returns the short version string.
func Version() string { func Version() string {
if !compareVersion || strings.HasPrefix(commit, fmt.Sprintf("tags/v%s-0-", version)) { info := GetInfo()
return version
} if info.Dirty {
return version + "*" return version + "*"
}
return version
} }
// FullVersion returns the full and detailed version string. // FullVersion returns the full and detailed version string.
func FullVersion() string { func FullVersion() string {
s := "" info := GetInfo()
if !compareVersion || strings.HasPrefix(commit, fmt.Sprintf("tags/v%s-0-", version)) {
s += fmt.Sprintf("%s\nversion %s\n", name, version) builder := new(strings.Builder)
} else {
s += fmt.Sprintf("%s\ndevelopment build, built on top version %s\n", name, version) builder.WriteString(fmt.Sprintf("%s\nversion %s\n", info.Name, Version()))
} builder.WriteString(fmt.Sprintf("\ncommit %s\n", info.Commit))
s += fmt.Sprintf("\ncommit %s\n", commit) builder.WriteString(fmt.Sprintf("built with %s (%s) %s/%s\n", runtime.Version(), runtime.Compiler, runtime.GOOS, runtime.GOARCH))
s += fmt.Sprintf("built with %s (%s) %s/%s\n", runtime.Version(), runtime.Compiler, runtime.GOOS, runtime.GOARCH) builder.WriteString(fmt.Sprintf(" on %s\n", info.Time))
s += fmt.Sprintf(" using options %s\n", strings.ReplaceAll(buildOptions, "§", " ")) builder.WriteString(fmt.Sprintf("\nLicensed under the %s license.\nThe source code is available here: %s", license, info.Source))
s += fmt.Sprintf(" by %s@%s\n", buildUser, buildHost)
s += fmt.Sprintf(" on %s\n", buildDate) return builder.String()
s += fmt.Sprintf("\nLicensed under the %s license.\nThe source code is available here: %s", license, buildSource)
return s
} }
// CheckVersion checks if the metadata is ok. // CheckVersion checks if the metadata is ok.
@ -92,17 +99,11 @@ func CheckVersion() error {
return nil // testing on windows return nil // testing on windows
default: default:
// check version information // check version information
if name == "[NAME]" { if name == "[NAME]" || license == "[license unknown]" {
return errors.New("must call SetInfo() before calling CheckVersion()") return errors.New("must call SetInfo() before calling CheckVersion()")
} }
if version == "[version unknown]" ||
commit == "[commit unknown]" || if version == "[version unknown]" {
license == "[license unknown]" ||
buildOptions == "[options unknown]" ||
buildUser == "[user unknown]" ||
buildHost == "[host unknown]" ||
buildDate == "[date unknown]" ||
buildSource == "[source unknown]" {
return errors.New("please build using the supplied build script.\n$ ./build {main.go|...}") return errors.New("please build using the supplied build script.\n$ ./build {main.go|...}")
} }
} }

View file

@ -17,11 +17,8 @@ func registerInfoMetric() error {
map[string]string{ map[string]string{
"version": checkUnknown(meta.Version), "version": checkUnknown(meta.Version),
"commit": checkUnknown(meta.Commit), "commit": checkUnknown(meta.Commit),
"build_options": checkUnknown(meta.BuildOptions), "build_date": checkUnknown(meta.Time),
"build_user": checkUnknown(meta.BuildUser), "build_source": checkUnknown(meta.Source),
"build_host": checkUnknown(meta.BuildHost),
"build_date": checkUnknown(meta.BuildDate),
"build_source": checkUnknown(meta.BuildSource),
"go_os": runtime.GOOS, "go_os": runtime.GOOS,
"go_arch": runtime.GOARCH, "go_arch": runtime.GOARCH,
"go_version": runtime.Version(), "go_version": runtime.Version(),