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,34 +5,32 @@ 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]" buildSource = "[source unknown]"
license = "[license unknown]" license = "[license unknown]"
buildOptions = "[options unknown]"
buildUser = "[user unknown]"
buildHost = "[host unknown]"
buildDate = "[date unknown]"
buildSource = "[source unknown]"
compareVersion bool info *Info
loadInfo sync.Once
) )
// Info holds the programs meta information. // Info holds the programs meta information.
type Info struct { type Info struct {
Name string Name string
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() {
Name: name, buildInfo, _ := debug.ReadBuildInfo()
Version: version, buildSettings := make(map[string]string)
Commit: commit, for _, setting := range buildInfo.Settings {
License: license, buildSettings[setting.Key] = setting.Value
BuildOptions: buildOptions, }
BuildUser: buildUser,
BuildHost: buildHost, info = &Info{
BuildDate: buildDate, Name: name,
BuildSource: buildSource, Version: version,
} License: license,
BuildInfo: *buildInfo,
Source: buildSource,
Commit: buildSettings["vcs.revision"],
Time: buildSettings["vcs.time"],
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

@ -15,18 +15,15 @@ func registerInfoMetric() error {
_, err := NewGauge( _, err := NewGauge(
"info", "info",
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), "go_os": runtime.GOOS,
"build_date": checkUnknown(meta.BuildDate), "go_arch": runtime.GOARCH,
"build_source": checkUnknown(meta.BuildSource), "go_version": runtime.Version(),
"go_os": runtime.GOOS, "go_compiler": runtime.Compiler,
"go_arch": runtime.GOARCH, "comment": commentOption(),
"go_version": runtime.Version(),
"go_compiler": runtime.Compiler,
"comment": commentOption(),
}, },
func() float64 { func() float64 {
// Report as 0 the first time in order to detect (re)starts. // Report as 0 the first time in order to detect (re)starts.