All checks were successful
check / check (pull_request) Successful in 2m37s
No tag could be cut from this repo at all. Three independent blockers. goreleaser was configured for GitHub while the repo lives on Gitea: .goreleaser.yaml had a release: block but no gitea_urls:, so goreleaser defaulted to the GitHub API and a release would have failed or published somewhere nobody is looking. It now points at https://git.eeqj.de/api/v1. The version was a hardcoded Makefile constant, VERSION := 1.0.0-rc.1, so every local build claimed to be a release candidate that had never been tagged and did not exist, while git tag -l was empty and internal/globals defaulted to dev. The version now comes from git, via the new script/version: the exact tag with a leading v stripped when HEAD is on one (so a make build and a goreleaser build of the same commit report the same string, and it matches the archive names), otherwise dev-<12-char sha>, with -dirty appended in either case when tracked files are modified. Untracked files are not counted, matching git describe --dirty. goreleaser's snapshot template gets the same treatment: it was {{ incpatch .Version }}-next, which manufactures a release number from the last tag and, with no tags at all, from goreleaser's fabricated v0.0.0. That change had one non-obvious consequence. internal/cli/version.go gated its "this is a development build" notice on the version being exactly "dev", so as soon as untagged builds carried a commit sha the notice would have gone silent and an unreleased binary would have read as a release. The gate is now globals.IsDevVersion, a predicate over a string rather than a comparison against a global so that it can be tested, and it is tested at the boundary that matters: dev-<sha> and its -dirty variant are development builds, 1.0.0-dev and 1.0.0-rc.1 are not. The command writes to cmd.OutOrStdout() so its output can be asserted on at all. Releases now come from CI rather than a workstation: a tag-triggered .gitea/workflows/release.yml, with fetch-depth: 0 because a shallow checkout has no tags and would silently mislabel the release, and with the RELEASE_TOKEN repository secret passed as GITEA_TOKEN (documented in README.md; the runner's automatic token is deliberately not used, since it is not guaranteed to carry release write scope). script/release unsets any GITHUB_TOKEN or GITLAB_TOKEN it finds, because goreleaser picks its forge from whichever token variable is set and refuses to run when it sees more than one -- an unrelated runner token must not get to decide where these artifacts are published. make release and make release-snapshot were the last two Makefile targets that were not shims; they now call script/release and script/release-snapshot, which resolve goreleaser the way script/lint resolves the linter -- a PATH binary is accepted only at the pinned version, never as a silent fallback. script/bootstrap installs it from a sha256-verified GitHub release archive per REPO_POLICIES.md, through a separate script/install-goreleaser: separate because script/bootstrap hard-fails without a usable Docker daemon by design, and the release runner needs goreleaser without needing Docker. dist/ and .tool/ are gitignored and excluded from the Docker build context. Verified by running it: make release-snapshot produces the four linux,darwin x amd64,arm64 archives plus checksums.txt, and the binary from dist/ reports dev-<sha> with the development-build notice. Tag handling was exercised in a throwaway repository; no tag was created here, since that is the owner's call. Signing, SBOM, reproducible builds, shell completions and a man page remain out of scope.
82 lines
2.7 KiB
Go
82 lines
2.7 KiB
Go
// Package globals holds application-wide metadata (name, version,
|
|
// commit) that is populated at build time via linker flags.
|
|
package globals
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// 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 not built
|
|
// from a tagged commit. script/version emits either this exact string
|
|
// (outside a git checkout) or this string followed by "-" and the
|
|
// commit it was built from, and goreleaser's snapshot template matches
|
|
// that shape. It is deliberately not a number: a build that is not a
|
|
// release must not name itself like one.
|
|
const DevVersion = "dev"
|
|
|
|
// 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
|
|
|
|
// 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. Both "dev" and "dev-<sha>" (and its "-dirty" variant)
|
|
// count: a caller that compares against "dev" exactly would treat every
|
|
// commit-stamped development build as a release.
|
|
func IsDevVersion(v string) bool {
|
|
return v == DevVersion || strings.HasPrefix(v, DevVersion+"-")
|
|
}
|
|
|
|
// 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
|
|
}
|