Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
11 changes: 6 additions & 5 deletions pkg/cli/copilot-agents.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path/filepath"
"strings"

"github.com/githubnext/gh-aw/pkg/console"
"github.com/githubnext/gh-aw/pkg/logger"
)

Expand Down Expand Up @@ -44,7 +45,7 @@ func ensureFileMatchesTemplate(subdir, fileName, templateContent, fileType strin
if strings.TrimSpace(existingContent) == expectedContent {
copilotAgentsLog.Printf("File is up-to-date: %s", targetPath)
if verbose {
fmt.Printf("%s is up-to-date: %s\n", fileType, targetPath)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("%s is up-to-date: %s", fileType, targetPath)))
}
return nil
}
Expand All @@ -64,9 +65,9 @@ func ensureFileMatchesTemplate(subdir, fileName, templateContent, fileType strin

if verbose {
if existingContent == "" {
fmt.Printf("Created %s: %s\n", fileType, targetPath)
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Created %s: %s", fileType, targetPath)))
} else {
fmt.Printf("Updated %s: %s\n", fileType, targetPath)
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Updated %s: %s", fileType, targetPath)))
}
}

Expand Down Expand Up @@ -100,7 +101,7 @@ func cleanupOldPromptFile(promptFileName string, verbose bool) error {
return fmt.Errorf("failed to remove old prompt file: %w", err)
}
if verbose {
fmt.Printf("Removed old prompt file: %s\n", oldPath)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Removed old prompt file: %s", oldPath)))
}
}

Expand Down Expand Up @@ -139,7 +140,7 @@ func cleanupOldCopilotInstructions(verbose bool) error {
return fmt.Errorf("failed to remove old instructions file: %w", err)
}
if verbose {
fmt.Printf("Removed old instructions file: %s\n", oldPath)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Removed old instructions file: %s", oldPath)))
}
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/cli/mcp_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,11 @@ func AddMCPTool(workflowFile string, mcpServerID string, registryURL string, tra
// Security fix for CWE-312, CWE-315, CWE-359: Avoid logging detailed error messages
// that could contain sensitive information from secret references
mcpAddLog.Print("Workflow compilation failed")
fmt.Println(console.FormatWarningMessage("Workflow compilation failed. Please check your workflow configuration."))
fmt.Println(console.FormatInfoMessage("You can fix the issues and run 'gh aw compile' manually"))
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("Workflow compilation failed. Please check your workflow configuration."))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("You can fix the issues and run 'gh aw compile' manually"))
} else {
mcpAddLog.Print("Workflow compiled successfully")
fmt.Println(console.FormatSuccessMessage("Workflow compiled successfully"))
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Workflow compiled successfully"))
}

return nil
Expand Down
6 changes: 3 additions & 3 deletions pkg/cli/mcp_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ func spawnMCPInspector(workflowFile string, serverFilter string, verbose bool) e
} else {
// Direct command mode
if config.Command == "" {
fmt.Println(console.FormatWarningMessage(fmt.Sprintf("Skipping server %s: no command specified", config.Name)))
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Skipping server %s: no command specified", config.Name)))
continue
}
cmd = exec.Command(config.Command, config.Args...)
Expand All @@ -837,7 +837,7 @@ func spawnMCPInspector(workflowFile string, serverFilter string, verbose bool) e
go func(serverCmd *exec.Cmd, serverName string) {
defer wg.Done()
if err := serverCmd.Wait(); err != nil && verbose {
fmt.Println(console.FormatWarningMessage(fmt.Sprintf("Server %s exited with error: %v", serverName, err)))
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Server %s exited with error: %v", serverName, err)))
}
}(cmd, config.Name)

Expand All @@ -851,7 +851,7 @@ func spawnMCPInspector(workflowFile string, serverFilter string, verbose bool) e
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("All stdio servers started successfully"))
}

