diff --git a/CHANGELOG.md b/CHANGELOG.md index 788e82c2..44e44bb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ## Changes since v7.15.3 +- [#3452](https://github.com/oauth2-proxy/oauth2-proxy/pull/3452) fix: resolve version from build info when not set via ldflags (so `go install`-ed binaries report a real version instead of `undefined`) (@Lrifton92) + # V7.15.3 ## Release Highlights diff --git a/pkg/version/version.go b/pkg/version/version.go index 8635c8ba..628036be 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -1,4 +1,30 @@ package version -// VERSION contains version information +import "runtime/debug" + +// VERSION contains version information. It is set at build time via +// -ldflags "-X github.com/oauth2-proxy/oauth2-proxy/v7/pkg/version.VERSION=". +// When the binary is built without those flags (for example via +// `go install github.com/oauth2-proxy/oauth2-proxy/v7@latest`), it falls back +// to the module version recorded in the build info so that `--version` still +// reports a meaningful value instead of "undefined". var VERSION = "undefined" + +func init() { + VERSION = resolveVersion(VERSION, debug.ReadBuildInfo) +} + +// resolveVersion returns ldflagsVersion when it has been explicitly set at +// build time. Otherwise it derives the version from the module build info, +// allowing `go install`-ed binaries to report a meaningful version. +func resolveVersion(ldflagsVersion string, readBuildInfo func() (*debug.BuildInfo, bool)) string { + if ldflagsVersion != "" && ldflagsVersion != "undefined" { + return ldflagsVersion + } + if info, ok := readBuildInfo(); ok && info != nil { + if v := info.Main.Version; v != "" && v != "(devel)" { + return v + } + } + return ldflagsVersion +} diff --git a/pkg/version/version_test.go b/pkg/version/version_test.go new file mode 100644 index 00000000..9629a485 --- /dev/null +++ b/pkg/version/version_test.go @@ -0,0 +1,63 @@ +package version + +import ( + "runtime/debug" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResolveVersion(t *testing.T) { + testCases := []struct { + name string + ldflagsVersion string + buildInfo *debug.BuildInfo + buildInfoOK bool + expected string + }{ + { + name: "ldflags version takes precedence over build info", + ldflagsVersion: "v7.15.3", + buildInfo: &debug.BuildInfo{Main: debug.Module{Version: "v7.15.0"}}, + buildInfoOK: true, + expected: "v7.15.3", + }, + { + name: "falls back to build info version when undefined", + ldflagsVersion: "undefined", + buildInfo: &debug.BuildInfo{Main: debug.Module{Version: "v7.15.3"}}, + buildInfoOK: true, + expected: "v7.15.3", + }, + { + name: "keeps undefined when build info is unavailable", + ldflagsVersion: "undefined", + buildInfo: nil, + buildInfoOK: false, + expected: "undefined", + }, + { + name: "keeps undefined for a (devel) build info version", + ldflagsVersion: "undefined", + buildInfo: &debug.BuildInfo{Main: debug.Module{Version: "(devel)"}}, + buildInfoOK: true, + expected: "undefined", + }, + { + name: "keeps undefined for an empty build info version", + ldflagsVersion: "undefined", + buildInfo: &debug.BuildInfo{Main: debug.Module{Version: ""}}, + buildInfoOK: true, + expected: "undefined", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := resolveVersion(tc.ldflagsVersion, func() (*debug.BuildInfo, bool) { + return tc.buildInfo, tc.buildInfoOK + }) + assert.Equal(t, tc.expected, result) + }) + } +}