refactor(cli): migrate commands to RunE with a single exit funnel - #490
refactor(cli): migrate commands to RunE with a single exit funnel#490Caesarsage wants to merge 5 commits into
Conversation
Signed-off-by: caesarsage <destinyerhabor6@gmail.com>
Signed-off-by: caesarsage <destinyerhabor6@gmail.com>
Signed-off-by: caesarsage <destinyerhabor6@gmail.com>
Signed-off-by: caesarsage <destinyerhabor6@gmail.com>
|
HOLD till PR #489 is review and merged |
|
Stacked PR of #489 |
Vaishnav88sk
left a comment
There was a problem hiding this comment.
Please resolve the conflicts.
Also add copyright block for pkg/errors/error_test.go
| watcher, err := fsnotify.NewWatcher() | ||
| if err != nil { | ||
| fmt.Printf("Failed to create file watcher: %s\n", err) | ||
| return false | ||
| return fmt.Errorf("failed to create file watcher: %w", err) | ||
| } | ||
| defer watcher.Close() | ||
|
|
||
| // Watch the directory, not the file: editors replace files on save | ||
| // (rename + create), which silently drops a watch set on the file itself. | ||
| artifactPath, err := filepath.Abs(opts.artifact) | ||
| if err != nil { | ||
| fmt.Printf("Failed to resolve artifact path: %s\n", err) | ||
| return false | ||
| return fmt.Errorf("failed to resolve artifact path: %w", err) | ||
| } | ||
| if err := watcher.Add(filepath.Dir(artifactPath)); err != nil { | ||
| fmt.Printf("Failed to watch %s: %s\n", filepath.Dir(artifactPath), err) | ||
| return false | ||
| return fmt.Errorf("failed to watch %s: %w", filepath.Dir(artifactPath), err) | ||
| } |
There was a problem hiding this comment.
These new error paths are still unclassified fmt.Errorf(...) returns.
Since this PR is introducing a kind-based exit funnel, these should be wrapped consistently as well (likely KindEnvironment for watcher/runtime setup problems, or KindUsage where appropriate). Otherwise these cases still collapse to the generic 20 path.
| if len(args) == 0 { | ||
| fmt.Println("import command require <specificationFile1[:primary],specificationFile2[:primary]> args") | ||
| cmd.HelpFunc()(cmd, args) | ||
| os.Exit(1) | ||
| return errors.Wrapf(errors.KindUsage, "import requires a <specificationFile1[:primary],specificationFile2[:primary]> argument") | ||
| } |
There was a problem hiding this comment.
One behavioral change to call out here: this no longer prints help/usage, whereas the previous implementation did.
I’m fine with the RunE refactor, but if the goal is “no impact on the binary”, we should either preserve the old help/usage behavior for bad invocations or explicitly document/test that this user-facing behavior is changing.
There was a problem hiding this comment.
Thanks for catching this. I will make a fix for this by creating am helper usage function
| if len(args) != 1 { | ||
| cmd.HelpFunc()(cmd, args) | ||
| os.Exit(1) | ||
| return errors.Wrapf(errors.KindUsage, "login requires exactly one SERVER argument") | ||
| } |
There was a problem hiding this comment.
Same comment here: this changes the UX on invalid invocation from “show help + exit” to “print one error line + exit”.
That may be acceptable, but it is user-visible behavior and contradicts the current PR description of “no impact on the binary”. Please either preserve the old behavior or call out the change explicitly.
| @@ -197,6 +191,7 @@ func NewImportDirCommand(globalClientOpts *connectors.ClientOptions) *cobra.Comm | |||
| } | |||
|
|
|||
| fmt.Printf("\nImport completed: %d/%d files imported successfully\n", result.SuccessCount, result.TotalFiles) | |||
There was a problem hiding this comment.
Please double-check this path against the intended import-dir semantics.
As written, partial failures still return nil, so the single exit funnel will still exit 0 even when some files failed. If we want import-dir to be CI-friendly, this likely needs to return a non-zero error when FailedCount > 0.
| u, err := url.Parse(realmURL) | ||
| if err != nil { | ||
| panic(err) | ||
| return nil, errors.Wrap(errors.KindUsage, fmt.Errorf("invalid Keycloak URL %q: %w", realmURL, err)) | ||
| } |
There was a problem hiding this comment.
I flagged in #489 and you said was fixed here. Please point to the current line number and confirm it now returns errors.Wrap(errors.KindUsage or KindAPI, err) instead of panic(err).
There was a problem hiding this comment.
this is returning the errors helper as i mentioned on #489. I am not sure I understand the comment here
| u, err := url.Parse(apiURL) | ||
| if err != nil { | ||
| panic(err) | ||
| return nil, errors.Wrap(errors.KindUsage, fmt.Errorf("invalid server URL %q: %w", apiURL, err)) | ||
| } | ||
| mc.APIURL = u | ||
|
|
There was a problem hiding this comment.
Same as keycloak_client.go, confirm the url.Parse panic here is replaced with a returned classified error, and share the line number.
There was a problem hiding this comment.
this is returning the errors helper as i mentioned on #489 and all are documented on the documentation folder. I am not sure I understand the comment here
Signed-off-by: caesarsage <destinyerhabor6@gmail.com>
depend on #489
Part of the Microcks CLI v2 work (#255). Stacked on PR #489.
Run+ scatteredos.Exit/log.FataltoRunEreturning errors.cmd.Handle, called only bymain— prints to stderr and maps Failure Kind → exit code (cmd/exit.go). Nothing else exits.ErrTestFailedsentinel → exit1with no spurious error line (mirrorskubectl diff).No impact on the
microcksbinary: commands, flags, args, and success output are unchanged. Only code importing these packages is affected.Exit codes (new, user-visible)
0= success / non-zero = failure still holds, and1still means "contract test failed". Operational failures now carry distinct codes so CI can branch on why:These codes were previously undocumented and inconsistent (
1/2/20interchangeably), so there is no prior contract to break. Documented inREADME.md+documentation/error-handling.md.