diff --git a/cmd/gh-aw/main.go b/cmd/gh-aw/main.go index 170bfb98343..6520d530323 100644 --- a/cmd/gh-aw/main.go +++ b/cmd/gh-aw/main.go @@ -662,11 +662,11 @@ Use "` + string(constants.CLIExtensionPrefix) + ` help all" to show help for all // Add flags to new command newCmd.Flags().BoolP("force", "f", false, "Overwrite existing files without confirmation") newCmd.Flags().BoolP("interactive", "i", false, "Launch interactive workflow creation wizard") - newCmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)") + newCmd.Flags().StringP("engine", "e", "", "Override AI engine (copilot, claude, codex, gemini, crush)") cli.RegisterEngineFlagCompletion(newCmd) // Add AI flag to compile and add commands - compileCmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)") + compileCmd.Flags().StringP("engine", "e", "", "Override AI engine (copilot, claude, codex, gemini, crush)") compileCmd.Flags().String("action-mode", "", "Action script inlining mode (inline, dev, release). Auto-detected if not specified") compileCmd.Flags().String("action-tag", "", "Override action SHA or tag for actions/setup (overrides action-mode to release). Accepts full SHA or tag name") compileCmd.Flags().String("actions-repo", "", "Override the external actions repository used in action mode (default: github/gh-aw-actions)") @@ -727,7 +727,7 @@ Use "` + string(constants.CLIExtensionPrefix) + ` help all" to show help for all // Add flags to run command runCmd.Flags().Int("repeat", 0, "Number of additional times to run after the initial execution (e.g., --repeat 3 runs 4 times total)") runCmd.Flags().Bool("enable-if-needed", false, "Enable the workflow before running if needed, and restore state afterward") - runCmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)") + runCmd.Flags().StringP("engine", "e", "", "Override AI engine (copilot, claude, codex, gemini, crush)") runCmd.Flags().StringP("repo", "r", "", "Target repository ([HOST/]owner/repo format). Defaults to current repository") runCmd.Flags().String("ref", "", "Branch or tag name to run the workflow on (default: current branch)") runCmd.Flags().Bool("auto-merge-prs", false, "Auto-merge any pull requests created during the workflow execution") diff --git a/pkg/cli/add_wizard_command.go b/pkg/cli/add_wizard_command.go index c172dff0414..5b2674d2105 100644 --- a/pkg/cli/add_wizard_command.go +++ b/pkg/cli/add_wizard_command.go @@ -20,7 +20,7 @@ func NewAddWizardCommand(validateEngine func(string) error) *cobra.Command { Long: `Interactively add one or more agentic workflows with guided setup. This command walks you through: - - Selecting an AI engine (Copilot, Claude, or Codex) + - Selecting an AI engine (Copilot, Claude, Codex, Gemini, or Crush) - Configuring API keys and secrets - Creating a pull request with the workflow - Optionally running the workflow immediately diff --git a/pkg/cli/add_wizard_command_test.go b/pkg/cli/add_wizard_command_test.go new file mode 100644 index 00000000000..f3a77eaf54f --- /dev/null +++ b/pkg/cli/add_wizard_command_test.go @@ -0,0 +1,16 @@ +//go:build !integration + +package cli + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestAddWizardCommandMentionsCrush(t *testing.T) { + cmd := NewAddWizardCommand(func(string) error { return nil }) + require.NotNil(t, cmd, "Add wizard command should be created") + assert.Contains(t, cmd.Long, "Copilot, Claude, Codex, Gemini, or Crush", "Add wizard help should mention all interactive engine options") +} diff --git a/pkg/cli/completion_command.go b/pkg/cli/completion_command.go index 09b80b72435..d4294ce4704 100644 --- a/pkg/cli/completion_command.go +++ b/pkg/cli/completion_command.go @@ -20,7 +20,7 @@ func NewCompletionCommand() *cobra.Command { Tab completion provides: - Command name completion (add, compile, run, etc.) - Workflow name completion for commands that accept workflow arguments -- Engine name completion for --engine flag (copilot, claude, codex, custom) +- Engine name completion for --engine flag (copilot, claude, codex, gemini, crush) - Directory path completion for --dir flag - Helpful descriptions for workflows when available diff --git a/pkg/cli/flags.go b/pkg/cli/flags.go index eadf188432a..cb89f671320 100644 --- a/pkg/cli/flags.go +++ b/pkg/cli/flags.go @@ -2,16 +2,22 @@ package cli import "github.com/spf13/cobra" +const engineFlagHelpList = "copilot, claude, codex, gemini, crush" + +func engineFlagUsage(prefix string) string { + return prefix + " (" + engineFlagHelpList + ")" +} + // addEngineFlag adds the --engine/-e flag to a command. // This flag allows overriding the AI engine type. func addEngineFlag(cmd *cobra.Command) { - cmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)") + cmd.Flags().StringP("engine", "e", "", engineFlagUsage("Override AI engine")) } // addEngineFilterFlag adds the --engine/-e flag to a command for filtering. // This flag allows filtering results by AI engine type. func addEngineFilterFlag(cmd *cobra.Command) { - cmd.Flags().StringP("engine", "e", "", "Filter logs by AI engine (claude, codex, copilot, custom)") + cmd.Flags().StringP("engine", "e", "", engineFlagUsage("Filter logs by AI engine")) } // addRepoFlag adds the --repo/-r flag to a command. diff --git a/pkg/cli/flags_test.go b/pkg/cli/flags_test.go index 776c770088a..0b5a05e8e92 100644 --- a/pkg/cli/flags_test.go +++ b/pkg/cli/flags_test.go @@ -265,3 +265,30 @@ func createDisableCommandStub() *cobra.Command { cmd.Flags().StringP("repo", "r", "", "Target repository") return cmd } + +func TestEngineFlagUsageText(t *testing.T) { + t.Parallel() + + overrideCmd := &cobra.Command{Use: "override-test"} + addEngineFlag(overrideCmd) + + engineFlag := overrideCmd.Flags().Lookup("engine") + if engineFlag == nil { + t.Fatal("Expected --engine override flag to exist") + } + + if engineFlag.Usage != "Override AI engine (copilot, claude, codex, gemini, crush)" { + t.Errorf("Unexpected --engine override usage text: %s", engineFlag.Usage) + } + + filterCmd := &cobra.Command{Use: "filter-test"} + addEngineFilterFlag(filterCmd) + filterFlag := filterCmd.Flags().Lookup("engine") + if filterFlag == nil { + t.Fatal("Expected --engine filter flag to exist") + } + + if filterFlag.Usage != "Filter logs by AI engine (copilot, claude, codex, gemini, crush)" { + t.Errorf("Unexpected --engine filter usage text: %s", filterFlag.Usage) + } +} diff --git a/pkg/cli/health_command.go b/pkg/cli/health_command.go index 0f52a495b1f..4872c0ab2d4 100644 --- a/pkg/cli/health_command.go +++ b/pkg/cli/health_command.go @@ -40,7 +40,7 @@ Shows health metrics for workflows including: - Success/failure rates over time period - Trend indicators (↑ improving, → stable, ↓ degrading) - Average execution duration -- Alerts when success rate drops below threshold +- Warnings when success rate drops below threshold When called without a workflow name, displays summary for all workflows. When called with a specific workflow name, displays detailed metrics for that workflow. @@ -51,7 +51,7 @@ Examples: ` + string(constants.CLIExtensionPrefix) + ` health # Summary of all workflows (last 7 days) ` + string(constants.CLIExtensionPrefix) + ` health issue-monster # Detailed metrics for specific workflow ` + string(constants.CLIExtensionPrefix) + ` health --days 30 # Summary for last 30 days - ` + string(constants.CLIExtensionPrefix) + ` health --threshold 90 # Alert if below 90% success rate + ` + string(constants.CLIExtensionPrefix) + ` health --threshold 90 # Warn if below 90% success rate ` + string(constants.CLIExtensionPrefix) + ` health --json # Output in JSON format ` + string(constants.CLIExtensionPrefix) + ` health issue-monster --days 90 # 90-day metrics for workflow`, Args: cobra.MaximumNArgs(1), diff --git a/pkg/cli/health_command_test.go b/pkg/cli/health_command_test.go index adb6532549f..c8760bf0158 100644 --- a/pkg/cli/health_command_test.go +++ b/pkg/cli/health_command_test.go @@ -67,6 +67,7 @@ func TestHealthCommand(t *testing.T) { assert.NotNil(t, cmd, "Health command should be created") assert.Equal(t, "health", cmd.Name(), "Command name should be 'health'") assert.True(t, cmd.HasAvailableFlags(), "Command should have flags") + assert.Contains(t, cmd.Long, "Warnings when success rate drops below threshold", "Health help should consistently use warnings terminology") // Check that required flags are registered daysFlag := cmd.Flags().Lookup("days") diff --git a/pkg/cli/init_command.go b/pkg/cli/init_command.go index 8016d77be39..65a5f7d6b3a 100644 --- a/pkg/cli/init_command.go +++ b/pkg/cli/init_command.go @@ -17,14 +17,11 @@ func NewInitCommand() *cobra.Command { Short: "Initialize the repository for agentic workflows", Long: `Initialize the repository for agentic workflows by configuring .gitattributes and creating the dispatcher agent file. -Interactive Mode (default): +Usage: gh aw init - - When invoked without flags, init enters interactive mode and prompts you to: - - Select which AI engine to use (Copilot, Claude, or Codex) - - Automatically configure engine-specific settings (e.g., MCP for Copilot) - - Detect and configure secrets from your environment - - Set up repository Actions secrets automatically + +This command performs non-interactive repository setup and does not prompt for +engine selection or secret configuration. This command: - Configures .gitattributes to mark .lock.yml files as generated @@ -59,8 +56,8 @@ After running this command, you can: - Create new workflows from scratch with: ` + string(constants.CLIExtensionPrefix) + ` new Examples: - ` + string(constants.CLIExtensionPrefix) + ` init # Interactive mode - ` + string(constants.CLIExtensionPrefix) + ` init -v # Interactive with verbose output + ` + string(constants.CLIExtensionPrefix) + ` init # Initialize repository with defaults + ` + string(constants.CLIExtensionPrefix) + ` init -v # Initialize with verbose output ` + string(constants.CLIExtensionPrefix) + ` init --no-mcp # Skip MCP configuration ` + string(constants.CLIExtensionPrefix) + ` init --codespaces # Configure Codespaces ` + string(constants.CLIExtensionPrefix) + ` init --codespaces repo1,repo2 # Codespaces with additional repos @@ -117,7 +114,7 @@ Examples: }, } - cmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)") + cmd.Flags().StringP("engine", "e", "", "Override AI engine (copilot, claude, codex, gemini, crush)") _ = cmd.Flags().MarkHidden("engine") // Hide the engine flag from help output (internal use only) cmd.Flags().Bool("no-mcp", false, "Skip configuring gh-aw MCP server integration for GitHub Copilot Agent") cmd.Flags().String("codespaces", "", "Create devcontainer.json for GitHub Codespaces with agentic workflows support. Specify comma-separated repository names in the same organization (e.g., repo1,repo2), or use without value for current repo only") diff --git a/pkg/cli/init_command_test.go b/pkg/cli/init_command_test.go index 8505f797f10..ad33ebb067f 100644 --- a/pkg/cli/init_command_test.go +++ b/pkg/cli/init_command_test.go @@ -114,8 +114,8 @@ func TestInitCommandHelp(t *testing.T) { t.Error("Expected help text to mention Copilot") } - if !strings.Contains(helpText, "Interactive Mode") { - t.Error("Expected help text to mention Interactive Mode") + if !strings.Contains(helpText, "non-interactive repository setup") { + t.Error("Expected help text to mention non-interactive setup") } } diff --git a/pkg/cli/logs_filtering_test.go b/pkg/cli/logs_filtering_test.go index 4c12068dd76..040972a5ac4 100644 --- a/pkg/cli/logs_filtering_test.go +++ b/pkg/cli/logs_filtering_test.go @@ -66,7 +66,7 @@ func TestLogsCommandFlags(t *testing.T) { t.Fatal("Engine flag not found") } - if engineFlag.Usage != "Filter logs by AI engine (claude, codex, copilot, custom)" { + if engineFlag.Usage != "Filter logs by AI engine (copilot, claude, codex, gemini, crush)" { t.Errorf("Unexpected engine flag usage text: %s", engineFlag.Usage) } diff --git a/pkg/cli/project_command.go b/pkg/cli/project_command.go index 9c551c72309..52d8c9678ac 100644 --- a/pkg/cli/project_command.go +++ b/pkg/cli/project_command.go @@ -61,7 +61,7 @@ Examples: func NewProjectNewCommand() *cobra.Command { cmd := &cobra.Command{ Use: "new ", - Short: "Create a new GitHub Project V2", + Short: "Create a new GitHub Project V2 board", Long: `Create a new GitHub Project V2 board owned by a user or organization. The project can optionally be linked to a specific repository. diff --git a/pkg/cli/project_command_test.go b/pkg/cli/project_command_test.go index 3b4d4118dcb..04f670cfc31 100644 --- a/pkg/cli/project_command_test.go +++ b/pkg/cli/project_command_test.go @@ -21,7 +21,7 @@ func TestNewProjectNewCommand(t *testing.T) { cmd := NewProjectNewCommand() require.NotNil(t, cmd, "Command should be created") assert.Equal(t, "new <title>", cmd.Use, "Command usage should be 'new <title>'") - assert.Contains(t, cmd.Short, "Create a new GitHub Project V2", "Short description should be about creating projects") + assert.Contains(t, cmd.Short, "Create a new GitHub Project V2 board", "Short description should mention board creation") // Check flags ownerFlag := cmd.Flags().Lookup("owner") diff --git a/pkg/cli/upgrade_command.go b/pkg/cli/upgrade_command.go index eaeae48fb83..0cca2c4ea03 100644 --- a/pkg/cli/upgrade_command.go +++ b/pkg/cli/upgrade_command.go @@ -42,6 +42,10 @@ This command: 3. Updates GitHub Actions versions in .github/aw/actions-lock.json (unless --no-actions is set) 4. Compiles all workflows to generate lock files (like 'compile' command) +Flag behavior: +- --no-fix skips codemods, action version updates, and workflow compilation +- --no-actions and --no-compile are only applied when --no-fix is not set + DEPENDENCY HEALTH AUDIT: Use --audit to check dependency health without performing upgrades. This includes: - Outdated Go dependencies with available updates @@ -105,8 +109,8 @@ Examples: cmd.Flags().StringP("dir", "d", "", "Workflow directory (default: .github/workflows)") cmd.Flags().Bool("no-fix", false, "Skip codemods, action version updates, and workflow compilation (only update agent files)") - cmd.Flags().Bool("no-actions", false, "Skip updating GitHub Actions versions") - cmd.Flags().Bool("no-compile", false, "Skip recompiling workflows (do not modify lock files)") + cmd.Flags().Bool("no-actions", false, "Skip updating GitHub Actions versions (ignored when --no-fix is set)") + cmd.Flags().Bool("no-compile", false, "Skip recompiling workflows (do not modify lock files; ignored when --no-fix is set)") cmd.Flags().Bool("create-pull-request", false, "Create a pull request with the upgrade changes") cmd.Flags().Bool("pr", false, "Alias for --create-pull-request") _ = cmd.Flags().MarkHidden("pr") // Hide the short alias from help output diff --git a/pkg/cli/validate_command.go b/pkg/cli/validate_command.go index 28cb6c81f59..28fa910bd79 100644 --- a/pkg/cli/validate_command.go +++ b/pkg/cli/validate_command.go @@ -76,7 +76,7 @@ Examples: }, } - cmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)") + addEngineFlag(cmd) cmd.Flags().StringP("dir", "d", "", "Workflow directory (default: .github/workflows)") cmd.Flags().Bool("strict", false, "Override frontmatter to enforce strict mode validation for all workflows (enforces action pinning, network config, safe-outputs, refuses write permissions and deprecated fields). Note: Workflows default to strict mode unless frontmatter sets strict: false") cmd.Flags().BoolP("json", "j", false, "Output results in JSON format")