Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Make --version flag handling stateless and deduplicate version output
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
  • Loading branch information
Copilot and pelikhan authored Sep 29, 2026
commit b2680c4565bc896e596d8377cdea6dc55ca26f84
19 changes: 14 additions & 5 deletions cmd/gh-aw/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"io"
"os"
"os/signal"
"sort"
Expand All @@ -27,7 +28,11 @@ var (
// Global flags
var verboseFlag bool
var bannerFlag bool
var versionFlag bool

// printVersion writes the CLI name and version string to the given writer.
func printVersion(w io.Writer) {
fmt.Fprintf(w, "%s version %s\n", string(constants.CLIExtensionPrefix), version)
}

// formatListWithOr formats a list of strings with commas and "or" before the last item
// Example: ["a", "b", "c"] -> "a, b, or c"
Expand Down Expand Up @@ -104,8 +109,12 @@ For detailed help on any command, use:
}
},
RunE: func(cmd *cobra.Command, args []string) error {
if versionFlag {
fmt.Fprintf(os.Stdout, "%s version %s\n", string(constants.CLIExtensionPrefix), version)
if versionFlag, _ := cmd.Flags().GetBool("version"); versionFlag {
// Reset the flag's value immediately so repeated in-process
// executions (e.g. tests reusing rootCmd) don't keep printing
// the version after a run that didn't pass --version.
_ = cmd.Flags().Set("version", "false")
printVersion(os.Stdout)
return nil
}
return cmd.Help()
Expand Down Expand Up @@ -391,7 +400,7 @@ var versionCmd = &cobra.Command{
Long: `Print the current version and build information for the gh aw CLI extension.`,
Example: ` ` + string(constants.CLIExtensionPrefix) + ` version # Print the current version`,
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Fprintf(os.Stdout, "%s version %s\n", string(constants.CLIExtensionPrefix), version)
printVersion(os.Stdout)
return nil
},
}
Expand Down Expand Up @@ -700,7 +709,7 @@ func configureRootCommand() {
rootCmd.AddGroup(&cobra.Group{ID: "utilities", Title: "Utilities:"})
rootCmd.PersistentFlags().BoolVarP(&verboseFlag, "verbose", "v", false, "Enable verbose output showing detailed information")
rootCmd.PersistentFlags().BoolVar(&bannerFlag, "banner", false, "Display ASCII logo banner with purple GitHub color theme")
rootCmd.Flags().BoolVar(&versionFlag, "version", false, "Print the current version")
rootCmd.Flags().Bool("version", false, "Print the current version")
rootCmd.SetOut(os.Stderr)
rootCmd.SilenceUsage = true
rootCmd.SilenceErrors = true
Expand Down
57 changes: 57 additions & 0 deletions cmd/gh-aw/version_flag_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//go:build !integration

package main

import (
"bytes"
"io"
"os"
"strings"
"testing"
)

// TestRootVersionFlagIsStateless verifies that executing the root command with
// --version does not leave state behind that causes a later execution without
// --version to keep printing the version instead of help.
func TestRootVersionFlagIsStateless(t *testing.T) {
captureStdout := func(fn func()) string {
originalStdout := os.Stdout
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("failed to create pipe: %v", err)
}
os.Stdout = w
defer func() { os.Stdout = originalStdout }()

fn()

if err := w.Close(); err != nil {
t.Fatalf("failed to close pipe writer: %v", err)
}
var buf bytes.Buffer
if _, err := io.Copy(&buf, r); err != nil {
t.Fatalf("failed to read pipe: %v", err)
}
return buf.String()
}

rootCmd.SetArgs([]string{"--version"})
firstOutput := captureStdout(func() {
if err := rootCmd.Execute(); err != nil {
t.Fatalf("first execute (--version) returned error: %v", err)
}
})
if !strings.Contains(firstOutput, "version") {
t.Errorf("expected first execution to print version, got: %q", firstOutput)
}

rootCmd.SetArgs([]string{})
secondOutput := captureStdout(func() {
if err := rootCmd.Execute(); err != nil {
t.Fatalf("second execute (no args) returned error: %v", err)
}
})
if strings.Contains(secondOutput, "version") {
t.Errorf("expected second execution to not print version (should show help), got: %q", secondOutput)
}
}
Loading