diff --git a/docs/src/content/docs/agent-factory-status.mdx b/docs/src/content/docs/agent-factory-status.mdx index 5d20cd6fb2..9ded2e3614 100644 --- a/docs/src/content/docs/agent-factory-status.mdx +++ b/docs/src/content/docs/agent-factory-status.mdx @@ -54,6 +54,7 @@ These are experimental agentic workflows used by the GitHub Next team to learn, | [Daily Firewall Logs Collector and Reporter](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-firewall-report.md) | copilot | [![Daily Firewall Logs Collector and Reporter](https://github.com/github/gh-aw/actions/workflows/daily-firewall-report.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-firewall-report.lock.yml) | - | - | | [Daily Issues Report Generator](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-issues-report.md) | codex | [![Daily Issues Report Generator](https://github.com/github/gh-aw/actions/workflows/daily-issues-report.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-issues-report.lock.yml) | - | - | | [Daily Malicious Code Scan Agent](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-malicious-code-scan.md) | copilot | [![Daily Malicious Code Scan Agent](https://github.com/github/gh-aw/actions/workflows/daily-malicious-code-scan.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-malicious-code-scan.lock.yml) | - | - | +| [Daily MCP Tool Concurrency Analysis](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-mcp-concurrency-analysis.md) | copilot | [![Daily MCP Tool Concurrency Analysis](https://github.com/github/gh-aw/actions/workflows/daily-mcp-concurrency-analysis.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-mcp-concurrency-analysis.lock.yml) | `0 9 * * 1-5` | - | | [Daily News](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-news.md) | copilot | [![Daily News](https://github.com/github/gh-aw/actions/workflows/daily-news.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-news.lock.yml) | `0 9 * * 1-5` | - | | [Daily Observability Report for AWF Firewall and MCP Gateway](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-observability-report.md) | codex | [![Daily Observability Report for AWF Firewall and MCP Gateway](https://github.com/github/gh-aw/actions/workflows/daily-observability-report.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-observability-report.lock.yml) | - | - | | [Daily Project Performance Summary Generator (Using Safe Inputs)](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-performance-summary.md) | codex | [![Daily Project Performance Summary Generator (Using Safe Inputs)](https://github.com/github/gh-aw/actions/workflows/daily-performance-summary.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-performance-summary.lock.yml) | - | - | diff --git a/pkg/cli/agentic_workflow_agent_test.go b/pkg/cli/agentic_workflow_agent_test.go deleted file mode 100644 index 859f9acf01..0000000000 --- a/pkg/cli/agentic_workflow_agent_test.go +++ /dev/null @@ -1,150 +0,0 @@ -//go:build !integration - -package cli - -import ( - "os" - "os/exec" - "path/filepath" - "testing" - - "github.com/github/gh-aw/pkg/testutil" -) - -func TestEnsureCreateWorkflowPrompt(t *testing.T) { - tests := []struct { - name string - existingContent string - expectExists bool - }{ - { - name: "reports missing file without error", - existingContent: "", - expectExists: false, - }, - { - name: "reports existing file", - existingContent: "# Test content", - expectExists: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Create a temporary directory for testing - tempDir := testutil.TempDir(t, "test-*") - - // Change to temp directory and initialize git repo for findGitRoot to work - oldWd, _ := os.Getwd() - defer func() { - _ = os.Chdir(oldWd) - }() - err := os.Chdir(tempDir) - if err != nil { - t.Fatalf("Failed to change directory: %v", err) - } - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatalf("Failed to init git repo: %v", err) - } - - awDir := filepath.Join(tempDir, ".github", "aw") - promptPath := filepath.Join(awDir, "create-agentic-workflow.md") - - // Create initial content if specified - if tt.existingContent != "" { - if err := os.MkdirAll(awDir, 0755); err != nil { - t.Fatalf("Failed to create aw directory: %v", err) - } - if err := os.WriteFile(promptPath, []byte(tt.existingContent), 0644); err != nil { - t.Fatalf("Failed to create initial prompt: %v", err) - } - } - - // Call the function with skipInstructions=false to test the functionality - err = ensureCreateWorkflowPrompt(false, false) - if err != nil { - t.Fatalf("ensureCreateWorkflowPrompt() returned error: %v", err) - } - - // Check that file exists or not based on test expectation - _, statErr := os.Stat(promptPath) - fileExists := statErr == nil - - if fileExists != tt.expectExists { - if tt.expectExists { - t.Errorf("Expected prompt file to exist, but it doesn't") - } else { - t.Errorf("Expected prompt file to not exist, but it does") - } - } - }) - } -} - -func TestEnsureCreateWorkflowPrompt_WithSkipInstructionsTrue(t *testing.T) { - // Create a temporary directory for testing - tempDir := testutil.TempDir(t, "test-*") - - // Change to temp directory and initialize git repo for findGitRoot to work - oldWd, _ := os.Getwd() - defer func() { - _ = os.Chdir(oldWd) - }() - err := os.Chdir(tempDir) - if err != nil { - t.Fatalf("Failed to change directory: %v", err) - } - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatalf("Failed to init git repo: %v", err) - } - - // Call the function with skipInstructions=true - err = ensureCreateWorkflowPrompt(false, true) - if err != nil { - t.Fatalf("ensureCreateWorkflowPrompt() returned error: %v", err) - } - - // Check that file was NOT created - awDir := filepath.Join(tempDir, ".github", "aw") - promptPath := filepath.Join(awDir, "create-agentic-workflow.md") - if _, err := os.Stat(promptPath); !os.IsNotExist(err) { - t.Fatalf("Expected prompt file to NOT exist when skipInstructions=true") - } -} - -func TestEnsureCreateWorkflowPrompt_ReportsNonExistent(t *testing.T) { - // Create a temporary directory for testing - tempDir := testutil.TempDir(t, "test-*") - - // Change to temp directory and initialize git repo for findGitRoot to work - oldWd, _ := os.Getwd() - defer func() { - _ = os.Chdir(oldWd) - }() - err := os.Chdir(tempDir) - if err != nil { - t.Fatalf("Failed to change directory: %v", err) - } - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatalf("Failed to init git repo: %v", err) - } - - // Call the function - it should not error even if file doesn't exist - err = ensureCreateWorkflowPrompt(false, false) - if err != nil { - t.Fatalf("ensureCreateWorkflowPrompt() returned error: %v", err) - } - - // Check that new prompt file was NOT created (files are source of truth in .github/aw/) - awDir := filepath.Join(tempDir, ".github", "aw") - newPromptPath := filepath.Join(awDir, "create-agentic-workflow.md") - if _, err := os.Stat(newPromptPath); !os.IsNotExist(err) { - t.Fatalf("Expected new prompt file to NOT be created (files are source of truth)") - } -} diff --git a/pkg/cli/copilot-agents.go b/pkg/cli/copilot-agents.go index 9cd6907fed..fcd638b872 100644 --- a/pkg/cli/copilot-agents.go +++ b/pkg/cli/copilot-agents.go @@ -12,88 +12,6 @@ import ( var copilotAgentsLog = logger.New("cli:copilot_agents") -// cleanupOldPromptFile removes an old prompt file from .github/prompts/ if it exists -func cleanupOldPromptFile(promptFileName string, verbose bool) error { - gitRoot, err := findGitRoot() - if err != nil { - return nil // Not in a git repository, skip - } - - oldPath := filepath.Join(gitRoot, ".github", "prompts", promptFileName) - - // Check if the old file exists and remove it - if _, err := os.Stat(oldPath); err == nil { - if err := os.Remove(oldPath); err != nil { - return fmt.Errorf("failed to remove old prompt file: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Removed old prompt file: %s", oldPath))) - } - } - - return nil -} - -// ensureCopilotInstructions ensures that .github/aw/github-agentic-workflows.md exists -func ensureCopilotInstructions(verbose bool, skipInstructions bool) error { - copilotAgentsLog.Print("Checking Copilot instructions file") - - if skipInstructions { - copilotAgentsLog.Print("Skipping instructions check: instructions disabled") - return nil - } - - // First, clean up the old file location if it exists - if err := cleanupOldCopilotInstructions(verbose); err != nil { - return err - } - - gitRoot, err := findGitRoot() - if err != nil { - return err // Not in a git repository, skip - } - - targetPath := filepath.Join(gitRoot, ".github", "aw", "github-agentic-workflows.md") - - // Check if the file exists - if _, err := os.Stat(targetPath); err == nil { - copilotAgentsLog.Printf("Copilot instructions file exists: %s", targetPath) - if verbose { - fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Copilot instructions file exists: %s", targetPath))) - } - return nil - } - - // File doesn't exist - this is expected in external repositories - copilotAgentsLog.Printf("Copilot instructions file not found: %s (expected in gh-aw repository)", targetPath) - if verbose { - fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Copilot instructions file not found: %s", targetPath))) - } - return nil -} - -// cleanupOldCopilotInstructions removes the old instructions file from .github/instructions/ -func cleanupOldCopilotInstructions(verbose bool) error { - gitRoot, err := findGitRoot() - if err != nil { - return nil // Not in a git repository, skip - } - - oldPath := filepath.Join(gitRoot, ".github", "instructions", "github-agentic-workflows.instructions.md") - - // Check if the old file exists and remove it - if _, err := os.Stat(oldPath); err == nil { - if err := os.Remove(oldPath); err != nil { - return fmt.Errorf("failed to remove old instructions file: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Removed old instructions file: %s", oldPath))) - } - } - - return nil -} - // ensureAgenticWorkflowsDispatcher ensures that .github/agents/agentic-workflows.agent.md contains the dispatcher agent func ensureAgenticWorkflowsDispatcher(verbose bool, skipInstructions bool) error { copilotAgentsLog.Print("Ensuring agentic workflows dispatcher agent") @@ -161,66 +79,25 @@ func ensureAgenticWorkflowsDispatcher(verbose bool, skipInstructions bool) error return nil } -// ensureCreateWorkflowPrompt ensures that .github/aw/create-agentic-workflow.md exists -func ensureCreateWorkflowPrompt(verbose bool, skipInstructions bool) error { - return ensurePromptFileExists(".github/aw/create-agentic-workflow.md", "create workflow prompt", verbose, skipInstructions) -} - -// ensureUpdateWorkflowPrompt ensures that .github/aw/update-agentic-workflow.md exists -func ensureUpdateWorkflowPrompt(verbose bool, skipInstructions bool) error { - return ensurePromptFileExists(".github/aw/update-agentic-workflow.md", "update workflow prompt", verbose, skipInstructions) -} - -// ensureCreateSharedAgenticWorkflowPrompt ensures that .github/aw/create-shared-agentic-workflow.md exists -func ensureCreateSharedAgenticWorkflowPrompt(verbose bool, skipInstructions bool) error { - return ensurePromptFileExists(".github/aw/create-shared-agentic-workflow.md", "create shared workflow prompt", verbose, skipInstructions) -} - -// ensureDebugWorkflowPrompt ensures that .github/aw/debug-agentic-workflow.md exists -func ensureDebugWorkflowPrompt(verbose bool, skipInstructions bool) error { - return ensurePromptFileExists(".github/aw/debug-agentic-workflow.md", "debug workflow prompt", verbose, skipInstructions) -} - -// ensureUpgradeAgenticWorkflowsPrompt ensures that .github/aw/upgrade-agentic-workflows.md exists -func ensureUpgradeAgenticWorkflowsPrompt(verbose bool, skipInstructions bool) error { - return ensurePromptFileExists(".github/aw/upgrade-agentic-workflows.md", "upgrade workflows prompt", verbose, skipInstructions) -} - -// ensureSerenaTool ensures that .github/aw/serena-tool.md exists -func ensureSerenaTool(verbose bool, skipInstructions bool) error { - return ensurePromptFileExists(".github/aw/serena-tool.md", "Serena tool documentation", verbose, skipInstructions) -} - -// ensurePromptFileExists checks if a prompt file exists -func ensurePromptFileExists(relativePath, fileType string, verbose bool, skipInstructions bool) error { - copilotAgentsLog.Printf("Checking %s file: %s", fileType, relativePath) - - if skipInstructions { - copilotAgentsLog.Print("Skipping file check: instructions disabled") - return nil - } - +// cleanupOldPromptFile removes an old prompt file from .github/prompts/ if it exists +func cleanupOldPromptFile(promptFileName string, verbose bool) error { gitRoot, err := findGitRoot() if err != nil { - return err // Not in a git repository, skip + return nil // Not in a git repository, skip } - targetPath := filepath.Join(gitRoot, relativePath) + oldPath := filepath.Join(gitRoot, ".github", "prompts", promptFileName) - // Check if the file exists - if _, err := os.Stat(targetPath); err == nil { - copilotAgentsLog.Printf("%s file exists: %s", fileType, targetPath) + // Check if the old file exists and remove it + if _, err := os.Stat(oldPath); err == nil { + if err := os.Remove(oldPath); err != nil { + return fmt.Errorf("failed to remove old prompt file: %w", err) + } if verbose { - fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("%s file exists: %s", fileType, targetPath))) + fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Removed old prompt file: %s", oldPath))) } - return nil } - // File doesn't exist - this is expected in external repositories - copilotAgentsLog.Printf("%s file not found: %s (expected in gh-aw repository)", fileType, targetPath) - if verbose { - fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("%s file not found: %s", fileType, targetPath))) - } return nil } diff --git a/pkg/cli/copilot_instructions_test.go b/pkg/cli/copilot_instructions_test.go deleted file mode 100644 index 6d110699be..0000000000 --- a/pkg/cli/copilot_instructions_test.go +++ /dev/null @@ -1,171 +0,0 @@ -//go:build !integration - -package cli - -import ( - "os" - "os/exec" - "path/filepath" - "testing" - - "github.com/github/gh-aw/pkg/testutil" -) - -func TestEnsureCopilotInstructions(t *testing.T) { - tests := []struct { - name string - existingContent string - expectExists bool - }{ - { - name: "reports missing file without error", - existingContent: "", - expectExists: false, - }, - { - name: "reports existing file", - existingContent: "# Test content", - expectExists: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Create a temporary directory for testing - tempDir := testutil.TempDir(t, "test-*") - - // Change to temp directory and initialize git repo for findGitRoot to work - oldWd, _ := os.Getwd() - defer func() { - _ = os.Chdir(oldWd) - }() - err := os.Chdir(tempDir) - if err != nil { - t.Fatalf("Failed to change directory: %v", err) - } - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatalf("Failed to init git repo: %v", err) - } - - copilotDir := filepath.Join(tempDir, ".github", "aw") - copilotInstructionsPath := filepath.Join(copilotDir, "github-agentic-workflows.md") - - // Create initial content if specified - if tt.existingContent != "" { - if err := os.MkdirAll(copilotDir, 0755); err != nil { - t.Fatalf("Failed to create copilot directory: %v", err) - } - if err := os.WriteFile(copilotInstructionsPath, []byte(tt.existingContent), 0644); err != nil { - t.Fatalf("Failed to create initial copilot instructions: %v", err) - } - } - - // Call the function with skipInstructions=false to test the functionality - err = ensureCopilotInstructions(false, false) - if err != nil { - t.Fatalf("ensureCopilotInstructions() returned error: %v", err) - } - - // Check that file exists or not based on test expectation - _, statErr := os.Stat(copilotInstructionsPath) - fileExists := statErr == nil - - if fileExists != tt.expectExists { - if tt.expectExists { - t.Errorf("Expected copilot instructions file to exist, but it doesn't") - } else { - t.Errorf("Expected copilot instructions file to not exist, but it does") - } - } - }) - } -} - -func TestEnsureCopilotInstructions_WithSkipInstructionsTrue(t *testing.T) { - // Create a temporary directory for testing - tempDir := testutil.TempDir(t, "test-*") - - // Change to temp directory and initialize git repo for findGitRoot to work - oldWd, _ := os.Getwd() - defer func() { - _ = os.Chdir(oldWd) - }() - err := os.Chdir(tempDir) - if err != nil { - t.Fatalf("Failed to change directory: %v", err) - } - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatalf("Failed to init git repo: %v", err) - } - - copilotDir := filepath.Join(tempDir, ".github", "aw") - copilotInstructionsPath := filepath.Join(copilotDir, "github-agentic-workflows.md") - - // Call the function with skipInstructions=true - err = ensureCopilotInstructions(false, true) - if err != nil { - t.Fatalf("ensureCopilotInstructions() returned error: %v", err) - } - - // Check that file does not exist (no file created when skipInstructions=true) - if _, err := os.Stat(copilotInstructionsPath); !os.IsNotExist(err) { - t.Fatalf("Expected copilot instructions file to not exist when skipInstructions=true") - } -} - -func TestEnsureCopilotInstructions_CleansUpOldFile(t *testing.T) { - // Create a temporary directory for testing - tempDir := testutil.TempDir(t, "test-*") - - // Change to temp directory and initialize git repo for findGitRoot to work - oldWd, _ := os.Getwd() - defer func() { - _ = os.Chdir(oldWd) - }() - err := os.Chdir(tempDir) - if err != nil { - t.Fatalf("Failed to change directory: %v", err) - } - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatalf("Failed to init git repo: %v", err) - } - - // Create the old file location - oldDir := filepath.Join(tempDir, ".github", "instructions") - oldPath := filepath.Join(oldDir, "github-agentic-workflows.instructions.md") - if err := os.MkdirAll(oldDir, 0755); err != nil { - t.Fatalf("Failed to create old directory: %v", err) - } - if err := os.WriteFile(oldPath, []byte("old content"), 0644); err != nil { - t.Fatalf("Failed to create old file: %v", err) - } - - // Verify old file exists - if _, err := os.Stat(oldPath); os.IsNotExist(err) { - t.Fatalf("Old file should exist before running ensureCopilotInstructions") - } - - // Call the function - err = ensureCopilotInstructions(false, false) - if err != nil { - t.Fatalf("ensureCopilotInstructions() returned error: %v", err) - } - - // Verify old file was removed - if _, err := os.Stat(oldPath); !os.IsNotExist(err) { - t.Errorf("Old file should be removed after ensureCopilotInstructions") - } - - // New file should not be created by ensureCopilotInstructions anymore - // (files in .github/aw are source of truth, not created by init) - newPath := filepath.Join(tempDir, ".github", "aw", "github-agentic-workflows.md") - if _, err := os.Stat(newPath); !os.IsNotExist(err) { - t.Errorf("New file should not be created by ensureCopilotInstructions (files are source of truth)") - } -} diff --git a/pkg/cli/fix_command.go b/pkg/cli/fix_command.go index 225a328ed9..274447bfd3 100644 --- a/pkg/cli/fix_command.go +++ b/pkg/cli/fix_command.go @@ -187,54 +187,12 @@ func runFixCommand(workflowIDs []string, write bool, verbose bool, workflowDir s // This ensures the latest templates are always used fixLog.Print("Updating prompt and agent files") - // Update copilot instructions - if err := ensureCopilotInstructions(verbose, false); err != nil { - fixLog.Printf("Failed to update copilot instructions: %v", err) - fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to update copilot instructions: %v", err))) - } - // Update dispatcher agent if err := ensureAgenticWorkflowsDispatcher(verbose, false); err != nil { fixLog.Printf("Failed to update dispatcher agent: %v", err) fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to update dispatcher agent: %v", err))) } - // Update create workflow prompt - if err := ensureCreateWorkflowPrompt(verbose, false); err != nil { - fixLog.Printf("Failed to update create workflow prompt: %v", err) - fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to update workflow creation prompt: %v", err))) - } - - // Update update workflow prompt - if err := ensureUpdateWorkflowPrompt(verbose, false); err != nil { - fixLog.Printf("Failed to update update workflow prompt: %v", err) - fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to update workflow update prompt: %v", err))) - } - - // Update create shared agentic workflow prompt - if err := ensureCreateSharedAgenticWorkflowPrompt(verbose, false); err != nil { - fixLog.Printf("Failed to update create shared workflow prompt: %v", err) - fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to update shared workflow creation prompt: %v", err))) - } - - // Update debug workflow prompt - if err := ensureDebugWorkflowPrompt(verbose, false); err != nil { - fixLog.Printf("Failed to update debug workflow prompt: %v", err) - fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to update debug workflow prompt: %v", err))) - } - - // Update upgrade agentic workflows prompt - if err := ensureUpgradeAgenticWorkflowsPrompt(verbose, false); err != nil { - fixLog.Printf("Failed to update upgrade workflows prompt: %v", err) - fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to update upgrade workflow prompt: %v", err))) - } - - // Update Serena tool documentation - if err := ensureSerenaTool(verbose, false); err != nil { - fixLog.Printf("Failed to update Serena tool documentation: %v", err) - fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to update Serena tool documentation: %v", err))) - } - // Delete old template files from pkg/cli/templates/ (only with --write) if write { fixLog.Print("Cleaning up old template files") diff --git a/pkg/cli/init.go b/pkg/cli/init.go index 4289981820..99cee3ef6e 100644 --- a/pkg/cli/init.go +++ b/pkg/cli/init.go @@ -159,16 +159,6 @@ func initializeBasicRepository(verbose bool) error { fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Configured .gitattributes")) } - // Write copilot instructions - initLog.Print("Writing GitHub Copilot instructions") - if err := ensureCopilotInstructions(verbose, false); err != nil { - initLog.Printf("Failed to write copilot instructions: %v", err) - return fmt.Errorf("failed to write copilot instructions: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created GitHub Copilot instructions")) - } - // Write dispatcher agent initLog.Print("Writing agentic workflows dispatcher agent") if err := ensureAgenticWorkflowsDispatcher(verbose, false); err != nil { @@ -179,36 +169,6 @@ func initializeBasicRepository(verbose bool) error { fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created dispatcher agent")) } - // Write create workflow prompt - initLog.Print("Writing create workflow prompt") - if err := ensureCreateWorkflowPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write create workflow prompt: %v", err) - return fmt.Errorf("failed to write create workflow prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created create workflow prompt")) - } - - // Write update workflow prompt - initLog.Print("Writing update workflow prompt") - if err := ensureUpdateWorkflowPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write update workflow prompt: %v", err) - return fmt.Errorf("failed to write update workflow prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created update workflow prompt")) - } - - // Write create shared agentic workflow prompt - initLog.Print("Writing create shared agentic workflow prompt") - if err := ensureCreateSharedAgenticWorkflowPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write create shared workflow prompt: %v", err) - return fmt.Errorf("failed to write create shared workflow prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created shared workflow creation prompt")) - } - // Delete existing setup agentic workflows agent if it exists initLog.Print("Cleaning up setup agentic workflows agent") if err := deleteSetupAgenticWorkflowsAgent(verbose); err != nil { @@ -216,36 +176,6 @@ func initializeBasicRepository(verbose bool) error { return fmt.Errorf("failed to delete setup agentic workflows agent: %w", err) } - // Write debug workflow prompt - initLog.Print("Writing debug workflow prompt") - if err := ensureDebugWorkflowPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write debug workflow prompt: %v", err) - return fmt.Errorf("failed to write debug workflow prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created debug workflow prompt")) - } - - // Write upgrade agentic workflows prompt - initLog.Print("Writing upgrade agentic workflows prompt") - if err := ensureUpgradeAgenticWorkflowsPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write upgrade workflows prompt: %v", err) - return fmt.Errorf("failed to write upgrade workflows prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created upgrade workflows prompt")) - } - - // Write Serena tool documentation - initLog.Print("Writing Serena tool documentation") - if err := ensureSerenaTool(verbose, false); err != nil { - initLog.Printf("Failed to write Serena tool documentation: %v", err) - return fmt.Errorf("failed to write Serena tool documentation: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created Serena tool documentation")) - } - return nil } @@ -477,16 +407,6 @@ func InitRepository(verbose bool, mcp bool, tokens bool, engine string, codespac fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Configured .gitattributes")) } - // Write copilot instructions - initLog.Print("Writing GitHub Copilot instructions") - if err := ensureCopilotInstructions(verbose, false); err != nil { - initLog.Printf("Failed to write copilot instructions: %v", err) - return fmt.Errorf("failed to write copilot instructions: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created GitHub Copilot instructions")) - } - // Write dispatcher agent initLog.Print("Writing agentic workflows dispatcher agent") if err := ensureAgenticWorkflowsDispatcher(verbose, false); err != nil { @@ -497,36 +417,6 @@ func InitRepository(verbose bool, mcp bool, tokens bool, engine string, codespac fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created dispatcher agent")) } - // Write create workflow prompt - initLog.Print("Writing create workflow prompt") - if err := ensureCreateWorkflowPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write create workflow prompt: %v", err) - return fmt.Errorf("failed to write create workflow prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created create workflow prompt")) - } - - // Write update workflow prompt (new) - initLog.Print("Writing update workflow prompt") - if err := ensureUpdateWorkflowPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write update workflow prompt: %v", err) - return fmt.Errorf("failed to write update workflow prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created update workflow prompt")) - } - - // Write create shared agentic workflow prompt - initLog.Print("Writing create shared agentic workflow prompt") - if err := ensureCreateSharedAgenticWorkflowPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write create shared workflow prompt: %v", err) - return fmt.Errorf("failed to write create shared workflow prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created shared workflow creation prompt")) - } - // Delete existing setup agentic workflows agent if it exists initLog.Print("Cleaning up setup agentic workflows agent") if err := deleteSetupAgenticWorkflowsAgent(verbose); err != nil { @@ -534,36 +424,6 @@ func InitRepository(verbose bool, mcp bool, tokens bool, engine string, codespac return fmt.Errorf("failed to delete setup agentic workflows agent: %w", err) } - // Write debug workflow prompt - initLog.Print("Writing debug workflow prompt") - if err := ensureDebugWorkflowPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write debug workflow prompt: %v", err) - return fmt.Errorf("failed to write debug workflow prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created debug workflow prompt")) - } - - // Write upgrade agentic workflows prompt - initLog.Print("Writing upgrade agentic workflows prompt") - if err := ensureUpgradeAgenticWorkflowsPrompt(verbose, false); err != nil { - initLog.Printf("Failed to write upgrade workflows prompt: %v", err) - return fmt.Errorf("failed to write upgrade workflows prompt: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created upgrade workflows prompt")) - } - - // Write Serena tool documentation - initLog.Print("Writing Serena tool documentation") - if err := ensureSerenaTool(verbose, false); err != nil { - initLog.Printf("Failed to write Serena tool documentation: %v", err) - return fmt.Errorf("failed to write Serena tool documentation: %w", err) - } - if verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created Serena tool documentation")) - } - // Configure MCP if requested if mcp { initLog.Print("Configuring GitHub Copilot Agent MCP integration") diff --git a/pkg/cli/init_command.go b/pkg/cli/init_command.go index 07e59ebdb7..3d774ce3aa 100644 --- a/pkg/cli/init_command.go +++ b/pkg/cli/init_command.go @@ -28,13 +28,8 @@ Interactive Mode (default): This command: - Configures .gitattributes to mark .lock.yml files as generated -- Creates GitHub Copilot custom instructions at .github/aw/github-agentic-workflows.md - Creates the dispatcher agent at .github/agents/agentic-workflows.agent.md -- Creates workflow creation prompt at .github/aw/create-agentic-workflow.md (for new workflows) -- Creates workflow update prompt at .github/aw/update-agentic-workflow.md (for updating existing workflows) -- Creates shared workflow creation prompt at .github/aw/create-shared-agentic-workflow.md -- Creates debug workflow prompt at .github/aw/debug-agentic-workflow.md -- Creates upgrade workflow prompt at .github/aw/upgrade-agentic-workflows.md +- Verifies workflow prompt files exist in .github/aw/ (create-agentic-workflow.md, update-agentic-workflow.md, etc.) - Removes old prompt files from .github/prompts/ if they exist - Configures VSCode settings (.vscode/settings.json) - Generates/updates .github/workflows/agentics-maintenance.yml if any workflows use expires field for discussions or issues diff --git a/pkg/cli/upgrade_agentic_workflow_agent_test.go b/pkg/cli/upgrade_agentic_workflow_agent_test.go deleted file mode 100644 index e7a206ddd0..0000000000 --- a/pkg/cli/upgrade_agentic_workflow_agent_test.go +++ /dev/null @@ -1,117 +0,0 @@ -//go:build !integration - -package cli - -import ( - "os" - "os/exec" - "path/filepath" - "testing" - - "github.com/github/gh-aw/pkg/testutil" -) - -func TestEnsureUpgradeAgenticWorkflowsPrompt(t *testing.T) { - tests := []struct { - name string - existingContent string - expectExists bool - }{ - { - name: "reports missing file without error", - existingContent: "", - expectExists: false, - }, - { - name: "reports existing file", - existingContent: "# Test content", - expectExists: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Create a temporary directory for testing - tempDir := testutil.TempDir(t, "test-*") - - // Change to temp directory and initialize git repo for findGitRoot to work - oldWd, _ := os.Getwd() - defer func() { - _ = os.Chdir(oldWd) - }() - err := os.Chdir(tempDir) - if err != nil { - t.Fatalf("Failed to change directory: %v", err) - } - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatalf("Failed to init git repo: %v", err) - } - - awDir := filepath.Join(tempDir, ".github", "aw") - promptPath := filepath.Join(awDir, "upgrade-agentic-workflows.md") - - // Create initial content if specified - if tt.existingContent != "" { - if err := os.MkdirAll(awDir, 0755); err != nil { - t.Fatalf("Failed to create aw directory: %v", err) - } - if err := os.WriteFile(promptPath, []byte(tt.existingContent), 0644); err != nil { - t.Fatalf("Failed to create initial prompt: %v", err) - } - } - - // Call the function with skipInstructions=false to test the functionality - err = ensureUpgradeAgenticWorkflowsPrompt(false, false) - if err != nil { - t.Fatalf("ensureUpgradeAgenticWorkflowsPrompt() returned error: %v", err) - } - - // Check that file exists or not based on test expectation - _, statErr := os.Stat(promptPath) - fileExists := statErr == nil - - if fileExists != tt.expectExists { - if tt.expectExists { - t.Errorf("Expected prompt file to exist, but it doesn't") - } else { - t.Errorf("Expected prompt file to not exist, but it does") - } - } - }) - } -} - -func TestEnsureUpgradeAgenticWorkflowAgent_WithSkipInstructionsTrue(t *testing.T) { - // Create a temporary directory for testing - tempDir := testutil.TempDir(t, "test-*") - - // Change to temp directory and initialize git repo for findGitRoot to work - oldWd, _ := os.Getwd() - defer func() { - _ = os.Chdir(oldWd) - }() - err := os.Chdir(tempDir) - if err != nil { - t.Fatalf("Failed to change directory: %v", err) - } - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatalf("Failed to init git repo: %v", err) - } - - // Call the function with skipInstructions=true - err = ensureUpgradeAgenticWorkflowsPrompt(false, true) - if err != nil { - t.Fatalf("ensureUpgradeAgenticWorkflowsPrompt() returned error: %v", err) - } - - // Check that file was NOT created - awDir := filepath.Join(tempDir, ".github", "aw") - upgradePromptPath := filepath.Join(awDir, "upgrade-agentic-workflows.md") - if _, err := os.Stat(upgradePromptPath); !os.IsNotExist(err) { - t.Fatalf("Expected upgrade prompt file to NOT exist when skipInstructions=true") - } -} diff --git a/pkg/cli/upgrade_command.go b/pkg/cli/upgrade_command.go index c9ea54b792..c452ed4b0c 100644 --- a/pkg/cli/upgrade_command.go +++ b/pkg/cli/upgrade_command.go @@ -41,9 +41,8 @@ This command: 4. Compiles all workflows to generate lock files (like 'compile' command) The upgrade process ensures: -- GitHub Copilot instructions are up-to-date (.github/aw/github-agentic-workflows.md) - Dispatcher agent is current (.github/agents/agentic-workflows.agent.md) -- All workflow prompts are updated (create, update, debug, upgrade) +- All workflow prompts exist in .github/aw/ (create, update, debug, upgrade) - All workflows use the latest syntax and configuration options - Deprecated fields are automatically migrated across all workflows - GitHub Actions are pinned to the latest versions @@ -258,54 +257,12 @@ func runUpgradeCommand(verbose bool, workflowDir string, noFix bool, noCompile b // updateAgentFiles updates all agent and prompt files to the latest templates func updateAgentFiles(verbose bool) error { - // Update copilot instructions - if err := ensureCopilotInstructions(verbose, false); err != nil { - upgradeLog.Printf("Failed to update copilot instructions: %v", err) - return fmt.Errorf("failed to update copilot instructions: %w", err) - } - // Update dispatcher agent if err := ensureAgenticWorkflowsDispatcher(verbose, false); err != nil { upgradeLog.Printf("Failed to update dispatcher agent: %v", err) return fmt.Errorf("failed to update dispatcher agent: %w", err) } - // Update create workflow prompt - if err := ensureCreateWorkflowPrompt(verbose, false); err != nil { - upgradeLog.Printf("Failed to update create workflow prompt: %v", err) - return fmt.Errorf("failed to update create workflow prompt: %w", err) - } - - // Update update workflow prompt - if err := ensureUpdateWorkflowPrompt(verbose, false); err != nil { - upgradeLog.Printf("Failed to update update workflow prompt: %v", err) - return fmt.Errorf("failed to update update workflow prompt: %w", err) - } - - // Update create shared agentic workflow prompt - if err := ensureCreateSharedAgenticWorkflowPrompt(verbose, false); err != nil { - upgradeLog.Printf("Failed to update create shared workflow prompt: %v", err) - return fmt.Errorf("failed to update create shared workflow prompt: %w", err) - } - - // Update debug workflow prompt - if err := ensureDebugWorkflowPrompt(verbose, false); err != nil { - upgradeLog.Printf("Failed to update debug workflow prompt: %v", err) - return fmt.Errorf("failed to update debug workflow prompt: %w", err) - } - - // Update upgrade agentic workflows prompt - if err := ensureUpgradeAgenticWorkflowsPrompt(verbose, false); err != nil { - upgradeLog.Printf("Failed to update upgrade workflows prompt: %v", err) - return fmt.Errorf("failed to update upgrade workflows prompt: %w", err) - } - - // Update Serena tool documentation - if err := ensureSerenaTool(verbose, false); err != nil { - upgradeLog.Printf("Failed to update Serena tool documentation: %v", err) - return fmt.Errorf("failed to update Serena tool documentation: %w", err) - } - // Upgrade copilot-setup-steps.yml version actionMode := workflow.DetectActionMode(GetVersion()) if err := upgradeCopilotSetupSteps(verbose, actionMode, GetVersion()); err != nil { diff --git a/pkg/cli/upgrade_command_test.go b/pkg/cli/upgrade_command_test.go index 626ed5208d..c6a17e2345 100644 --- a/pkg/cli/upgrade_command_test.go +++ b/pkg/cli/upgrade_command_test.go @@ -436,12 +436,6 @@ This workflow is already up to date. exec.Command("git", "add", ".").Run() exec.Command("git", "commit", "-m", "Initial commit").Run() - // Create all the agent files to ensure no changes will be made - if err := ensureCopilotInstructions(false, false); err == nil { - exec.Command("git", "add", ".").Run() - exec.Command("git", "commit", "-m", "Add agent files").Run() - } - // Run upgrade command with --push (should fail because no remote is configured) config := UpgradeConfig{ Verbose: false,