// Package globals holds application-wide metadata (name, version, // commit) that is populated at build time via linker flags, or from the // build info Go records in the binary when the linker flags set none. package globals import ( "regexp" "runtime/debug" "strings" "time" "golang.org/x/mod/module" ) // Appname is the application name, populated from main(). var Appname = "vaultik" //nolint:gochecknoglobals // set via -ldflags at build time // DevVersion is the version a binary reports when it was built without // git metadata: script/version emits it outside a git checkout, and a // binary keeps it when neither its linker flags nor its Go build info // name a version. goreleaser's snapshot template stamps // it followed by "-" and the commit it was built from. It is // deliberately not a number. const DevVersion = "dev" // Unknown is what Commit and CommitDate hold when the build did not // stamp them, and the version script/docker and script/cibuild stamp // when the host has no git checkout. const Unknown = "unknown" // Version is the application version, populated from main(). var Version = DevVersion //nolint:gochecknoglobals // set via -ldflags at build time // Commit is the git commit hash, populated from main(). var Commit = Unknown //nolint:gochecknoglobals // set via -ldflags at build time // CommitDate is the ISO-8601 date of the commit, populated from main(). var CommitDate = Unknown //nolint:gochecknoglobals // set via -ldflags at build time // develVersion is the main module version Go records when it cannot // tell which version it built. const develVersion = "(devel)" // UseBuildInfo applies FromBuildInfo to Version, Commit and CommitDate, // with the build info of the running binary. func UseBuildInfo() { info, ok := debug.ReadBuildInfo() if !ok { return } Version, Commit, CommitDate = FromBuildInfo( info, Version, Commit, CommitDate) } // FromBuildInfo returns version, commit and commitDate, with each one // the linker flags left unset taken from info. A `go install` of a tag // sets no linker flags, but Go records the tag as the main module's // version. Go records the commit and its time only when it builds from // a git checkout. The time is cut to a date, as the Makefile stamps it. func FromBuildInfo( info *debug.BuildInfo, version, commit, commitDate string, ) (string, string, string) { if (version == "" || version == DevVersion) && info.Main.Version != "" && info.Main.Version != develVersion { version = info.Main.Version } for _, s := range info.Settings { switch s.Key { case "vcs.revision": if commit == Unknown { commit = s.Value } case "vcs.time": t, err := time.Parse(time.RFC3339, s.Value) if commitDate == Unknown && err == nil { commitDate = t.UTC().Format(time.DateOnly) } } } return version, commit, commitDate } // Author identifies the upstream author of vaultik. const Author = "Jeffrey Paul " // Homepage is the canonical URL for vaultik. const Homepage = "https://sneak.berlin/go/vaultik" // ReleasesURL is where tagged release artifacts are published. const ReleasesURL = "https://git.eeqj.de/sneak/vaultik/releases" // License is the SPDX identifier for the project license. const License = "MIT" // Globals contains application-wide configuration and metadata. type Globals struct { Appname string Version string Commit string CommitDate string StartTime time.Time } // New creates and returns a new Globals instance initialized with the // package-level variables. func New() (*Globals, error) { return &Globals{ Appname: Appname, Version: Version, Commit: Commit, CommitDate: CommitDate, }, nil } // IsDevVersion reports whether v names a development build rather than // a release. "dev" and goreleaser's snapshot "dev-" count, and so // does what `git describe --tags --always --dirty` gives a make or // docker build of an untagged commit: the bare short commit, or // tag-N-gHASH on a commit after a tag. A Go pseudo-version counts: Go // records one for a build of an untagged commit without linker flags. // Any version ending in "-dirty" or "+dirty" counts, a modified // checkout of a tag ("v1.0.0-dirty", "v1.0.0+dirty") included. // A plain tag such as "v1.0.0" or "1.0.0" is a release. // // The empty string counts too. Nothing that knows its version reports // no version, so an empty Version means the stamping failed, and the // safe reading of "we could not establish that this is a release" is // that it is not one. The Makefile refuses to build at all in that // case; this is the second line of defence, for a binary linked by // something other than the Makefile. Unknown counts for the same // reason. func IsDevVersion(v string) bool { if v == "" || v == Unknown || v == DevVersion || strings.HasPrefix(v, DevVersion+"-") || strings.HasSuffix(v, "-dirty") || strings.HasSuffix(v, "+dirty") || module.IsPseudoVersion(v) { return true } return regexp.MustCompile(`^(.+-[0-9]+-g)?[0-9a-f]+$`).MatchString(v) } // shortCommitLen is the number of commit-hash characters ShortCommit keeps. const shortCommitLen = 12 // ShortCommit returns the first 12 chars of the commit hash, or the // whole string if it's shorter (e.g. "unknown"). func (g *Globals) ShortCommit() string { if len(g.Commit) > shortCommitLen { return g.Commit[:shortCommitLen] } return g.Commit }