Do you use
cobraandgoreleaserto package and build your golang CLIs. If not, you should reconsider. They are a fantastic combination and combined with one of my new projects you can add an easy to use and extensible version subcommand which features different outputs

I’ve recently been playing around with building a lot of golang CLI’s, I’ll be
writing more about this at a later date, mostly while experimenting with
Kubernetes kubectl plugins. One thing I’ve found really useful is to use
cobra the golang library that helps you
to create powerful CLIs it combined with goreleaser
to help with packaging and distribution. Something I’ve always admired of
kubectl was the very simple ways you can get the version you’re currently
running and the different ways they can be mutated.
So I spent sometime and created a unified
go-version package for taking
in ldflags from the compiler and giving you both a JSON output and a plain
text output. All you need to do is create a simple command file for the
version and copy and paste the below code into your version.go file.
Getting Started
package main
import (
"fmt"
goVersion "github.com/christopherhein/go-version"
"github.com/spf13/cobra"
)
var (
shortened = false
version = "dev"
commit = "none"
date = "unknown"
versionCmd = &cobra.Command{
Use: "version",
Short: "Version will output the current build information",
Long: ``,
Run: func(_ *cobra.Command, _ []string) {
var response string
versionOutput := goVersion.New(version, commit, date)
if shortened {
response = versionOutput.ToShortened()
} else {
response = versionOutput.ToJSON()
}
fmt.Printf("%+v", response)
return
},
}
)
func init() {
versionCmd.Flags().BoolVarP(&shortened, "short", "s", false, "Use shortened output for version information.")
rootCmd.AddCommand(versionCmd)
}Then when you are compiling your code you can either use goreleaser which will
automatically add -X main.commit=<SOMEHASH> and -X main.date=<SOMEDATE> or
run a command like this to build your CLI.
go build -ldflags "-X main.commit=<SOMEHASH> -X main.date=<SOMEDATE>"Once you have done this your CLI will have a new version subcommand. This
subcommand will responde to -s or --short to return different variations of
the output.
This is really useful if you plan to use your tool within CI/CD processes where you might need to check the version installed before running the process.
$ ./my-cli version
{"Version":"dev","Commit":"<SOMEHASH>","Date":"<SOMEDATE>"}Or to make this human readible you could use:
$ ./my-cli -s
Version: dev
Commit: <SOMEHASH>
Date: <SOMEDATE>Long-Term
Future plans are to make it so that all you have to do is include a the package
and pass the cobra function to a register function in go-version. Also to add
support for YAML and potentially jsonpath output mechanisms.
Conclusion
If you find yourself using cobra to build out a CLI think about potentially
using my go-version package to give an easy way to expose proper versioning to
your customers. It will definitely make it easier for others to work with your
tool and allow them to check this while debugging.
Go check out the project and it’s roadmap in the issues. https://github.com/christopherhein/go-version
- Chris