Getting a --version flag for Cobra CLIs in Go

Featured image for sharing metadata for article

In my post Getting a --version flag for Cobra CLIs in Go, built with GoReleaser I wanted to add a --version flag to my Go command-line tools.

However, I noted that this solution only works when using GoReleaser, and doesn't work when built from source.

Fortunately this week Carlana Johnson wrote about a project she's built for this exact functionality.

So how do we do this with a Cobra CLI?

The below examples can be found in an example repo on GitLab.com.

Firstly, in our main.go, we can pass versioninfo's data to a SetVersionInfo method:

package main

import (
	"time"

	"github.com/carlmjohnson/versioninfo"
	"gitlab.com/tanna.dev/go-cobra-version-example/cmd"
)

func main() {
	cmd.SetVersionInfo(versioninfo.Version, versioninfo.Revision, versioninfo.LastCommit.Format(time.RFC3339))
	cmd.Execute()
}

This then calls this snippet to allow us to set the rootCmd's versioning information:

func SetVersionInfo(version, commit, date string) {
	rootCmd.Version = fmt.Sprintf("%s (Built on %s from Git SHA %s)", version, date, commit)
}

If we build it normally with go build and then invoke it, we'll see the version information:

go build
./go-cobra-version-example --version
go-cobra-version-example version (devel) (Built on 2023-05-27T09:53:47Z from Git SHA 43043f4715f3878b8d13ae73fa6b12dbd1253447)

And if we build it using goreleaser, we still see the version info:

goreleaser release --snapshot --clean
# where $PLATFORM is the OS platform you're running from
./dist/go-cobra-version-example_$PLATFORM/go-cobra-goreleaser-version-example --version
go-cobra-version-example version (devel) (Built on 2023-05-27T09:53:47Z from Git SHA 43043f4715f3878b8d13ae73fa6b12dbd1253447)

As we can see, this doesn't pick up as well when goreleaser is performing a release. Following the docs we can tweak the code to pick up the Goreleaser-defined variables, or the data from versioninfo:

package main

import (
	"time"

	"github.com/carlmjohnson/versioninfo"
	"gitlab.com/tanna.dev/go-cobra-version-example/cmd"
)

// these values are automagically populated by Goreleaser
var (
	version = "dev"
	commit  = "none"
	date    = "unknown"
)

func main() {
	// if installing from source, i.e. not a binary built by `Goreleaser`, this version will not be updated. In that case, use the automagic detection in `versioninfo`
	if version == "dev" {
		version = versioninfo.Version
		commit = versioninfo.Revision
		date = versioninfo.LastCommit.Format(time.RFC3339)
	} else {
		// Goreleaser doesn't prefix with a `v`, which we expect
		version = "v" + version
	}

	cmd.SetVersionInfo(version, commit, date)
	cmd.Execute()
}

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the Apache License 2.0.

#blogumentation #go #goreleaser.

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.