fmt.Println(console.FormatInfoMessage("Configuration details for MCP inspector:"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Configuration details for MCP inspector:"))
for _, config := range mcpConfigs {
fmt.Fprintf(os.Stderr, "\n📡 %s (%s):\n", config.Name, config.Type)
switch config.Type {
Expand Down
7 changes: 3 additions & 4 deletions pkg/cli/mcp_list_tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,9 @@ func ListToolsForMCP(workflowFile string, mcpServerName string, verbose bool) er
}

// Connect to the MCP server and get its tools
fmt.Printf("%s %s (%s)\n",
console.FormatInfoMessage("📡 Connecting to MCP server:"),
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("📡 Connecting to MCP server: %s (%s)",
targetConfig.Name,
targetConfig.Type)
targetConfig.Type)))

info, err := connectToMCPServer(*targetConfig, verbose)
if err != nil {
Expand Down Expand Up @@ -140,7 +139,7 @@ func displayToolsList(info *parser.MCPServerInfo, verbose bool) {
return
}

fmt.Printf("\n%s\n", console.FormatInfoMessage(fmt.Sprintf("🛠️ Available Tools (%d total)", len(info.Tools))))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("\n🛠️ Available Tools (%d total)", len(info.Tools))))

// Configure options based on verbose flag
opts := MCPToolTableOptions{
Expand Down
13 changes: 7 additions & 6 deletions pkg/cli/mcp_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"fmt"
"os"
"strings"

"github.com/githubnext/gh-aw/pkg/console"
Expand Down Expand Up @@ -36,7 +37,7 @@ func checkAndSuggestSecrets(toolConfig map[string]any, verbose bool) error {
mcpSecretsLog.Printf("Found %d required secrets in configuration", len(requiredSecrets))

if verbose {
fmt.Println(console.FormatInfoMessage("Checking repository secrets..."))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Checking repository secrets..."))
}

// Check each secret using GitHub CLI
Expand All @@ -47,7 +48,7 @@ func checkAndSuggestSecrets(toolConfig map[string]any, verbose bool) error {
// If we get a 403 error, ignore it as requested
if strings.Contains(err.Error(), "403") {
if verbose {
fmt.Println(console.FormatWarningMessage("Repository secrets check skipped (insufficient permissions)"))
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("Repository secrets check skipped (insufficient permissions)"))
}
return nil
}
Expand All @@ -62,14 +63,14 @@ func checkAndSuggestSecrets(toolConfig map[string]any, verbose bool) error {
// Suggest CLI commands for missing secrets
if len(missingSecrets) > 0 {
mcpSecretsLog.Printf("Found %d missing secrets", len(missingSecrets))
fmt.Println(console.FormatWarningMessage("The following secrets are required but not found in the repository:"))
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("The following secrets are required but not found in the repository:"))
for _, secretName := range missingSecrets {
fmt.Println(console.FormatInfoMessage(fmt.Sprintf("To add %s secret:", secretName)))
fmt.Println(console.FormatCommandMessage(fmt.Sprintf("gh secret set %s", secretName)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("To add %s secret:", secretName)))
fmt.Fprintln(os.Stderr, console.FormatCommandMessage(fmt.Sprintf("gh secret set %s", secretName)))
}
} else if verbose {
mcpSecretsLog.Print("All required secrets are available in repository")
fmt.Println(console.FormatSuccessMessage("All required secrets are available in the repository"))
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("All required secrets are available in the repository"))
}

return nil
Expand Down
56 changes: 28 additions & 28 deletions pkg/cli/remove_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func RemoveWorkflows(pattern string, keepOrphans bool) error {
workflowsDir := getWorkflowsDir()

if _, err := os.Stat(workflowsDir); os.IsNotExist(err) {
fmt.Println("No .github/workflows directory found.")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("No .github/workflows directory found."))
return nil
}

Expand All @@ -38,26 +38,26 @@ func RemoveWorkflows(pattern string, keepOrphans bool) error {

removeLog.Printf("Found %d workflow files", len(mdFiles))
if len(mdFiles) == 0 {
fmt.Println("No workflow files found to remove.")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("No workflow files found to remove."))
return nil
}

var filesToRemove []string

// If no pattern specified, list all files for user to see
if pattern == "" {
fmt.Println("Available workflows to remove:")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Available workflows to remove:"))
for _, file := range mdFiles {
workflowName, _ := extractWorkflowNameFromFile(file)
base := filepath.Base(file)
name := strings.TrimSuffix(base, ".md")
if workflowName != "" {
fmt.Printf(" %-20s - %s\n", name, workflowName)
fmt.Fprintf(os.Stderr, " %-20s - %s\n", name, workflowName)
} else {
fmt.Printf(" %s\n", name)
fmt.Fprintf(os.Stderr, " %s\n", name)
}
}
fmt.Println("\nUsage: " + string(constants.CLIExtensionPrefix) + " remove <pattern>")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("\nUsage: %s remove <pattern>", string(constants.CLIExtensionPrefix))))
return nil
}

