common/version/version.go

126 lines
2.4 KiB
Go

package version
import (
"fmt"
"runtime"
"runtime/debug"
"strings"
"github.com/prometheus/client_golang/prometheus"
"github.com/spf13/cobra"
"go.ntppool.org/common/logger"
"golang.org/x/mod/semver"
)
// VERSION has the current software version (set in the build process)
var VERSION string
var buildTime string
var gitVersion string
var gitModified bool
var info Info
type Info struct {
Version string `json:",omitempty"`
GitRev string `json:",omitempty"`
BuildTime string `json:",omitempty"`
}
func init() {
info.BuildTime = buildTime
info.GitRev = gitVersion
if len(VERSION) == 0 {
VERSION = "dev-snapshot"
} else {
if !strings.HasPrefix(VERSION, "v") {
VERSION = "v" + VERSION
}
if !semver.IsValid(VERSION) {
logger.Setup().Warn("invalid version number", "version", VERSION)
}
}
if bi, ok := debug.ReadBuildInfo(); ok {
for _, h := range bi.Settings {
// logger.Setup().Info("build info", "k", h.Key, "v", h.Value)
switch h.Key {
case "vcs.time":
buildTime = h.Value
info.BuildTime = h.Value
case "vcs.revision":
// https://blog.carlmjohnson.net/post/2023/golang-git-hash-how-to/
// todo: use BuildInfo.Main.Version if revision is empty
gitVersion = h.Value
info.GitRev = h.Value
case "vcs.modified":
if h.Value == "true" {
gitModified = true
}
}
}
}
info.Version = VERSION
Version()
}
func VersionCmd(name string) *cobra.Command {
versionCmd := &cobra.Command{
Use: "version",
Short: "Print version and build information",
Run: func(cmd *cobra.Command, args []string) {
ver := Version()
fmt.Printf("%s %s\n", name, ver)
},
}
return versionCmd
}
func RegisterMetric(registry prometheus.Registerer) {
buildInfo := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "build_info",
Help: "Build information",
},
[]string{"version", "build"},
)
registry.MustRegister(buildInfo)
info := VersionInfo()
buildInfo.WithLabelValues(fmt.Sprintf("%s/%s", info.Version, info.GitRev), info.BuildTime).Set(1)
}
var v string
func VersionInfo() Info {
return info
}
func Version() string {
if len(v) > 0 {
return v
}
extra := []string{}
if len(buildTime) > 0 {
extra = append(extra, buildTime)
}
extra = append(extra, runtime.Version())
v := VERSION
if len(gitVersion) > 0 {
g := gitVersion
if len(g) > 7 {
g = g[0:7]
}
v += "/" + g
if gitModified {
v += "-M"
}
}
v = fmt.Sprintf("%s (%s)", v, strings.Join(extra, ", "))
return v
}