fix: Report a valid version string with unreleased builds - #278
Open
drewr wants to merge 3 commits into
Open
Conversation
k8s.io/component-base/version's gitVersion was never set via ldflags in flake.nix, so `datumctl version` crashed parsing its compiled-in placeholder "v0.0.0-master+$Format:%H$". The prior git-describe fallback was also dead: nix flakes strip .git from the copied source, so it silently produced "dev" instead of a real version. Now the git sha comes from self.dirtyRev/rev (reliable without .git), the last tag from an optional untracked VERSION file staged via `git add -N` (flake sources only see files git knows about), and both feed main.version and the component-base ldflags so the result is always a valid <tag>+<sha>[-dev] version string.
drewr
enabled auto-merge
September 5, 2026 20:04
k8s.io/component-base/version's GitVersion is only real when ldflags set it (goreleaser or the nix flake); a plain `go build`/`go run` in local dev still left it at the unparseable compiled-in placeholder, which the plugin compatibility check and update checker both read as a version. Add internal/version.ApplyFallback, called at startup, which detects the placeholder and derives a valid v0.0.0+<sha>[-dev] version from the VCS info Go's toolchain already stamps into the binary automatically. It's a no-op whenever ldflags already provided a real version. Also drop the flake's `-X main.version=...` ldflag, which targeted a variable that doesn't exist in package main.
internal/version.ApplyFallback's runtime patch can only ever produce "v0.0.0+<sha>": component-base's SetDynamicVersion rejects any version whose major/minor/patch don't match the compiled-in placeholder's (0.0.0), and Go's automatic VCS stamping has no notion of the nearest tag anyway. So a plain `go build`/`go run` always showed v0.0.0 even when a real release tag was available. Add `task build`, which embeds the real <last-tag>+<sha>[-dev] version via ldflags at compile time (like nix/goreleaser already do), so local development builds get a proper version instead of the v0.0.0 fallback. Claude-Session: https://claude.ai/code/session_01PKKmeZhi8VV2EcvknMV9Qv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I mostly use datumctl from nix, built from the main branch. That means the version looks like:
This fixes it to look like:
Background
This happens because
k8s.io/component-base/version(which backs the version command) was never given a real version vialdflags, so it kept its compiled-in placeholder. The flake's existinggit describefallback for the version was also silently broken: nix flakes always strip.gitfrom the copied source, so it produceddevinstead of a real value.This PR embeds a real, always-valid version in nix builds: the commit sha comes from
self.dirtyRev/self.rev(populated by nix's own git metadata, no.gitneeded), and the last tag comes from an optional untrackedVERSIONfile thattask nix-buildgenerates and stages before building (nix flakes only see files git knows about). The result (<tag>+<sha>[-dev]) feeds thek8s.io/component-base/versionldflags, matching what.goreleaser.yamlalready does for tagged releases.The same placeholder shows up building outside nix and outside a release too — a plain
go build/go runduring local dev. Since ldflags aren't involved there, this addsinternal/version.ApplyFallback, called at startup: it detects the placeholder and derives a validv0.0.0+<sha>[-dev]version from the VCS info Go's toolchain already stamps into the binary automatically. It's a no-op whenever ldflags already provided a real version, so nix and release builds are unaffected. Also drops the flake's-X main.version=...ldflag, which targeted a variable that doesn't exist inpackage main.ApplyFallback's runtime patch can never surface a real release tag, though —component-base'sSetDynamicVersionrejects any version whose major/minor/patch don't match the compiled-in placeholder's (0.0.0), and Go's VCS stamping has no notion of the nearest tag anyway. So a plaingo buildalways showedv0.0.0even when a real tag was available.task buildcloses that gap: it embeds the real<last-tag>+<sha>[-dev]version via ldflags at compile time (same mechanism nix/goreleaser use), so local development builds get a proper version instead of thev0.0.0fallback.Test plan
task nix-buildsucceeds and embedsgit describe --tags's value plus the commit shatask buildsucceeds and embeds the real last tag plus the commit shago build/go run(no ldflags) produces a validv0.0.0+<sha>[-dev]fallback instead of the placeholderdatumctl version --clientprints a valid version with no parse error, in all three casesgo test ./...and the nix build's test suite pass-devsuffix, not-dirtyhttps://claude.ai/code/session_01PKKmeZhi8VV2EcvknMV9Qv