check / check (push) Successful in 12m33s
A `go install` of a tag sets no linker flags, so the binary reported `dev`. Version, commit and commit date that the linker flags leave unset now come from the build info Go records. Go records a pseudo-version for an untagged commit and a `+dirty` suffix for a modified checkout; `IsDevVersion` now counts both as development builds, using `golang.org/x/mod`. Model: opus-5-5
158 lines
5.3 KiB
Go
158 lines
5.3 KiB
Go
// 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 <sneak@sneak.berlin>"
|
|
|
|
// 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-<sha>" 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
|
|
}
|