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 blog post is 100% human-written, and has nothing derived from LLMs (be it code, editorial support or prose).

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.