fix(update): recover the release version from build info - #197
Merged
Conversation
A `go install github.com/livetemplate/prereview@latest` binary reported version "dev" and could never self-update — `--update` refused with ErrDevBuild, whose own message recommends that exact install method. Only goreleaser sets -X main.version, and `go install` doesn't apply it. Go does record the module version in the binary's embedded build info, so fall back to that when the ldflag is absent. The fallback only accepts a bare vX.Y.Z tag: a local `go build` embeds a version too, but as a pseudo-version and/or with a "+dirty" suffix, and treating those as releases would let the on-run check overwrite a developer's own build with a download. A build sitting on an exact tag with a dirty tree reads as "v0.25.0+dirty" — the suffix is the only thing separating it from a genuine release, hence the reject-any-suffix rule rather than parsing past it. The leading "v" is stripped so --version reads identically whether the binary came from goreleaser (which stamps "0.25.0") or `go install` (whose build info says "v0.25.0"). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E8bxKS4xC9LisPy7Gacgmq
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.
Problem
A binary installed with
go install github.com/livetemplate/prereview@latestreports versiondevand can never self-update —--updaterefuses withErrDevBuild, whose own message recommends that exact install method. Only goreleaser sets-X main.version;go installdoesn't apply it.Verified before writing anything, in an isolated
GOBINso nothing landed onPATH:Its build info, however, records the real thing:
mod github.com/livetemplate/prereview v0.25.0.Fix
update.ReleaseVersionfalls back todebug.ReadBuildInfo()when the ldflag is absent, wired in viainit()inmain.go.The fallback only accepts a bare
vX.Y.Ztag. This strictness is the load-bearing part. A localgo buildembeds a version too, and building this very branch produced:An exact release tag on a dirty tree. The obvious predicate — strip build metadata, accept valid semver — would have let that build claim to be
v0.25.0, and the on-run update check would then overwrite a developer's own working binary with a download. SoisReleaseTagrejects on any suffix rather than parsing past it: pseudo-versions,+dirty, and(devel)all staydev.A clean build sitting exactly on a release tag does become self-updatable. That's intentional and safe — no uncommitted work to lose, and it's by definition an older release.
The leading
vis stripped so--versionreads identically whether the binary came from goreleaser (which stamps0.25.0) orgo install(whose build info saysv0.25.0).ErrDevBuild's text now says the binary "was built from a source tree", which is whatdevactually means once this lands.Verification
isReleaseTagcases + 7releaseVersioncases, including the real-world pseudo-versionv0.24.5-0.20260723204349-7ab83524cad7+dirtygo buildstill printsdevand--updatestill refuses — the safety direction, checked by handgo vetclean; touched files gofmt-cleanversionbeforeinit()runs (topUsageis aconst; every read is insiderun()/runExternal()/main()), so nothing captures the stale"dev"literal--version— the goreleaser and Homebrewsystem "#{bin}/prereview", "--version"calls are exit-code smoke tests — so the addedv-stripping breaks no consumerreleaseVersiontakes the build-info reader as a parameter, since a test binary's own build info isn't the one under test.🤖 Generated with Claude Code
https://claude.ai/code/session_01E8bxKS4xC9LisPy7Gacgmq