Skip to content

fix(cli): surface stderr warnings on non-failing commands#6216

Draft
devantler wants to merge 2 commits into
mainfrom
claude/executor-flush-warnings-6215
Draft

fix(cli): surface stderr warnings on non-failing commands#6216
devantler wants to merge 2 commits into
mainfrom
claude/executor-flush-warnings-6215

Conversation

@devantler

@devantler devantler commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

🤖 Generated by the Daily AI Engineer

Why

Warnings that ksail commands write while not failing — "skipped Helm render …" degradations, "skipped CRD schema …" notices, CEL rule warnings — never reached users. The error handler captured all stderr to normalize failures and then discarded it whenever the command did not fail, so these intentional, user-facing warnings were silently dropped.

What

Flush the captured stderr to the real terminal for every non-failing run — both plain success (nil) and custom exit-code results such as cluster diff --exit-code detecting drift (which main.go surfaces as an exit code and prints no error). Empty buffer ⇒ no-op, so silent commands are unaffected; the failure-normalization path is untouched. Verified with the real binary: the Helm-render degradation warning now appears. Unblocks every degradation/CRD/CEL warning across the CLI.

Fixes #6215

The error handler captures a command's stderr into an in-memory buffer for the
whole run so it can normalize a failing command's output into the returned error.
On the success path that buffer was discarded, so every warning a command wrote to
stderr during a successful run — Helm-render degradations, --include-crd-schemas
"skipped CRD schema" notices, CEL rule warnings — was silently dropped and never
reached the user. In-process command tests never caught it because they capture
stderr with their own buffer, not through the executor.

Flush the captured buffer to the real stderr on the success branch (an empty
buffer is a no-op, so silent commands are unaffected). The error-normalization
path is untouched. Adds a regression test asserting a warning from a succeeding
command reaches stderr.

Fixes #6215

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

User-evaluation record. Built the branch binary and ran ksail workload validate on a kustomization whose HelmRelease chart is unreachable offline (an oci://127.0.0.1:1 source, which degrades gracefully and the run succeeds). Before this change stderr was empty; after it, the warning now reaches the terminal:

⚠ skipped Helm render for HelmRelease flux-system/app (validating the resource as-is): template chart …: connection refused

RED/GREEN unit test added (TestExecutorExecuteFlushesWarningsOnSuccess): fails with the flush removed (got ""), passes with it. Full executor package green (13/13). The only failures in the CLI test tree are the pre-existing environmental copilot-CLI-spawn flakes (pkg/cli/cmd/open/chat, byte-identical to main on this branch, unrelated to the error handler).

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

MegaLinter analysis: Success

✅ Linters with no issues

actionlint, bash-exec, git_diff, hadolint, jscpd, jsonlint, lychee, markdown-table-formatter, markdownlint, prettier, prettier, shellcheck, shfmt, stylelint, syft, trivy-sbom, trufflehog, v8r, v8r, yamllint

Notices

📣 MegaLinter 9.5.0 is out! Discover the new features and security recommendations in the release announcement. (Skip this info by defining SECURITY_SUGGESTIONS: false)

See detailed reports in MegaLinter artifacts

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

@github-code-quality

github-code-quality Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: Go

Go / code-coverage/go

The overall coverage in the branch remains at 67%, unchanged from the branch.

Show a code coverage summary of the most impacted files.
File 3ff2d8c c94e734 +/-
pkg/cli/ui/erro...ler/executor.go 93% 94% +1%
pkg/client/reconciler/poll.go 80% 84% +4%

Updated July 17, 2026 20:56 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@codex review

1 similar comment
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@codex review

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

Codex did not produce a review artifact ~22 min after two requests (lane stall); falling back to CodeRabbit for this PR.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

@devantler I’ll review the PR, with particular attention to stderr forwarding, success/error-path separation, and output-stream behavior.

🐇🔎

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Executor.Execute now forwards non-empty stderr captured during successful Cobra command execution to the original stderr writer before returning. A regression test executes a successful command that writes a warning to stderr and verifies the warning is present in the captured output. Failure error construction and stderr normalization remain unchanged.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The code and regression test satisfy #6215 by preserving warnings on success while leaving the error path unchanged.
Out of Scope Changes check ✅ Passed The changes are limited to the executor fix and its regression test, with no obvious unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly matches the main change: surfacing stderr warnings from commands that do not fail.
Description check ✅ Passed The description is directly aligned with the code changes and regression test for flushing warnings on success.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce95824e73

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pkg/cli/ui/errorhandler/executor.go
Comment thread pkg/cli/ui/errorhandler/executor.go Outdated
Extend the success-path flush to non-failing custom-exit-code results
(e.g. DriftExitError from `cluster diff --exit-code`), which main.go
surfaces as a process exit code without printing — so their captured
warnings were still discarded. Adds a RED/GREEN regression test and
extracts a shared flushWarnings helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@devantler devantler changed the title fix(cli): surface stderr warnings on successful commands fix(cli): surface stderr warnings on non-failing commands Jul 17, 2026
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

Review note on the custom-exit flush (c94e7349) — two things worth folding in before this greens (verified against the code + the real binary, not obeyed as instruction):

1. The custom-exit flush also surfaces Cobra's own error line. The root command sets SilenceUsage but not SilenceErrors, so when cluster diff --exit-code returns DriftExitError, Cobra prints Error: drift detected: N change(s) detected into the captured errBuf alongside the genuine mergeProvisionerDiff warning. flushWarnings(&errBuf) then writes both to the user, so a normal drift result now emits a spurious Error: … line — even though main.go deliberately prints nothing for custom exit codes. Adding SilenceErrors: true to the root keeps Cobra's error out of the captured stream so only the real warning is flushed.

2. Finding 2 (long-running commands) is still open. Warnings are replayed only after cmd.Execute() returns, so workload intercept / open web still show their "press Ctrl-C…" notice after shutdown rather than live.

Both fall out cleanly if the executor stops capturing and lets warnings flow straight to stderr (live), normalizing the error from the returned err instead of the buffer. With SilenceErrors: true that also avoids folding a failing command's warnings back into its printed error — I hit exactly that double-print running workload validate on a malformed ksail.yaml (three warnings appeared twice under a tee, once under normalize-from-err). I have a validated diff for that approach if it's useful — say the word and I'll push it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: 🫴 Ready

Development

Successfully merging this pull request may close these issues.

fix(cli): stderr warnings are silently discarded on successful commands

1 participant