Expand All @@ -76,7 +76,7 @@ func RemoveWorkflows(pattern string, keepOrphans bool) error {

if len(filesToRemove) == 0 {
removeLog.Printf("No workflows matched pattern: %q", pattern)
fmt.Printf("No workflows found matching pattern: %s\n", pattern)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("No workflows found matching pattern: %s", pattern)))
return nil
}

Expand All @@ -88,33 +88,33 @@ func RemoveWorkflows(pattern string, keepOrphans bool) error {
var err error
orphanedIncludes, err = previewOrphanedIncludes(filesToRemove, false)
if err != nil {
fmt.Printf("Warning: Failed to preview orphaned includes: %v\n", err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to preview orphaned includes: %v", err)))
orphanedIncludes = []string{} // Continue with empty list
}
}

// Show what will be removed
fmt.Printf("The following workflows will be removed:\n")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("The following workflows will be removed:"))
for _, file := range filesToRemove {
workflowName, _ := extractWorkflowNameFromFile(file)
if workflowName != "" {
fmt.Printf(" %s - %s\n", filepath.Base(file), workflowName)
fmt.Fprintf(os.Stderr, " %s - %s\n", filepath.Base(file), workflowName)
} else {
fmt.Printf(" %s\n", filepath.Base(file))
fmt.Fprintf(os.Stderr, " %s\n", filepath.Base(file))
}

// Also check for corresponding .lock.yml file in .github/workflows
lockFile := stringutil.MarkdownToLockFile(file)
if _, err := os.Stat(lockFile); err == nil {
fmt.Printf(" %s (compiled workflow)\n", filepath.Base(lockFile))
fmt.Fprintf(os.Stderr, " %s (compiled workflow)\n", filepath.Base(lockFile))
}
}

// Show orphaned includes that will also be removed
if len(orphanedIncludes) > 0 {
fmt.Printf("\nThe following orphaned include files will also be removed (suppress with --keep-orphans):\n")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("\nThe following orphaned include files will also be removed (suppress with --keep-orphans):"))
for _, include := range orphanedIncludes {
fmt.Printf(" %s (orphaned include)\n", include)
fmt.Fprintf(os.Stderr, " %s (orphaned include)\n", include)
}
}

