diff --git a/main.go b/main.go index f8b599e..6fc9272 100644 --- a/main.go +++ b/main.go @@ -29,14 +29,37 @@ import ( "io" "os" "os/exec" + "runtime/debug" "strconv" "strings" "github.com/DivergentCodes/commitlint/lint" ) +// version is stamped by the release workflow via -ldflags. Builds that are not +// produced by that workflow — notably `go install ...@v1.2.3`, the documented +// install path — leave it at the default, so fall back to the version the Go +// toolchain recorded in the binary. var version = "0.0.0-dev" +// resolveVersion prefers an ldflags-stamped version, then the module version +// embedded by `go install`, and otherwise reports the default. +func resolveVersion() string { + if version != "0.0.0-dev" { + return version + } + info, ok := debug.ReadBuildInfo() + if !ok || info.Main.Version == "" { + return version + } + // A build from a local directory records "(devel)", which is less + // informative than the default. + if info.Main.Version == "(devel)" { + return version + } + return info.Main.Version +} + func main() { if len(os.Args) < 2 { usage() @@ -46,7 +69,7 @@ func main() { case "lint": os.Exit(runLint(os.Args[2:])) case "version", "--version", "-v": - fmt.Println(version) + fmt.Println(resolveVersion()) case "help", "--help", "-h": usage() default: diff --git a/main_test.go b/main_test.go index f89a691..4314d23 100644 --- a/main_test.go +++ b/main_test.go @@ -144,3 +144,24 @@ func TestWriteTextSkipsPassingMessages(t *testing.T) { t.Errorf("failing message should be printed:\n%s", buf.String()) } } + +// `go install ...@vX.Y.Z` does not run the release workflow's -ldflags, so +// without a build-info fallback every installed binary reported 0.0.0-dev. +// Under `go test` the module version is "(devel)", so this cannot assert the +// installed-version path directly; it pins the precedence and the guarantee +// that the fallback never surfaces "(devel)" or an empty string. +func TestResolveVersion(t *testing.T) { + orig := version + defer func() { version = orig }() + + version = "v2.3.4" + if got := resolveVersion(); got != "v2.3.4" { + t.Errorf("stamped version should win: got %q, want v2.3.4", got) + } + + version = "0.0.0-dev" + got := resolveVersion() + if got == "" || got == "(devel)" { + t.Errorf("fallback must be informative, got %q", got) + } +}