diff --git a/internal/cmd/root.go b/internal/cmd/root.go index c73f59a..5fc3dc5 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -49,6 +49,10 @@ var ( // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { + // Cobra only registers the --version flag when Version is non-empty. + // Setting the template alone left --version and -v undefined, even though + // the man page and the shell completions both advertised them. + RootCmd.Version = version.GetVersion() RootCmd.SetVersionTemplate("y509 version {{.Version}}\nBuild: " + version.GetFullVersion() + "\n") if err := RootCmd.Execute(); err != nil { diff --git a/internal/version/version.go b/internal/version/version.go index 1932dab..4068e2e 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -2,6 +2,7 @@ package version import ( + "runtime/debug" "strings" ) @@ -14,6 +15,41 @@ var ( BuildDate = "unknown" ) +// Release builds get these values from -ldflags. A `go install` build gets no +// ldflags at all, so it reported itself as "dev" forever -- even though the +// toolchain had already stamped the module version and the VCS revision into +// the binary. Read them back out. +func init() { + info, ok := debug.ReadBuildInfo() + if !ok { + return + } + + // Each value falls back on its own. A build that sets only Version through + // -ldflags should still pick up the commit and the build time the toolchain + // recorded, rather than being left reporting "unknown" for both. + if Version == "dev" { + // "(devel)" is what a build from a local working tree reports. + if info.Main.Version != "" && info.Main.Version != "(devel)" { + Version = info.Main.Version + } + } + for _, setting := range info.Settings { + switch setting.Key { + case "vcs.revision": + // An empty value must not overwrite "unknown" -- it would render as + // "y509 version dev ()". + if GitCommit == "unknown" && setting.Value != "" { + GitCommit = setting.Value + } + case "vcs.time": + if BuildDate == "unknown" && setting.Value != "" { + BuildDate = setting.Value + } + } + } +} + // GetVersion returns the version string func GetVersion() string { return Version