From 0bf3e7500cab474364798b50f0496c27e0eab371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Thu, 31 Oct 2019 11:44:45 +0100 Subject: [PATCH 1/5] Add `--version` flag support --- Makefile | 6 ++++-- command/root.go | 14 ++++++++------ version/version.go | 11 ----------- 3 files changed, 12 insertions(+), 19 deletions(-) delete mode 100644 version/version.go diff --git a/Makefile b/Makefile index 988c9cad5..63e424b84 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,12 @@ BUILD_FILES = $(shell go list -f '{{range .GoFiles}}{{$$.Dir}}/{{.}}\ {{end}}' ./...) -# export GOFLAGS := -mod=vendor $GOFLAGS +GH_VERSION = $(shell go describe --tags 2>/dev/null || git rev-parse --short HEAD) +LDFLAGS := -X github.com/github/gh-cli/command.Version=$(GH_VERSION) $(LDFLAGS) +LDFLAGS := -X github.com/github/gh-cli/command.BuildDate=$(shell date +%Y-%m-%d) $(LDFLAGS) bin/gh: $(BUILD_FILES) - go build -o "$@" + @go build -ldflags "$(LDFLAGS)" -o "$@" test: go test ./... diff --git a/command/root.go b/command/root.go index c0b676c86..ed120b56b 100644 --- a/command/root.go +++ b/command/root.go @@ -6,12 +6,18 @@ import ( "github.com/github/gh-cli/api" "github.com/github/gh-cli/context" - "github.com/github/gh-cli/version" "github.com/spf13/cobra" ) +// Version is dynamically set at build time +var Version = "DEV" + +// BuildDate is dynamically set at build time +var BuildDate = "YYYY-MM-DD" + func init() { + RootCmd.Version = fmt.Sprintf("%s (%s)", Version, BuildDate) RootCmd.PersistentFlags().StringP("repo", "R", "", "current GitHub repository") RootCmd.PersistentFlags().StringP("current-branch", "B", "", "current git branch") // TODO: @@ -23,10 +29,6 @@ var RootCmd = &cobra.Command{ Use: "gh", Short: "GitHub CLI", Long: `Do things with GitHub from your terminal`, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("root") - }, } // overriden in tests @@ -57,7 +59,7 @@ var apiClientForContext = func(ctx context.Context) (*api.Client, error) { } opts := []api.ClientOption{ api.AddHeader("Authorization", fmt.Sprintf("token %s", token)), - api.AddHeader("User-Agent", fmt.Sprintf("GitHub CLI %s", version.Version)), + api.AddHeader("User-Agent", fmt.Sprintf("GitHub CLI %s", Version)), } if verbose := os.Getenv("DEBUG"); verbose != "" { opts = append(opts, api.VerboseLog(os.Stderr)) diff --git a/version/version.go b/version/version.go deleted file mode 100644 index 7314c51e6..000000000 --- a/version/version.go +++ /dev/null @@ -1,11 +0,0 @@ -package version - -import ( - "fmt" -) - -var Version = "0.0.0" - -func FullVersion() (string, error) { - return fmt.Sprintf("gh version %s", Version), nil -} From a6e61a3a8d49eaa720906f7023fef7d11e56af6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Thu, 31 Oct 2019 13:21:22 +0100 Subject: [PATCH 2/5] Silence Cobra usage on errors When an error occurs anywhere in a command, Cobra used to print the error itself and command usage help. We already print error in `main()`, and we don't want to use command usage string on anything other than flag-parsing errors. This also fixes the double output of each error. --- command/root.go | 16 ++++++++++++---- main.go | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/command/root.go b/command/root.go index c0b676c86..51c602511 100644 --- a/command/root.go +++ b/command/root.go @@ -1,6 +1,7 @@ package command import ( + "errors" "fmt" "os" @@ -16,17 +17,24 @@ func init() { RootCmd.PersistentFlags().StringP("current-branch", "B", "", "current git branch") // TODO: // RootCmd.PersistentFlags().BoolP("verbose", "V", false, "enable verbose output") + + RootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error { + cmd.Println(err) + cmd.Println(cmd.UsageString()) + return SilentErr + }) } +var SilentErr = errors.New("SilentErr") + // RootCmd is the entry point of command-line execution var RootCmd = &cobra.Command{ Use: "gh", Short: "GitHub CLI", Long: `Do things with GitHub from your terminal`, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("root") - }, + + SilenceErrors: true, + SilenceUsage: true, } // overriden in tests diff --git a/main.go b/main.go index f954ae933..2ef3e1e2c 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,9 @@ import ( func main() { if err := command.RootCmd.Execute(); err != nil { - fmt.Println(err) + if err != command.SilentErr { + fmt.Println(err) + } os.Exit(1) } } From faa96be9eadd3fe5d9f4b23637322946ddbb2fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Thu, 31 Oct 2019 15:46:38 +0100 Subject: [PATCH 3/5] Ensure that errors are printed to stderr --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 2ef3e1e2c..ae20c309d 100644 --- a/main.go +++ b/main.go @@ -10,7 +10,7 @@ import ( func main() { if err := command.RootCmd.Execute(); err != nil { if err != command.SilentErr { - fmt.Println(err) + fmt.Fprintln(os.Stderr, err) } os.Exit(1) } From e87775845d3e19548448acc6f26692ffce11998c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Thu, 31 Oct 2019 22:44:43 +0100 Subject: [PATCH 4/5] Also print cmd usage string on "unknown command" --- command/root.go | 10 +++++----- main.go | 9 ++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/command/root.go b/command/root.go index 51c602511..a309960e3 100644 --- a/command/root.go +++ b/command/root.go @@ -1,7 +1,6 @@ package command import ( - "errors" "fmt" "os" @@ -19,13 +18,14 @@ func init() { // RootCmd.PersistentFlags().BoolP("verbose", "V", false, "enable verbose output") RootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error { - cmd.Println(err) - cmd.Println(cmd.UsageString()) - return SilentErr + return FlagError{err} }) } -var SilentErr = errors.New("SilentErr") +// FlagError is the kind of error raised in flag processing +type FlagError struct { + error +} // RootCmd is the entry point of command-line execution var RootCmd = &cobra.Command{ diff --git a/main.go b/main.go index ae20c309d..e7f94a5d0 100644 --- a/main.go +++ b/main.go @@ -3,14 +3,17 @@ package main import ( "fmt" "os" + "strings" "github.com/github/gh-cli/command" ) func main() { - if err := command.RootCmd.Execute(); err != nil { - if err != command.SilentErr { - fmt.Fprintln(os.Stderr, err) + if cmd, err := command.RootCmd.ExecuteC(); err != nil { + fmt.Fprintln(os.Stderr, err) + _, isFlagError := err.(command.FlagError) + if isFlagError || strings.HasPrefix(err.Error(), "unknown command ") { + fmt.Fprintln(os.Stderr, cmd.UsageString()) } os.Exit(1) } From c3d70bd8cd49eff2cd8e2dcfd276048d4a8fb3fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Thu, 31 Oct 2019 23:10:42 +0100 Subject: [PATCH 5/5] Clarify where Version and BuildDate are set --- command/root.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/command/root.go b/command/root.go index ed120b56b..3dff3bce6 100644 --- a/command/root.go +++ b/command/root.go @@ -10,10 +10,10 @@ import ( "github.com/spf13/cobra" ) -// Version is dynamically set at build time +// Version is dynamically set at build time in the Makefile var Version = "DEV" -// BuildDate is dynamically set at build time +// BuildDate is dynamically set at build time in the Makefile var BuildDate = "YYYY-MM-DD" func init() {