check / check (push) Successful in 12m14s
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
210 lines
5.9 KiB
Go
210 lines
5.9 KiB
Go
package globals_test
|
|
|
|
import (
|
|
"runtime/debug"
|
|
"testing"
|
|
|
|
"sneak.berlin/go/vaultik/internal/globals"
|
|
)
|
|
|
|
// TestGlobalsNew ensures the globals package initializes correctly
|
|
func TestGlobalsNew(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
g, err := globals.New()
|
|
if err != nil {
|
|
t.Fatalf("Failed to create Globals: %v", err)
|
|
}
|
|
|
|
if g == nil {
|
|
t.Fatal("Globals instance is nil")
|
|
}
|
|
|
|
if g.Appname != "vaultik" {
|
|
t.Errorf("Expected Appname to be 'vaultik', got '%s'", g.Appname)
|
|
}
|
|
|
|
// Version and Commit will be "dev" and "unknown" by default
|
|
if g.Version == "" {
|
|
t.Error("Version should not be empty")
|
|
}
|
|
|
|
if g.Commit == "" {
|
|
t.Error("Commit should not be empty")
|
|
}
|
|
}
|
|
|
|
// TestIsDevVersion covers the boundary that matters: everything
|
|
// script/version, a plain docker build and goreleaser's snapshot
|
|
// template can emit for an untagged build must be recognised as a
|
|
// development build, and a real tag must not be. A plain equality check
|
|
// against "dev" used to decide this, which classified every
|
|
// commit-stamped dev build as a release.
|
|
func TestIsDevVersion(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
cases := []struct {
|
|
version string
|
|
want bool
|
|
}{
|
|
// What an untagged build produces.
|
|
{"dev", true},
|
|
{"dev-b6e4a218a39e", true},
|
|
{"dev-b6e4a218a39e-dirty", true},
|
|
// What `git describe --tags --always --dirty` produces with no
|
|
// tag reachable, and on a commit after a tag.
|
|
{"877eb2f", true},
|
|
{"877eb2f-dirty", true},
|
|
{"v1.0.0-3-g877eb2f", true},
|
|
{"v1.0.0-3-g877eb2f-dirty", true},
|
|
{"1.0.0-rc.1-12-g877eb2f", true},
|
|
// A tagged commit with uncommitted changes is not that tag.
|
|
{"v1.0.0-dirty", true},
|
|
// What Go records for a build without linker flags: a
|
|
// pseudo-version for an untagged commit, "+dirty" for a
|
|
// modified checkout.
|
|
{"v1.0.0-rc3.0.20261111001226-abcdefabcdef", true},
|
|
{"v0.0.0-20261111001226-abcdefabcdef", true},
|
|
{"v1.0.1-0.20261111001226-abcdefabcdef", true},
|
|
{"v1.0.0+dirty", true},
|
|
// What a tagged build produces (goreleaser's .Version strips
|
|
// the leading "v"; script/version keeps it).
|
|
{"1.0.0", false},
|
|
{"0.1.0", false},
|
|
{"1.0.0-rc.1", false},
|
|
{"v1.0.0", false},
|
|
{"v1.0.0-rc3", false},
|
|
// A release must not be mistaken for a dev build just because
|
|
// the string happens to contain "dev".
|
|
{"1.0.0-dev", false},
|
|
{"developer", false},
|
|
// A binary with no version string at all did not get stamped,
|
|
// which is a build failure, not a release. It must never print
|
|
// as one. The Makefile refuses to build when script/version
|
|
// yields nothing; this covers a binary linked some other way.
|
|
{"", true},
|
|
// What script/docker and script/cibuild stamp when the host
|
|
// has no git checkout.
|
|
{"unknown", true},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
if got := globals.IsDevVersion(tc.version); got != tc.want {
|
|
t.Errorf("IsDevVersion(%q) = %v, want %v", tc.version, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestDefaultVersionIsDev pins the default: a binary whose linker flags
|
|
// and build info name no version must report itself as a development
|
|
// build rather than as some default release number.
|
|
func TestDefaultVersionIsDev(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if !globals.IsDevVersion(globals.DevVersion) {
|
|
t.Errorf("DevVersion %q is not recognised as a dev version",
|
|
globals.DevVersion)
|
|
}
|
|
}
|
|
|
|
// buildInfo returns build info with the given main module version and,
|
|
// when revision is not empty, the commit settings Go records for a
|
|
// build from a git checkout.
|
|
func buildInfo(version, revision string) *debug.BuildInfo {
|
|
info := &debug.BuildInfo{
|
|
Main: debug.Module{Path: "sneak.berlin/go/vaultik", Version: version},
|
|
}
|
|
|
|
if revision != "" {
|
|
info.Settings = []debug.BuildSetting{
|
|
{Key: "vcs.revision", Value: revision},
|
|
{Key: "vcs.time", Value: "2026-11-10T23:12:26Z"},
|
|
}
|
|
}
|
|
|
|
return info
|
|
}
|
|
|
|
// TestFromBuildInfo covers a binary from `go install` of a tag, which
|
|
// carries no linker flags: it must report the tag. Values the linker
|
|
// flags set are kept.
|
|
func TestFromBuildInfo(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const (
|
|
tag = "v1.0.0-rc3"
|
|
rev = "0123456789abcdef0123456789abcdef01234567"
|
|
)
|
|
|
|
cases := []struct {
|
|
name string
|
|
info *debug.BuildInfo
|
|
version, commit, date string
|
|
wantVersion, wantCommit string
|
|
wantDate string
|
|
}{
|
|
{
|
|
name: "go install of a tag",
|
|
info: buildInfo(tag, ""),
|
|
version: globals.DevVersion,
|
|
commit: globals.Unknown,
|
|
date: globals.Unknown,
|
|
wantVersion: tag,
|
|
wantCommit: globals.Unknown,
|
|
wantDate: globals.Unknown,
|
|
},
|
|
{
|
|
name: "empty version",
|
|
info: buildInfo(tag, ""),
|
|
version: "",
|
|
commit: globals.Unknown,
|
|
date: globals.Unknown,
|
|
wantVersion: tag,
|
|
wantCommit: globals.Unknown,
|
|
wantDate: globals.Unknown,
|
|
},
|
|
{
|
|
name: "go build in a git checkout",
|
|
info: buildInfo(tag, rev),
|
|
version: globals.DevVersion,
|
|
commit: globals.Unknown,
|
|
date: globals.Unknown,
|
|
wantVersion: tag,
|
|
wantCommit: rev,
|
|
wantDate: "2026-11-10",
|
|
},
|
|
{
|
|
name: "Go could not tell the version",
|
|
info: buildInfo("(devel)", ""),
|
|
version: globals.DevVersion,
|
|
commit: globals.Unknown,
|
|
date: globals.Unknown,
|
|
wantVersion: globals.DevVersion,
|
|
wantCommit: globals.Unknown,
|
|
wantDate: globals.Unknown,
|
|
},
|
|
{
|
|
name: "linker flags set",
|
|
info: buildInfo(tag, rev),
|
|
version: "v1.0.0-rc2-4-gabcdef1",
|
|
commit: "abcdef1",
|
|
date: "2026-11-01",
|
|
wantVersion: "v1.0.0-rc2-4-gabcdef1",
|
|
wantCommit: "abcdef1",
|
|
wantDate: "2026-11-01",
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
version, commit, date := globals.FromBuildInfo(
|
|
tc.info, tc.version, tc.commit, tc.date)
|
|
|
|
if version != tc.wantVersion || commit != tc.wantCommit ||
|
|
date != tc.wantDate {
|
|
t.Errorf("%s: got %q, %q, %q; want %q, %q, %q", tc.name,
|
|
version, commit, date,
|
|
tc.wantVersion, tc.wantCommit, tc.wantDate)
|
|
}
|
|
}
|
|
}
|