From 74861291c920ec422b979cb483e88caddaf09b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20Kivim=C3=A4ki?= Date: Thu, 29 Feb 2024 09:47:01 +0200 Subject: [PATCH] fix: honor user abort when upgrading recipes with check command --- internal/cli/check.go | 4 +++- internal/cli/create.go | 3 ++- internal/cli/eject.go | 3 ++- internal/cli/execute.go | 10 +++------- internal/cli/pull.go | 3 ++- internal/cli/push.go | 3 ++- internal/cli/root.go | 19 +++++++++++++++++++ internal/cli/test.go | 4 ++-- internal/cli/upgrade.go | 23 +++-------------------- internal/cli/validate.go | 3 ++- internal/cli/why.go | 3 ++- 11 files changed, 42 insertions(+), 36 deletions(-) diff --git a/internal/cli/check.go b/internal/cli/check.go index c8c6beb1..04881d5d 100644 --- a/internal/cli/check.go +++ b/internal/cli/check.go @@ -40,7 +40,8 @@ func NewCheckCmd() *cobra.Command { return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runCheck(cmd, opts) + err := runCheck(cmd, opts) + return errorHandler(cmd, err) }, PostRun: func(cmd *cobra.Command, args []string) { cmd.Root().SetContext(cmd.Context()) @@ -138,6 +139,7 @@ func runCheck(cmd *cobra.Command, opts checkOptions) error { for sauce, version := range upgrades { cmd.Printf(" %s upgrade %s:%s\n", os.Args[0], sauce.CheckFrom, version) } + cmd.Println("\nor rerun the command with '--upgrade' flag to upgrade all recipes to the latest version.") } var exitCode int diff --git a/internal/cli/create.go b/internal/cli/create.go index 9fb1dba3..76a69805 100644 --- a/internal/cli/create.go +++ b/internal/cli/create.go @@ -51,7 +51,8 @@ my-recipe return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runCreate(cmd, opts) + err := runCreate(cmd, opts) + return errorHandler(cmd, err) }, } diff --git a/internal/cli/eject.go b/internal/cli/eject.go index 3fa88663..0d1d5562 100644 --- a/internal/cli/eject.go +++ b/internal/cli/eject.go @@ -26,7 +26,8 @@ func NewEjectCmd() *cobra.Command { return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runEject(cmd, opts) + err := runEject(cmd, opts) + return errorHandler(cmd, err) }, Example: `jalapeno eject`, } diff --git a/internal/cli/execute.go b/internal/cli/execute.go index d8a31cde..05829d8a 100644 --- a/internal/cli/execute.go +++ b/internal/cli/execute.go @@ -14,7 +14,6 @@ import ( "github.com/futurice/jalapeno/pkg/recipe" "github.com/futurice/jalapeno/pkg/recipeutil" "github.com/futurice/jalapeno/pkg/ui/survey" - uiutil "github.com/futurice/jalapeno/pkg/ui/util" "github.com/gofrs/uuid" "github.com/spf13/cobra" "golang.org/x/mod/semver" @@ -43,7 +42,8 @@ func NewExecuteCmd() *cobra.Command { return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runExecute(cmd, opts) + err := runExecute(cmd, opts) + return errorHandler(cmd, err) }, Example: `# Execute local recipe jalapeno execute path/to/recipe @@ -185,11 +185,7 @@ func runExecute(cmd *cobra.Command, opts executeOptions) error { promptedValues, err := survey.PromptUserForValues(cmd.InOrStdin(), cmd.OutOrStdout(), varsWithoutValues, values) if err != nil { - if errors.Is(err, uiutil.ErrUserAborted) { - return nil - } else { - return fmt.Errorf("error when prompting for values: %s", err) - } + return fmt.Errorf("error when prompting for values: %s", err) } values = recipeutil.MergeValues(values, promptedValues) } else { diff --git a/internal/cli/pull.go b/internal/cli/pull.go index 0ac4da0d..7280382b 100644 --- a/internal/cli/pull.go +++ b/internal/cli/pull.go @@ -30,7 +30,8 @@ func NewPullCmd() *cobra.Command { return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runPull(cmd, opts) + err := runPull(cmd, opts) + return errorHandler(cmd, err) }, Example: `# Pull recipe from OCI repository jalapeno pull ghcr.io/user/recipe:latest diff --git a/internal/cli/push.go b/internal/cli/push.go index 8af6d606..bab1616a 100644 --- a/internal/cli/push.go +++ b/internal/cli/push.go @@ -30,7 +30,8 @@ func NewPushCmd() *cobra.Command { return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runPush(cmd, opts) + err := runPush(cmd, opts) + return errorHandler(cmd, err) }, Example: `# Push recipe to OCI repository jalapeno push path/to/recipe ghcr.io/user/recipe diff --git a/internal/cli/root.go b/internal/cli/root.go index e18bc13d..d38f4b11 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -2,10 +2,12 @@ package cli import ( "context" + "errors" "fmt" "time" "github.com/carlmjohnson/versioninfo" + uiutil "github.com/futurice/jalapeno/pkg/ui/util" "github.com/spf13/cobra" ) @@ -65,3 +67,20 @@ func NewRootCmd() *cobra.Command { return cmd } + +func errorHandler(cmd *cobra.Command, err error) error { + if err == nil { + return nil + } + + // Print empty line before error message + cmd.Println() + + // If the error is a user abort, don't print the error message + if errors.Is(err, uiutil.ErrUserAborted) { + cmd.Println("User aborted") + return nil + } + + return err +} diff --git a/internal/cli/test.go b/internal/cli/test.go index e2e786e7..12066f2b 100644 --- a/internal/cli/test.go +++ b/internal/cli/test.go @@ -31,7 +31,8 @@ func NewTestCmd() *cobra.Command { return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runTest(cmd, opts) + err := runTest(cmd, opts) + return errorHandler(cmd, err) }, Example: `# Run recipe tests jalapeno test path/to/recipe @@ -169,7 +170,6 @@ func runTest(cmd *cobra.Command, opts testOptions) error { } if len(formattedErrs) > 0 { - cmd.Println() return fmt.Errorf("recipe tests failed: %w", errors.Join(formattedErrs...)) } diff --git a/internal/cli/upgrade.go b/internal/cli/upgrade.go index 6d46b983..1ab7a9f0 100644 --- a/internal/cli/upgrade.go +++ b/internal/cli/upgrade.go @@ -17,7 +17,6 @@ import ( "github.com/futurice/jalapeno/pkg/recipeutil" "github.com/futurice/jalapeno/pkg/ui/conflict" "github.com/futurice/jalapeno/pkg/ui/survey" - uiutil "github.com/futurice/jalapeno/pkg/ui/util" "github.com/gofrs/uuid" "github.com/spf13/cobra" "golang.org/x/mod/semver" @@ -46,7 +45,8 @@ func NewUpgradeCmd() *cobra.Command { return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runUpgrade(cmd, opts) + err := runUpgrade(cmd, opts) + return errorHandler(cmd, err) }, Example: `# Upgrade recipe with local recipe jalapeno upgrade path/to/recipe @@ -200,7 +200,6 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error { opts.Values.ParseEnvironmentVariables, ) if err != nil { - cmd.Println() return fmt.Errorf("failed to parse provided values: %w", err) } @@ -226,7 +225,6 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error { if v.Default != "" { defaultValue, err := v.ParseDefaultValue() if err != nil { - cmd.Println() return fmt.Errorf("failed to parse default value for variable '%s': %w", v.Name, err) } values[v.Name] = defaultValue @@ -237,7 +235,6 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error { // If there are still variables without values, return error if len(varsWithoutDefaultValues) > 0 { - cmd.Println() return recipeutil.NewNoInputError(varsWithoutDefaultValues) } } @@ -251,10 +248,6 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error { ) if err != nil { - if errors.Is(err, uiutil.ErrUserAborted) { - return nil - } - return fmt.Errorf("error when prompting for values: %w", err) } @@ -279,7 +272,6 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error { if data, err := os.ReadFile(filepath.Join(opts.Dir, recipe.IgnoreFileName)); err == nil { ignorePatterns = append(ignorePatterns, strings.Split(string(data), "\n")...) } else if !errors.Is(err, fs.ErrNotExist) { - cmd.Println() // something else happened than trying to read an ignore file that does not exist return fmt.Errorf("failed to read ignore file: %w\n\n%s", err, cliutil.MakeRetryMessage(os.Args, values)) } @@ -292,7 +284,6 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error { skip := false for _, pattern := range ignorePatterns { if matched, err := filepath.Match(pattern, path); err != nil { - cmd.Println() return fmt.Errorf("bad ignore pattern '%s': %w\n\n%s", pattern, err, cliutil.MakeRetryMessage(os.Args, values)) } else if matched { // file was marked as ignored for upgrades @@ -348,13 +339,7 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error { ) if err != nil { - if errors.Is(err, uiutil.ErrUserAborted) { - cmd.Printf("User aborted\n\n%s\n", cliutil.MakeRetryMessage(os.Args, values)) - return nil - } - - cmd.Println() - return fmt.Errorf("error when prompting for question: %w\n\n%s", err, cliutil.MakeRetryMessage(os.Args, values)) + return fmt.Errorf("error when solving file conflicts: %w", err) } if bytes.Equal(conflictResult, prevFile.Content) { @@ -378,7 +363,6 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error { keep := false for _, pattern := range ignorePatterns { if matched, err := filepath.Match(pattern, filename); err != nil { - cmd.Println() return fmt.Errorf("bad ignore pattern '%s': %w\n\n%s", pattern, err, cliutil.MakeRetryMessage(os.Args, values)) } else if matched { keep = true @@ -389,7 +373,6 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error { if !keep { err := os.Remove(filepath.Join(opts.Dir, filename)) if err != nil { - cmd.Println() return fmt.Errorf("failed to remove deprecated file '%s': %w", filename, err) } diff --git a/internal/cli/validate.go b/internal/cli/validate.go index 0aa9cb66..51ac0ceb 100644 --- a/internal/cli/validate.go +++ b/internal/cli/validate.go @@ -27,7 +27,8 @@ func NewValidateCmd() *cobra.Command { return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runValidate(cmd, opts) + err := runValidate(cmd, opts) + return errorHandler(cmd, err) }, Args: cobra.ExactArgs(1), Example: `jalapeno validate path/to/recipe`, diff --git a/internal/cli/why.go b/internal/cli/why.go index 9029c454..e970d919 100644 --- a/internal/cli/why.go +++ b/internal/cli/why.go @@ -31,7 +31,8 @@ func NewWhyCmd() *cobra.Command { return option.Parse(&opts) }, RunE: func(cmd *cobra.Command, args []string) error { - return runWhy(cmd, opts) + err := runWhy(cmd, opts) + return errorHandler(cmd, err) }, Example: `jalapeno why path/to/file`, }