From 54d528c6d48d9d23df59c0f07b7576df66921ee2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 04:21:39 +0000 Subject: [PATCH 1/6] Initial plan From 02652f73a56852a1f2321e685e2bf8e047937395 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 04:34:47 +0000 Subject: [PATCH 2/6] Add ActionNeeded field, summary footer, and --fix-suggestions flag to status command Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com> --- pkg/cli/status.go | 4 +- pkg/cli/status_command.go | 150 ++++++++++++++++++++++++++++++++------ 2 files changed, 130 insertions(+), 24 deletions(-) diff --git a/pkg/cli/status.go b/pkg/cli/status.go index 432dc9c9a68..194ebfbf301 100644 --- a/pkg/cli/status.go +++ b/pkg/cli/status.go @@ -32,13 +32,15 @@ Examples: jsonFlag, _ := cmd.Flags().GetBool("json") ref, _ := cmd.Flags().GetString("ref") labelFilter, _ := cmd.Flags().GetString("label") - return StatusWorkflows(pattern, verbose, jsonFlag, ref, labelFilter) + fixSuggestions, _ := cmd.Flags().GetBool("fix-suggestions") + return StatusWorkflows(pattern, verbose, jsonFlag, ref, labelFilter, fixSuggestions) }, } addJSONFlag(cmd) cmd.Flags().String("ref", "", "Filter runs by branch or tag name (e.g., main, v1.0.0)") cmd.Flags().String("label", "", "Filter workflows by label") + cmd.Flags().Bool("fix-suggestions", false, "Generate executable shell script to fix stale workflows") // Register completions for status command cmd.ValidArgsFunction = CompleteWorkflowNames diff --git a/pkg/cli/status_command.go b/pkg/cli/status_command.go index 035a4bdcffc..97cfaa9d98e 100644 --- a/pkg/cli/status_command.go +++ b/pkg/cli/status_command.go @@ -28,9 +28,10 @@ type WorkflowStatus struct { On any `json:"on,omitempty" console:"-"` RunStatus string `json:"run_status,omitempty" console:"header:Run Status,omitempty"` RunConclusion string `json:"run_conclusion,omitempty" console:"header:Run Conclusion,omitempty"` + ActionNeeded string `json:"action_needed,omitempty" console:"header:Action Needed,omitempty"` } -func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, labelFilter string) error { +func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, labelFilter string, fixSuggestions bool) error { statusLog.Printf("Checking workflow status: pattern=%s, jsonOutput=%v, ref=%s, labelFilter=%s", pattern, jsonOutput, ref, labelFilter) if verbose && !jsonOutput { fmt.Printf("Checking status of workflow files\n") @@ -125,20 +126,15 @@ func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, // Check if compiled (.lock.yml file is in .github/workflows) lockFile := strings.TrimSuffix(file, ".md") + ".lock.yml" - compiled := "N/A" timeRemaining := "N/A" - if _, err := os.Stat(lockFile); err == nil { - // Check if up to date - mdStat, _ := os.Stat(file) - lockStat, _ := os.Stat(lockFile) - if mdStat.ModTime().After(lockStat.ModTime()) { - compiled = "No" - } else { - compiled = "Yes" - } + // Determine staleness and action needed + staleInfo := checkWorkflowStaleness(file, lockFile) + compiled := staleInfo.compiled + actionNeeded := staleInfo.actionNeeded - // Extract stop-time from lock file + // Extract stop-time from lock file if it exists + if _, err := os.Stat(lockFile); err == nil { if stopTime := workflow.ExtractStopTimeFromLockFile(lockFile); stopTime != "" { timeRemaining = calculateTimeRemaining(stopTime) } @@ -209,6 +205,7 @@ func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, On: onField, RunStatus: runStatus, RunConclusion: runConclusion, + ActionNeeded: actionNeeded, }) } @@ -238,20 +235,15 @@ func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, // Check if compiled (.lock.yml file is in .github/workflows) lockFile := strings.TrimSuffix(file, ".md") + ".lock.yml" - compiled := "N/A" timeRemaining := "N/A" - if _, err := os.Stat(lockFile); err == nil { - // Check if up to date - mdStat, _ := os.Stat(file) - lockStat, _ := os.Stat(lockFile) - if mdStat.ModTime().After(lockStat.ModTime()) { - compiled = "No" - } else { - compiled = "Yes" - } + // Determine staleness and action needed + staleInfo := checkWorkflowStaleness(file, lockFile) + compiled := staleInfo.compiled + actionNeeded := staleInfo.actionNeeded - // Extract stop-time from lock file + // Extract stop-time from lock file if it exists + if _, err := os.Stat(lockFile); err == nil { if stopTime := workflow.ExtractStopTimeFromLockFile(lockFile); stopTime != "" { timeRemaining = calculateTimeRemaining(stopTime) } @@ -318,12 +310,35 @@ func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, Labels: labels, RunStatus: runStatus, RunConclusion: runConclusion, + ActionNeeded: actionNeeded, }) } + // Handle --fix-suggestions flag + if fixSuggestions { + return generateFixScript(statuses) + } + // Render the table using struct-based rendering fmt.Print(console.RenderStruct(statuses)) + // Add summary footer showing compilation status + needsCompilation := 0 + for _, s := range statuses { + if s.ActionNeeded != "" { + needsCompilation++ + } + } + + if needsCompilation > 0 { + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("%d workflow%s need compilation", needsCompilation, pluralize(needsCompilation)))) + fmt.Fprintf(os.Stderr, " Run: %s\n", console.FormatCommandMessage("gh aw compile --all")) + } else if len(statuses) > 0 { + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("All workflows are up-to-date")) + } + return nil } @@ -366,6 +381,51 @@ func calculateTimeRemaining(stopTimeStr string) string { } } +// stalenessInfo holds information about workflow staleness +type stalenessInfo struct { + compiled string // "Yes", "No", "N/A", or "Stale" + actionNeeded string // Command to run if action is needed +} + +// checkWorkflowStaleness determines if a workflow needs compilation and returns action needed +func checkWorkflowStaleness(mdFile, lockFile string) stalenessInfo { + // Check if lock file exists + if _, err := os.Stat(lockFile); os.IsNotExist(err) { + // Never compiled + baseName := filepath.Base(mdFile) + return stalenessInfo{ + compiled: "No", + actionNeeded: fmt.Sprintf("gh aw compile %s", baseName), + } + } + + // Lock file exists - check if up to date using timestamp comparison + mdStat, err := os.Stat(mdFile) + if err != nil { + return stalenessInfo{compiled: "N/A", actionNeeded: ""} + } + + lockStat, err := os.Stat(lockFile) + if err != nil { + return stalenessInfo{compiled: "N/A", actionNeeded: ""} + } + + if mdStat.ModTime().After(lockStat.ModTime()) { + // Stale - source modified after lock file + baseName := filepath.Base(mdFile) + return stalenessInfo{ + compiled: "Stale", + actionNeeded: fmt.Sprintf("gh aw compile %s", baseName), + } + } + + // Up to date + return stalenessInfo{ + compiled: "Yes", + actionNeeded: "", + } +} + // StatusWorkflows shows status of workflows // getMarkdownWorkflowFiles finds all markdown files in .github/workflows directory func getMarkdownWorkflowFiles() ([]string, error) { @@ -520,3 +580,47 @@ func fetchLatestRunsByRef(ref string, verbose bool) (map[string]*WorkflowRun, er statusLog.Printf("Fetched latest runs for %d workflows on ref %s", len(latestRuns), ref) return latestRuns, nil } + +// generateFixScript generates an executable shell script to fix stale workflows +func generateFixScript(statuses []WorkflowStatus) error { + var staleWorkflows []string + for _, s := range statuses { + if s.ActionNeeded != "" { + staleWorkflows = append(staleWorkflows, s.Workflow+".md") + } + } + + if len(staleWorkflows) == 0 { + fmt.Println("#!/bin/bash") + fmt.Println("# Generated by gh aw status --fix-suggestions") + fmt.Println("# All workflows are up-to-date - no action needed") + return nil + } + + fmt.Println("#!/bin/bash") + fmt.Println("# Generated by gh aw status --fix-suggestions") + fmt.Println("# This script compiles all stale workflows") + fmt.Println() + fmt.Printf("# Found %d workflow%s needing compilation\n", len(staleWorkflows), pluralize(len(staleWorkflows))) + fmt.Println() + + for _, workflow := range staleWorkflows { + fmt.Printf("gh aw compile %s\n", workflow) + } + + fmt.Println() + fmt.Println("# Stage compiled lock files") + fmt.Println("git add .github/workflows/*.lock.yml") + fmt.Println() + fmt.Println("echo \"Done! Review changes with: git diff --cached\"") + + return nil +} + +// pluralize returns "s" if count != 1, otherwise empty string +func pluralize(count int) string { + if count == 1 { + return "" + } + return "s" +} From 5967c8a261c86c52976f7bb0c450fbb2a37667ee Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 04:44:20 +0000 Subject: [PATCH 3/6] Add color coding to Compiled column and tests for ActionNeeded field Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com> --- pkg/cli/commands_test.go | 10 +++--- pkg/cli/status_command.go | 27 +++++++++++++++- pkg/cli/status_command_test.go | 58 ++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/pkg/cli/commands_test.go b/pkg/cli/commands_test.go index 63a80bda5f5..9ec01e8a305 100644 --- a/pkg/cli/commands_test.go +++ b/pkg/cli/commands_test.go @@ -219,7 +219,7 @@ func TestRemoveWorkflows(t *testing.T) { } func TestStatusWorkflows(t *testing.T) { - err := StatusWorkflows("test-pattern", false, false, "", "") + err := StatusWorkflows("test-pattern", false, false, "", "", false) // Should not error since it's a stub implementation if err != nil { @@ -421,10 +421,10 @@ Test workflow for command existence.` _, err := CompileWorkflows(config) return err }, false, "CompileWorkflows"}, - {func() error { return RemoveWorkflows("nonexistent", false) }, false, "RemoveWorkflows"}, // Should handle missing directory gracefully - {func() error { return StatusWorkflows("nonexistent", false, false, "", "") }, false, "StatusWorkflows"}, // Should handle missing directory gracefully - {func() error { return EnableWorkflows("nonexistent") }, true, "EnableWorkflows"}, // Should now error when no workflows found to enable - {func() error { return DisableWorkflows("nonexistent") }, true, "DisableWorkflows"}, // Should now also error when no workflows found to disable + {func() error { return RemoveWorkflows("nonexistent", false) }, false, "RemoveWorkflows"}, // Should handle missing directory gracefully + {func() error { return StatusWorkflows("nonexistent", false, false, "", "", false) }, false, "StatusWorkflows"}, // Should handle missing directory gracefully + {func() error { return EnableWorkflows("nonexistent") }, true, "EnableWorkflows"}, // Should now error when no workflows found to enable + {func() error { return DisableWorkflows("nonexistent") }, true, "DisableWorkflows"}, // Should now also error when no workflows found to disable {func() error { return RunWorkflowOnGitHub("", false, "", "", "", false, false, false, []string{}, false) }, true, "RunWorkflowOnGitHub"}, // Should error with empty workflow name diff --git a/pkg/cli/status_command.go b/pkg/cli/status_command.go index 97cfaa9d98e..e05c4859f94 100644 --- a/pkg/cli/status_command.go +++ b/pkg/cli/status_command.go @@ -12,6 +12,8 @@ import ( "github.com/githubnext/gh-aw/pkg/console" "github.com/githubnext/gh-aw/pkg/logger" "github.com/githubnext/gh-aw/pkg/parser" + "github.com/githubnext/gh-aw/pkg/styles" + "github.com/githubnext/gh-aw/pkg/tty" "github.com/githubnext/gh-aw/pkg/workflow" ) @@ -239,7 +241,7 @@ func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, // Determine staleness and action needed staleInfo := checkWorkflowStaleness(file, lockFile) - compiled := staleInfo.compiled + compiled := colorCodeCompiled(staleInfo.compiled) // Apply color for console output actionNeeded := staleInfo.actionNeeded // Extract stop-time from lock file if it exists @@ -387,6 +389,29 @@ type stalenessInfo struct { actionNeeded string // Command to run if action is needed } +// colorCodeCompiled adds color formatting to the compiled status for console output +func colorCodeCompiled(compiled string) string { + // Only apply colors if output is a TTY + if !tty.IsStdoutTerminal() { + return compiled + } + + switch compiled { + case "Yes": + // Green for up-to-date + return styles.Success.Render(compiled) + case "Stale": + // Yellow for stale (needs recompilation) + return styles.Warning.Render(compiled) + case "No": + // Red for never compiled + return styles.Error.Render(compiled) + default: + // No color for N/A or other statuses + return compiled + } +} + // checkWorkflowStaleness determines if a workflow needs compilation and returns action needed func checkWorkflowStaleness(mdFile, lockFile string) stalenessInfo { // Check if lock file exists diff --git a/pkg/cli/status_command_test.go b/pkg/cli/status_command_test.go index b46ea2900ec..e3b8c5691c2 100644 --- a/pkg/cli/status_command_test.go +++ b/pkg/cli/status_command_test.go @@ -28,7 +28,7 @@ func TestStatusWorkflows_JSONOutput(t *testing.T) { // Test JSON output without pattern t.Run("JSON output without pattern", func(t *testing.T) { - err := StatusWorkflows("", false, true, "", "") + err := StatusWorkflows("", false, true, "", "", false) if err != nil { t.Errorf("StatusWorkflows with JSON flag failed: %v", err) } @@ -38,7 +38,7 @@ func TestStatusWorkflows_JSONOutput(t *testing.T) { // Test JSON output with pattern t.Run("JSON output with pattern", func(t *testing.T) { - err := StatusWorkflows("smoke", false, true, "", "") + err := StatusWorkflows("smoke", false, true, "", "", false) if err != nil { t.Errorf("StatusWorkflows with JSON flag and pattern failed: %v", err) } @@ -513,3 +513,57 @@ func TestWorkflowStatus_ConsoleRenderingWithRunStatus(t *testing.T) { } } } + +// TestWorkflowStatus_JSONMarshalingWithActionNeeded tests that action_needed is included in JSON output +func TestWorkflowStatus_JSONMarshalingWithActionNeeded(t *testing.T) { + // Test that WorkflowStatus with action_needed can be marshaled to JSON + status := WorkflowStatus{ + Workflow: "test-workflow", + EngineID: "copilot", + Compiled: "No", + Status: "active", + ActionNeeded: "gh aw compile test-workflow.md", + } + + jsonBytes, err := json.Marshal(status) + if err != nil { + t.Fatalf("Failed to marshal WorkflowStatus: %v", err) + } + + // Verify JSON contains action_needed field + var unmarshaled map[string]any + if err := json.Unmarshal(jsonBytes, &unmarshaled); err != nil { + t.Fatalf("Failed to unmarshal JSON: %v", err) + } + + if unmarshaled["action_needed"] != "gh aw compile test-workflow.md" { + t.Errorf("Expected action_needed='gh aw compile test-workflow.md', got %v", unmarshaled["action_needed"]) + } +} + +// TestWorkflowStatus_JSONMarshalingWithoutActionNeeded tests that empty action_needed is omitted +func TestWorkflowStatus_JSONMarshalingWithoutActionNeeded(t *testing.T) { + // Test that WorkflowStatus without action_needed omits the field + status := WorkflowStatus{ + Workflow: "test-workflow", + EngineID: "copilot", + Compiled: "Yes", + Status: "active", + // ActionNeeded is empty + } + + jsonBytes, err := json.Marshal(status) + if err != nil { + t.Fatalf("Failed to marshal WorkflowStatus: %v", err) + } + + // Verify JSON omits empty action_needed field (due to omitempty) + var unmarshaled map[string]any + if err := json.Unmarshal(jsonBytes, &unmarshaled); err != nil { + t.Fatalf("Failed to unmarshal JSON: %v", err) + } + + if _, exists := unmarshaled["action_needed"]; exists { + t.Errorf("Expected action_needed to be omitted when empty, but it was present with value: %v", unmarshaled["action_needed"]) + } +} From f213bded900f48e3f91a4fc71fe52e11822caeae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 05:53:27 +0000 Subject: [PATCH 4/6] Fix bulk compile command in status footer: use 'gh aw compile' instead of 'gh aw compile --all' Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/status_command.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cli/status_command.go b/pkg/cli/status_command.go index e05c4859f94..6db9923cfd9 100644 --- a/pkg/cli/status_command.go +++ b/pkg/cli/status_command.go @@ -335,7 +335,7 @@ func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, if needsCompilation > 0 { fmt.Fprintln(os.Stderr) fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("%d workflow%s need compilation", needsCompilation, pluralize(needsCompilation)))) - fmt.Fprintf(os.Stderr, " Run: %s\n", console.FormatCommandMessage("gh aw compile --all")) + fmt.Fprintf(os.Stderr, " Run: %s\n", console.FormatCommandMessage("gh aw compile")) } else if len(statuses) > 0 { fmt.Fprintln(os.Stderr) fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("All workflows are up-to-date")) From 960481d818c4a5b3a464aae4df177b74e966cf67 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 06:08:04 +0000 Subject: [PATCH 5/6] Remove --fix-suggestions flag, keep Action Needed column and summary footer always on Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/commands_test.go | 10 ++++---- pkg/cli/status.go | 4 +--- pkg/cli/status_command.go | 43 +--------------------------------- pkg/cli/status_command_test.go | 4 ++-- 4 files changed, 9 insertions(+), 52 deletions(-) diff --git a/pkg/cli/commands_test.go b/pkg/cli/commands_test.go index 9ec01e8a305..63a80bda5f5 100644 --- a/pkg/cli/commands_test.go +++ b/pkg/cli/commands_test.go @@ -219,7 +219,7 @@ func TestRemoveWorkflows(t *testing.T) { } func TestStatusWorkflows(t *testing.T) { - err := StatusWorkflows("test-pattern", false, false, "", "", false) + err := StatusWorkflows("test-pattern", false, false, "", "") // Should not error since it's a stub implementation if err != nil { @@ -421,10 +421,10 @@ Test workflow for command existence.` _, err := CompileWorkflows(config) return err }, false, "CompileWorkflows"}, - {func() error { return RemoveWorkflows("nonexistent", false) }, false, "RemoveWorkflows"}, // Should handle missing directory gracefully - {func() error { return StatusWorkflows("nonexistent", false, false, "", "", false) }, false, "StatusWorkflows"}, // Should handle missing directory gracefully - {func() error { return EnableWorkflows("nonexistent") }, true, "EnableWorkflows"}, // Should now error when no workflows found to enable - {func() error { return DisableWorkflows("nonexistent") }, true, "DisableWorkflows"}, // Should now also error when no workflows found to disable + {func() error { return RemoveWorkflows("nonexistent", false) }, false, "RemoveWorkflows"}, // Should handle missing directory gracefully + {func() error { return StatusWorkflows("nonexistent", false, false, "", "") }, false, "StatusWorkflows"}, // Should handle missing directory gracefully + {func() error { return EnableWorkflows("nonexistent") }, true, "EnableWorkflows"}, // Should now error when no workflows found to enable + {func() error { return DisableWorkflows("nonexistent") }, true, "DisableWorkflows"}, // Should now also error when no workflows found to disable {func() error { return RunWorkflowOnGitHub("", false, "", "", "", false, false, false, []string{}, false) }, true, "RunWorkflowOnGitHub"}, // Should error with empty workflow name diff --git a/pkg/cli/status.go b/pkg/cli/status.go index 194ebfbf301..432dc9c9a68 100644 --- a/pkg/cli/status.go +++ b/pkg/cli/status.go @@ -32,15 +32,13 @@ Examples: jsonFlag, _ := cmd.Flags().GetBool("json") ref, _ := cmd.Flags().GetString("ref") labelFilter, _ := cmd.Flags().GetString("label") - fixSuggestions, _ := cmd.Flags().GetBool("fix-suggestions") - return StatusWorkflows(pattern, verbose, jsonFlag, ref, labelFilter, fixSuggestions) + return StatusWorkflows(pattern, verbose, jsonFlag, ref, labelFilter) }, } addJSONFlag(cmd) cmd.Flags().String("ref", "", "Filter runs by branch or tag name (e.g., main, v1.0.0)") cmd.Flags().String("label", "", "Filter workflows by label") - cmd.Flags().Bool("fix-suggestions", false, "Generate executable shell script to fix stale workflows") // Register completions for status command cmd.ValidArgsFunction = CompleteWorkflowNames diff --git a/pkg/cli/status_command.go b/pkg/cli/status_command.go index 6db9923cfd9..aa87a698539 100644 --- a/pkg/cli/status_command.go +++ b/pkg/cli/status_command.go @@ -33,7 +33,7 @@ type WorkflowStatus struct { ActionNeeded string `json:"action_needed,omitempty" console:"header:Action Needed,omitempty"` } -func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, labelFilter string, fixSuggestions bool) error { +func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, labelFilter string) error { statusLog.Printf("Checking workflow status: pattern=%s, jsonOutput=%v, ref=%s, labelFilter=%s", pattern, jsonOutput, ref, labelFilter) if verbose && !jsonOutput { fmt.Printf("Checking status of workflow files\n") @@ -316,11 +316,6 @@ func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, }) } - // Handle --fix-suggestions flag - if fixSuggestions { - return generateFixScript(statuses) - } - // Render the table using struct-based rendering fmt.Print(console.RenderStruct(statuses)) @@ -606,42 +601,6 @@ func fetchLatestRunsByRef(ref string, verbose bool) (map[string]*WorkflowRun, er return latestRuns, nil } -// generateFixScript generates an executable shell script to fix stale workflows -func generateFixScript(statuses []WorkflowStatus) error { - var staleWorkflows []string - for _, s := range statuses { - if s.ActionNeeded != "" { - staleWorkflows = append(staleWorkflows, s.Workflow+".md") - } - } - - if len(staleWorkflows) == 0 { - fmt.Println("#!/bin/bash") - fmt.Println("# Generated by gh aw status --fix-suggestions") - fmt.Println("# All workflows are up-to-date - no action needed") - return nil - } - - fmt.Println("#!/bin/bash") - fmt.Println("# Generated by gh aw status --fix-suggestions") - fmt.Println("# This script compiles all stale workflows") - fmt.Println() - fmt.Printf("# Found %d workflow%s needing compilation\n", len(staleWorkflows), pluralize(len(staleWorkflows))) - fmt.Println() - - for _, workflow := range staleWorkflows { - fmt.Printf("gh aw compile %s\n", workflow) - } - - fmt.Println() - fmt.Println("# Stage compiled lock files") - fmt.Println("git add .github/workflows/*.lock.yml") - fmt.Println() - fmt.Println("echo \"Done! Review changes with: git diff --cached\"") - - return nil -} - // pluralize returns "s" if count != 1, otherwise empty string func pluralize(count int) string { if count == 1 { diff --git a/pkg/cli/status_command_test.go b/pkg/cli/status_command_test.go index e3b8c5691c2..453ccf00349 100644 --- a/pkg/cli/status_command_test.go +++ b/pkg/cli/status_command_test.go @@ -28,7 +28,7 @@ func TestStatusWorkflows_JSONOutput(t *testing.T) { // Test JSON output without pattern t.Run("JSON output without pattern", func(t *testing.T) { - err := StatusWorkflows("", false, true, "", "", false) + err := StatusWorkflows("", false, true, "", "") if err != nil { t.Errorf("StatusWorkflows with JSON flag failed: %v", err) } @@ -38,7 +38,7 @@ func TestStatusWorkflows_JSONOutput(t *testing.T) { // Test JSON output with pattern t.Run("JSON output with pattern", func(t *testing.T) { - err := StatusWorkflows("smoke", false, true, "", "", false) + err := StatusWorkflows("smoke", false, true, "", "") if err != nil { t.Errorf("StatusWorkflows with JSON flag and pattern failed: %v", err) } From ea40e0c2c7e22e2b76ec0aca76b9cacd0edea1a0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 06:18:10 +0000 Subject: [PATCH 6/6] Rephrase summary message to avoid pluralization and remove pluralize function Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/status_command.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pkg/cli/status_command.go b/pkg/cli/status_command.go index aa87a698539..4d63da3177e 100644 --- a/pkg/cli/status_command.go +++ b/pkg/cli/status_command.go @@ -329,7 +329,7 @@ func StatusWorkflows(pattern string, verbose bool, jsonOutput bool, ref string, if needsCompilation > 0 { fmt.Fprintln(os.Stderr) - fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("%d workflow%s need compilation", needsCompilation, pluralize(needsCompilation)))) + fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Workflows needing compilation: %d", needsCompilation))) fmt.Fprintf(os.Stderr, " Run: %s\n", console.FormatCommandMessage("gh aw compile")) } else if len(statuses) > 0 { fmt.Fprintln(os.Stderr) @@ -600,11 +600,3 @@ func fetchLatestRunsByRef(ref string, verbose bool) (map[string]*WorkflowRun, er statusLog.Printf("Fetched latest runs for %d workflows on ref %s", len(latestRuns), ref) return latestRuns, nil } - -// pluralize returns "s" if count != 1, otherwise empty string -func pluralize(count int) string { - if count == 1 { - return "" - } - return "s" -}