From 4d3fa76df999ca5a34eaf0307edff7516c2a89a6 Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Mon, 22 May 2023 14:47:11 +0200 Subject: [PATCH 1/2] Add version flag to print version and exit --- cmd/root/root.go | 9 ++++---- cmd/root/version.go | 45 ++++++++++++++++++++++++++++++++++++++++ cmd/version/version.go | 7 ++----- internal/build/print.go | 11 ++++++++++ internal/helpers.go | 1 + internal/version_test.go | 29 ++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 cmd/root/version.go create mode 100644 internal/build/print.go create mode 100644 internal/version_test.go diff --git a/cmd/root/root.go b/cmd/root/root.go index c519d21669c..8cfc76fddf3 100644 --- a/cmd/root/root.go +++ b/cmd/root/root.go @@ -67,6 +67,10 @@ var RootCmd = &cobra.Command{ // Wrap flag errors to include the usage string. func flagErrorFunc(c *cobra.Command, err error) error { + // We would like to use [errors.Is] here, but pflag doesn't wrap errors. + if strings.HasSuffix(err.Error(), errExitFromVersion.Error()) { + return build.PrintVersion(c.OutOrStdout()) + } return fmt.Errorf("%w\n\n%s", err, c.UsageString()) } @@ -105,9 +109,4 @@ func Execute() { func init() { RootCmd.SetFlagErrorFunc(flagErrorFunc) - - // The VS Code extension passes `-v` in debug mode and must be changed - // to use the new flags in `./logger.go` prior to removing this flag. - RootCmd.PersistentFlags().BoolP("verbose", "v", false, "") - RootCmd.PersistentFlags().MarkHidden("verbose") } diff --git a/cmd/root/version.go b/cmd/root/version.go new file mode 100644 index 00000000000..2acfe26c0d2 --- /dev/null +++ b/cmd/root/version.go @@ -0,0 +1,45 @@ +package root + +import ( + "errors" + "strconv" +) + +// errExitFromVersion is returned when the version flag is set. +var errExitFromVersion = errors.New("exit from version flag") + +type versionFlag struct { +} + +func (v *versionFlag) Set(s string) error { + b, err := strconv.ParseBool(s) + if err != nil { + return err + } + if b { + // Return if this flag as soon as this flag gets set. + // If no runnable command is specified, the root command's + // hooks are not executed, and this is the only place to + // detect whether the version flag is set. + return errExitFromVersion + } + return nil +} + +func (v *versionFlag) Type() string { + return "bool" +} + +func (v *versionFlag) String() string { + return "false" +} + +func (v *versionFlag) IsBoolFlag() bool { + return true +} + +func init() { + var f versionFlag + flag := RootCmd.PersistentFlags().VarPF(&f, "version", "v", "print version and exit") + flag.NoOptDefVal = "true" +} diff --git a/cmd/version/version.go b/cmd/version/version.go index c021a9809a0..70d2f9b42a9 100644 --- a/cmd/version/version.go +++ b/cmd/version/version.go @@ -2,7 +2,6 @@ package version import ( "encoding/json" - "fmt" "github.com/databricks/cli/cmd/root" "github.com/databricks/cli/internal/build" @@ -16,15 +15,13 @@ var versionCmd = &cobra.Command{ Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { - info := build.GetInfo() if detail { enc := json.NewEncoder(cmd.OutOrStdout()) enc.SetIndent("", " ") - return enc.Encode(info) + return enc.Encode(build.GetInfo()) } - fmt.Fprintln(cmd.OutOrStdout(), info.Version) - return nil + return build.PrintVersion(cmd.OutOrStdout()) }, } diff --git a/internal/build/print.go b/internal/build/print.go new file mode 100644 index 00000000000..812b86791e3 --- /dev/null +++ b/internal/build/print.go @@ -0,0 +1,11 @@ +package build + +import ( + "fmt" + "io" +) + +func PrintVersion(w io.Writer) error { + _, err := fmt.Fprintf(w, "Databricks CLI v%s\n", GetInfo().Version) + return err +} diff --git a/internal/helpers.go b/internal/helpers.go index b972b91ee7f..42132a54977 100644 --- a/internal/helpers.go +++ b/internal/helpers.go @@ -13,6 +13,7 @@ import ( "time" "github.com/databricks/cli/cmd/root" + _ "github.com/databricks/cli/cmd/version" "github.com/stretchr/testify/require" ) diff --git a/internal/version_test.go b/internal/version_test.go new file mode 100644 index 00000000000..54104002074 --- /dev/null +++ b/internal/version_test.go @@ -0,0 +1,29 @@ +package internal + +import ( + "fmt" + "testing" + + "github.com/databricks/cli/internal/build" + "github.com/stretchr/testify/assert" +) + +var expectedVersion = fmt.Sprintf("Databricks CLI v%s\n", build.GetInfo().Version) + +func TestVersionFlagShort(t *testing.T) { + stdout, stderr := RequireSuccessfulRun(t, "-v") + assert.Equal(t, expectedVersion, stdout.String()) + assert.Equal(t, "", stderr.String()) +} + +func TestVersionFlagLong(t *testing.T) { + stdout, stderr := RequireSuccessfulRun(t, "--version") + assert.Equal(t, expectedVersion, stdout.String()) + assert.Equal(t, "", stderr.String()) +} + +func TestVersionCommand(t *testing.T) { + stdout, stderr := RequireSuccessfulRun(t, "version") + assert.Equal(t, expectedVersion, stdout.String()) + assert.Equal(t, "", stderr.String()) +} From 8db5436715a342bd7d9607b761843ac67168bc5c Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Mon, 22 May 2023 20:43:42 +0200 Subject: [PATCH 2/2] Use native Cobra version feature --- cmd/root/root.go | 10 ++++----- cmd/root/version.go | 45 ----------------------------------------- cmd/version/version.go | 7 +++++-- internal/build/print.go | 11 ---------- 4 files changed, 9 insertions(+), 64 deletions(-) delete mode 100644 cmd/root/version.go delete mode 100644 internal/build/print.go diff --git a/cmd/root/root.go b/cmd/root/root.go index 8cfc76fddf3..3b940a491c9 100644 --- a/cmd/root/root.go +++ b/cmd/root/root.go @@ -15,8 +15,9 @@ import ( // RootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ - Use: "databricks", - Short: "Databricks CLI", + Use: "databricks", + Short: "Databricks CLI", + Version: build.GetInfo().Version, // Cobra prints the usage string to stderr if a command returns an error. // This usage string should only be displayed if an invalid combination of flags @@ -67,10 +68,6 @@ var RootCmd = &cobra.Command{ // Wrap flag errors to include the usage string. func flagErrorFunc(c *cobra.Command, err error) error { - // We would like to use [errors.Is] here, but pflag doesn't wrap errors. - if strings.HasSuffix(err.Error(), errExitFromVersion.Error()) { - return build.PrintVersion(c.OutOrStdout()) - } return fmt.Errorf("%w\n\n%s", err, c.UsageString()) } @@ -109,4 +106,5 @@ func Execute() { func init() { RootCmd.SetFlagErrorFunc(flagErrorFunc) + RootCmd.SetVersionTemplate("Databricks CLI v{{.Version}}\n") } diff --git a/cmd/root/version.go b/cmd/root/version.go deleted file mode 100644 index 2acfe26c0d2..00000000000 --- a/cmd/root/version.go +++ /dev/null @@ -1,45 +0,0 @@ -package root - -import ( - "errors" - "strconv" -) - -// errExitFromVersion is returned when the version flag is set. -var errExitFromVersion = errors.New("exit from version flag") - -type versionFlag struct { -} - -func (v *versionFlag) Set(s string) error { - b, err := strconv.ParseBool(s) - if err != nil { - return err - } - if b { - // Return if this flag as soon as this flag gets set. - // If no runnable command is specified, the root command's - // hooks are not executed, and this is the only place to - // detect whether the version flag is set. - return errExitFromVersion - } - return nil -} - -func (v *versionFlag) Type() string { - return "bool" -} - -func (v *versionFlag) String() string { - return "false" -} - -func (v *versionFlag) IsBoolFlag() bool { - return true -} - -func init() { - var f versionFlag - flag := RootCmd.PersistentFlags().VarPF(&f, "version", "v", "print version and exit") - flag.NoOptDefVal = "true" -} diff --git a/cmd/version/version.go b/cmd/version/version.go index 70d2f9b42a9..63fd4512872 100644 --- a/cmd/version/version.go +++ b/cmd/version/version.go @@ -2,6 +2,7 @@ package version import ( "encoding/json" + "fmt" "github.com/databricks/cli/cmd/root" "github.com/databricks/cli/internal/build" @@ -15,13 +16,15 @@ var versionCmd = &cobra.Command{ Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { + info := build.GetInfo() if detail { enc := json.NewEncoder(cmd.OutOrStdout()) enc.SetIndent("", " ") - return enc.Encode(build.GetInfo()) + return enc.Encode(info) } - return build.PrintVersion(cmd.OutOrStdout()) + _, err := fmt.Fprintf(cmd.OutOrStdout(), "Databricks CLI v%s\n", info.Version) + return err }, } diff --git a/internal/build/print.go b/internal/build/print.go deleted file mode 100644 index 812b86791e3..00000000000 --- a/internal/build/print.go +++ /dev/null @@ -1,11 +0,0 @@ -package build - -import ( - "fmt" - "io" -) - -func PrintVersion(w io.Writer) error { - _, err := fmt.Fprintf(w, "Databricks CLI v%s\n", GetInfo().Version) - return err -}