Expand All @@ -136,27 +136,27 @@ func RemoveWorkflows(pattern string, keepOrphans bool) error {
var removedFiles []string
for _, file := range filesToRemove {
if err := os.Remove(file); err != nil {
fmt.Println(console.FormatWarningMessage(fmt.Sprintf("Failed to remove %s: %v", file, err)))
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to remove %s: %v", file, err)))
} else {
fmt.Println(console.FormatSuccessMessage(fmt.Sprintf("Removed: %s", filepath.Base(file))))
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Removed: %s", filepath.Base(file))))
removedFiles = append(removedFiles, file)
}

// Also remove corresponding .lock.yml file
lockFile := stringutil.MarkdownToLockFile(file)
if _, err := os.Stat(lockFile); err == nil {
if err := os.Remove(lockFile); err != nil {
fmt.Printf("Warning: Failed to remove %s: %v\n", lockFile, err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to remove %s: %v", lockFile, err)))
} else {
fmt.Printf("Removed: %s\n", filepath.Base(lockFile))
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Removed: %s", filepath.Base(lockFile))))
}
}
}

// Clean up orphaned include files (if orphan removal is enabled)
if len(removedFiles) > 0 && !keepOrphans {
if err := cleanupOrphanedIncludes(false); err != nil {
fmt.Printf("Warning: Failed to clean up orphaned includes: %v\n", err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to clean up orphaned includes: %v", err)))
}
}

Expand All @@ -177,7 +177,7 @@ func cleanupOrphanedIncludes(verbose bool) error {
// No markdown files means we can clean up all includes
removeLog.Print("No markdown files found, cleaning up all includes")
if verbose {
fmt.Printf("No markdown files found, cleaning up all includes\n")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("No markdown files found, cleaning up all includes"))
}
return cleanupAllIncludes(verbose)
}
Expand All @@ -189,7 +189,7 @@ func cleanupOrphanedIncludes(verbose bool) error {
content, err := os.ReadFile(mdFile)
if err != nil {
if verbose {
fmt.Printf("Warning: Could not read %s for include analysis: %v\n", mdFile, err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Could not read %s for include analysis: %v", mdFile, err)))
}
continue
}
Expand All @@ -198,7 +198,7 @@ func cleanupOrphanedIncludes(verbose bool) error {
includes, err := findIncludesInContent(string(content), filepath.Dir(mdFile), verbose)
if err != nil {
if verbose {
fmt.Printf("Warning: Could not analyze includes in %s: %v\n", mdFile, err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Could not analyze includes in %s: %v", mdFile, err)))
}
continue
}
Expand Down Expand Up @@ -245,10 +245,10 @@ func cleanupOrphanedIncludes(verbose bool) error {
includePath := filepath.Join(workflowsDir, include)
if err := os.Remove(includePath); err != nil {
if verbose {
fmt.Printf("Warning: Failed to remove orphaned include %s: %v\n", include, err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to remove orphaned include %s: %v", include, err)))
}
} else {
fmt.Printf("Removed orphaned include: %s\n", include)
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Removed orphaned include: %s", include)))
}
}
}
Expand Down Expand Up @@ -290,7 +290,7 @@ func previewOrphanedIncludes(filesToRemove []string, verbose bool) ([]string, er
content, err := os.ReadFile(mdFile)
if err != nil {
if verbose {
fmt.Printf("Warning: Could not read %s for include analysis: %v\n", mdFile, err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Could not read %s for include analysis: %v", mdFile, err)))
}
continue
}
Expand All @@ -299,7 +299,7 @@ func previewOrphanedIncludes(filesToRemove []string, verbose bool) ([]string, er
includes, err := findIncludesInContent(string(content), filepath.Dir(mdFile), verbose)
if err != nil {
if verbose {
fmt.Printf("Warning: Could not analyze includes in %s: %v\n", mdFile, err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Could not analyze includes in %s: %v", mdFile, err)))
}
continue
}
Expand Down Expand Up @@ -371,10 +371,10 @@ func cleanupAllIncludes(verbose bool) error {
if strings.Contains(relPath, string(filepath.Separator)) {
if err := os.Remove(path); err != nil {
if verbose {
fmt.Printf("Warning: Failed to remove include %s: %v\n", relPath, err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to remove include %s: %v", relPath, err)))
}
} else {
fmt.Printf("Removed include: %s\n", relPath)
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Removed include: %s", relPath)))
}
}
}
Expand Down
Loading
Loading