diff --git a/cli/root.go b/cli/root.go index d2fc267221594..a112de28f5b28 100644 --- a/cli/root.go +++ b/cli/root.go @@ -53,7 +53,6 @@ func init() { func Root() *cobra.Command { cmd := &cobra.Command{ Use: "coder", - Version: buildinfo.Version(), SilenceErrors: true, SilenceUsage: true, Long: `Coder — A tool for provisioning self-hosted development environments. @@ -90,10 +89,10 @@ func Root() *cobra.Command { users(), portForward(), workspaceAgent(), + versionCmd(), ) cmd.SetUsageTemplate(usageTemplate()) - cmd.SetVersionTemplate(versionTemplate()) cmd.PersistentFlags().String(varURL, "", "Specify the URL to your deployment.") cmd.PersistentFlags().String(varToken, "", "Specify an authentication token.") @@ -110,6 +109,27 @@ func Root() *cobra.Command { return cmd } +// versionCmd prints the coder version +func versionCmd() *cobra.Command { + return &cobra.Command{ + Use: "version", + Short: "Show coder version", + Example: "coder version", + RunE: func(cmd *cobra.Command, args []string) error { + var str strings.Builder + _, _ = str.WriteString(fmt.Sprintf("Coder %s", buildinfo.Version())) + buildTime, valid := buildinfo.Time() + if valid { + _, _ = str.WriteString(" " + buildTime.Format(time.UnixDate)) + } + _, _ = str.WriteString("\r\n" + buildinfo.ExternalURL() + "\r\n") + + _, _ = fmt.Fprint(cmd.OutOrStdout(), str.String()) + return nil + }, + } +} + // createClient returns a new client from the command context. // It reads from global configuration files if flags are not set. func createClient(cmd *cobra.Command) (*codersdk.Client, error) { @@ -286,17 +306,6 @@ Use "{{.CommandPath}} [command] --help" for more information about a command. {{end}}` } -func versionTemplate() string { - template := `Coder {{printf "%s" .Version}}` - buildTime, valid := buildinfo.Time() - if valid { - template += " " + buildTime.Format(time.UnixDate) - } - template += "\r\n" + buildinfo.ExternalURL() - template += "\r\n" - return template -} - // FormatCobraError colorizes and adds "--help" docs to cobra commands. func FormatCobraError(err error, cmd *cobra.Command) string { helpErrMsg := fmt.Sprintf("Run '%s --help' for usage.", cmd.CommandPath()) diff --git a/cli/root_test.go b/cli/root_test.go index 28206cc46707f..48298267a02db 100644 --- a/cli/root_test.go +++ b/cli/root_test.go @@ -1,8 +1,11 @@ package cli_test import ( + "bytes" "testing" + "github.com/coder/coder/buildinfo" + "github.com/stretchr/testify/require" "github.com/coder/coder/cli" @@ -19,4 +22,18 @@ func TestRoot(t *testing.T) { errStr := cli.FormatCobraError(err, cmd) require.Contains(t, errStr, "Run 'coder delete --help' for usage.") }) + + t.Run("Version", func(t *testing.T) { + t.Parallel() + + buf := new(bytes.Buffer) + cmd, _ := clitest.New(t, "version") + cmd.SetOut(buf) + err := cmd.Execute() + require.NoError(t, err) + + output := buf.String() + require.Contains(t, output, buildinfo.Version(), "has version") + require.Contains(t, output, buildinfo.ExternalURL(), "has url") + }) }