Repository navigation
Write version output to stdout - #64336
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
gh aw --version output to use stdoutThere was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The focused implementation and regression tests correctly address the reported stream behavior.
Review effort: Balanced
Findings: None
What changed in this PR
Routes both version invocation forms to stdout while preserving stderr for help and diagnostics.
Changes:
- Adds explicit root
--versionhandling. - Writes version command output to stdout.
- Verifies stdout output and empty stderr for both forms.
| File | Description |
|---|---|
cmd/gh-aw/main.go |
Routes version output to stdout. |
cmd/gh-aw/version_test.go |
Adds regression coverage for output streams. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
|
✅ Test Quality Sentinel completed test quality analysis. Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff
|
|
✅ Ponytail Reviewer completed successfully! Lean already. Ship.
|
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅
|
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft. No ADR enforcement needed: PR does not have the 'implementation' label and has ≤100 new lines of code in business logic directories.
|
|
✅ PR Code Quality Reviewer completed the code quality review.
|
Comment MemoryNote This comment is managed by comment memory.It stores persistent context for this thread in the code block at the top of this comment.
|
There was a problem hiding this comment.
Verdict
I found one real regression risk in the custom --version plumbing, but not enough to block the patch.
Theme
The new root-level version handling stores parsed flag state in a package global, so repeated `Execute()` calls in the same process can stay stuck in version mode. That is mostly a testability and maintainability problem here because the CLI is normally one-shot, but the global command tree in this package is reused across tests.🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 40 AIC · ⌖ 7.03 AIC · ⊞ 20.2K
Comment /review to run again
| } | ||
| }, | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| if versionFlag { |
There was a problem hiding this comment.
This package-level versionFlag makes rootCmd.Execute() stateful, so once a test or in-process caller parses --version, a later bare execute can keep printing the version instead of help.
💡 Why this is risky
Because the flag is bound to a global bool, Cobra mutates shared state during parsing and nothing resets it between executes. This package already reuses the global `rootCmd` across tests, so adding any non-integration test for `--version` will couple later tests to its execution order. Please keep the flag handling stateless — for example, inspect `cmd.Flags().GetBool("version")` inside the execution path or reset the bound variable before each execute — and add a unit test that calls `Execute()` twice to prove the second run still shows help.There was a problem hiding this comment.
Fixed in b2680c4: the root command now reads cmd.Flags().GetBool("version") per-execution instead of a package-level bool, and resets the flag's value back to false immediately after handling it so a later Execute() without --version falls through to help. Added TestRootVersionFlagIsStateless, which calls rootCmd.Execute() twice (first with --version, then with no args) to prove this.
There was a problem hiding this comment.
Impeccable Skills Review — no blocking issues
Applied harden (bug-fix regression) since this is a targeted stream-routing fix.
- The fix correctly moves both
gh aw versionandgh aw --versionoutput to stdout while keeping help/usage on stderr — verified by building the binary and testing all four invocation shapes (version,--version, no-args,-h). -v/--verbose(persistent) does not collide with the new root-only--versionbool flag.- Regression test in
version_test.gonow asserts empty stderr for both forms — good coverage of the original bug (#64311).
No actionable issues found; approving.
🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet50 · 24.6 AIC · ⌖ 13.8 AIC · ⊞ 8.1K
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnosing-bugs and /tdd — approving with one minor style suggestion.
📋 Key Themes & Highlights
Key Themes
- Root cause fixed correctly: The regression (issue #64311) was caused by Cobra's built-in
--versionflag writing viagetVersionTemplateFunc, andversionCmdwriting toos.Stderrdirectly. Both paths are now fixed by removingrootCmd.Version/InitDefaultVersionFlagand adding an explicit--versionflag routed toos.Stdout, matchingversionCmd's stdout fix. - Regression test coverage is solid:
version_test.gonow exercises bothversionand--versioninvocations, capturesstderrseparately viaexec.Command, and asserts it's empty — directly guarding against the reported bug reappearing. - Manually verified: built the binary and confirmed
gh-aw --version,gh-aw version, and-v/--verboseall behave as expected with clean stdout/stderr separation;go vetand the integration test pass.
Minor Suggestion
- Small duplication between the
--versionprintf inrootCmd.RunEand the identical line inversionCmd.RunE— see inline comment for a small helper-function suggestion to keep the format as a single source of truth.
Positive Highlights
- ✅ Correctly identifies and removes the underlying Cobra-provided version flag rather than papering over the symptom
- ✅ Test explicitly asserts empty stderr, directly encoding the bug's regression condition
- ✅ No behavior change to help output or other flags (verified
-v/--verbosestill works)
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 63.5 AIC · ⌖ 14.4 AIC · ⊞ 10K
Comment /matt to run again
| Example: ` ` + string(constants.CLIExtensionPrefix) + ` version # Print the current version`, | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| fmt.Fprintf(os.Stderr, "%s version %s\n", string(constants.CLIExtensionPrefix), version) | ||
| fmt.Fprintf(os.Stdout, "%s version %s\n", string(constants.CLIExtensionPrefix), version) |
There was a problem hiding this comment.
[/codebase-design] Minor duplication: the %s version %s\n output line is now duplicated between rootCmd.RunE (line 108) and versionCmd.RunE (line 394).
💡 Suggested consolidation
Extract a small helper, e.g. printVersion(w io.Writer), and call it from both places to keep the format string as a single source of truth:
func printVersion(w io.Writer) {
fmt.Fprintf(w, "%s version %s\n", string(constants.CLIExtensionPrefix), version)
}Then in both RunE functions: printVersion(os.Stdout); return nil. This avoids future drift if the format ever changes (e.g. adding build metadata) and only one place needs updating.
@copilot please address this.
There was a problem hiding this comment.
Done in b2680c4: extracted printVersion(w io.Writer) and both rootCmd.RunE and versionCmd.RunE now call it instead of duplicating the format string.
|
@copilot run pr-finisher skill |
|
@copilot please address the remaining review note about root-level --version statefulness, refresh the branch if needed, and run the pr-finisher skill before handing this back for maintainer review.
|
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Already addressed in b2680c4: root |
|
🎉 This pull request is included in a new release. Release: |
gh aw --versionwrote its result to stderr, causing pipelines and command substitutions to receive empty output.Version output
gh aw --versionandgh aw versionto stdout.Regression coverage
version="$(gh aw --version)"gh aw --versionprints to stderr instead of stdout #64311