Skip to content
Closed
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
8 changes: 4 additions & 4 deletions pkg/cli/actionlint.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ func displayActionlintSummary() {
// Create visual separator
separator := strings.Repeat("━", 60)

fmt.Fprintf(os.Stderr, "\n%s\n", separator)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("\n"+separator))
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessage("Actionlint Summary"))
fmt.Fprintf(os.Stderr, "%s\n\n", separator)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(separator+"\n"))
Comment on lines +97 to +99

// Show total workflows checked
fmt.Fprintf(os.Stderr, "%s\n",
Expand All @@ -119,7 +119,7 @@ func displayActionlintSummary() {
if len(actionlintStats.ErrorsByKind) > 0 {
fmt.Fprintf(os.Stderr, "\n%s\n", console.FormatInfoMessage("Issues by type:"))
for kind, count := range actionlintStats.ErrorsByKind {
fmt.Fprintf(os.Stderr, " • %s: %d\n", kind, count)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" • %s: %d", kind, count)))
}
}
} else if actionlintStats.IntegrationErrors > 0 {
Expand All @@ -141,7 +141,7 @@ func displayActionlintSummary() {
fmt.Fprintf(os.Stderr, "\n%s\n", console.FormatWarningMessage(msg))
}

fmt.Fprintf(os.Stderr, "\n%s\n", separator)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("\n"+separator))
}

// getActionlintVersion fetches and caches the actionlint version from Docker
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/add_interactive_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (c *AddInteractiveConfig) selectAIEngineAndKey() error {

// If engine is already overridden, skip selection
if c.EngineOverride != "" {
fmt.Fprintf(os.Stderr, "Using coding agent: %s\n", c.EngineOverride)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Using coding agent: "+c.EngineOverride))
return c.configureEngineAPISecret(c.EngineOverride)
}

Expand Down
12 changes: 6 additions & 6 deletions pkg/cli/add_interactive_git.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (c *AddInteractiveConfig) createWorkflowPRAndConfigureSecret(ctx context.Co
// Step 8b: Optionally merge the PR – loop until merged, confirmed-merged, or user exits
if result.PRNumber == 0 {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("Could not determine PR number"))
fmt.Fprintln(os.Stderr, "Please merge the PR manually from the GitHub web interface.")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Please merge the PR manually from the GitHub web interface."))
} else {
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Pull request created: "+result.PRURL))
fmt.Fprintln(os.Stderr, "")
Expand Down Expand Up @@ -177,9 +177,9 @@ func (c *AddInteractiveConfig) createWorkflowPRAndConfigureSecret(ctx context.Co
if err := c.addRepositorySecret(secretName, secretValue); err != nil {
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(fmt.Sprintf("Failed to add secret: %v", err)))
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "Please add the secret manually:")
fmt.Fprintln(os.Stderr, " 1. Go to your repository Settings → Secrets and variables → Actions")
fmt.Fprintf(os.Stderr, " 2. Click 'New repository secret' and add '%s'\n", secretName)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Please add the secret manually:"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(" 1. Go to your repository Settings → Secrets and variables → Actions"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" 2. Click 'New repository secret' and add '%s'", secretName)))
return fmt.Errorf("failed to add secret: %w", err)
}

Expand Down Expand Up @@ -266,8 +266,8 @@ func (c *AddInteractiveConfig) checkCleanWorkingDirectory() error {
if err := checkCleanWorkingDirectory(c.Verbose); err != nil {
fmt.Fprintln(os.Stderr, console.FormatErrorMessage("Working directory is not clean."))
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "The add wizard creates a pull request which requires a clean working directory.")
fmt.Fprintln(os.Stderr, "Please commit or stash your changes first:")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("The add wizard creates a pull request which requires a clean working directory."))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Please commit or stash your changes first:"))
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, console.FormatCommandMessage(" git stash # Temporarily stash changes"))
fmt.Fprintln(os.Stderr, console.FormatCommandMessage(" git add -A && git commit -m 'wip' # Commit changes"))
Expand Down
16 changes: 8 additions & 8 deletions pkg/cli/add_interactive_orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@ func (c *AddInteractiveConfig) determineFilesToAdd() (workflowFiles []string, in
}

fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "The following workflow files will be added:")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("The following workflow files will be added:"))
for _, f := range workflowFiles {
fmt.Fprintf(os.Stderr, " • .github/workflows/%s\n", f)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(" • .github/workflows/"+f))
}

return workflowFiles, initFiles, nil
Expand Down Expand Up @@ -238,7 +238,7 @@ func (c *AddInteractiveConfig) confirmChanges(workflowFiles, initFiles []string,
}

if !confirmed {
fmt.Fprintln(os.Stderr, "Operation cancelled.")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Operation cancelled."))
return errors.New("user cancelled the operation")
}

Expand All @@ -248,23 +248,23 @@ func (c *AddInteractiveConfig) confirmChanges(workflowFiles, initFiles []string,
// showFinalInstructions shows final instructions to the user
func (c *AddInteractiveConfig) showFinalInstructions() {
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"))
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("🎉 Addition complete!"))
fmt.Fprintln(os.Stderr, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"))
fmt.Fprintln(os.Stderr, "")

// Show summary with workflow name(s)
if c.resolvedWorkflows != nil && len(c.resolvedWorkflows.Workflows) > 0 {
wf := c.resolvedWorkflows.Workflows[0]
fmt.Fprintf(os.Stderr, "The workflow '%s' has been added to the repository and will now run automatically.\n", wf.Spec.WorkflowName)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("The workflow '%s' has been added to the repository and will now run automatically.", wf.Spec.WorkflowName)))
c.showWorkflowDescriptions()
}

fmt.Fprintln(os.Stderr, "Useful commands:")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Useful commands:"))
fmt.Fprintln(os.Stderr, console.FormatCommandMessage(fmt.Sprintf(" %s status # Check workflow status", string(constants.CLIExtensionPrefix))))
fmt.Fprintln(os.Stderr, console.FormatCommandMessage(fmt.Sprintf(" %s run <workflow> # Trigger a workflow", string(constants.CLIExtensionPrefix))))
fmt.Fprintln(os.Stderr, console.FormatCommandMessage(fmt.Sprintf(" %s logs # View workflow logs", string(constants.CLIExtensionPrefix))))
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "Learn more at: https://github.github.com/gh-aw/")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Learn more at: https://github.github.com/gh-aw/"))
fmt.Fprintln(os.Stderr, "")
}
3 changes: 2 additions & 1 deletion pkg/cli/add_interactive_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"strings"

"github.com/github/gh-aw/pkg/console"
"github.com/github/gh-aw/pkg/sliceutil"
"github.com/github/gh-aw/pkg/workflow"
)
Expand Down Expand Up @@ -41,7 +42,7 @@ func (c *AddInteractiveConfig) checkExistingSecrets() error {
}

if c.Verbose && len(c.existingSecrets) > 0 {
fmt.Fprintf(os.Stderr, "Found %d existing secret(s) (repository + organization)\n", len(c.existingSecrets))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Found %d existing secret(s) (repository + organization)", len(c.existingSecrets))))
}

return nil
Expand Down
32 changes: 16 additions & 16 deletions pkg/cli/add_interactive_workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,22 @@ func (c *AddInteractiveConfig) checkStatusAndOfferRun(ctx context.Context) error
parsed, _ := parseWorkflowSpec(c.WorkflowSpecs[0])
if parsed != nil {
if c.Verbose {
fmt.Fprintf(os.Stderr, "Checking workflow status (attempt %d/5) for: %s\n", i+1, parsed.WorkflowName)
fmt.Fprintln(os.Stderr, console.FormatProgressMessage(fmt.Sprintf("Checking workflow status (attempt %d/5) for: %s", i+1, parsed.WorkflowName)))
}
// Check if workflow is in status
statuses, err := findWorkflowsByFilenamePattern(parsed.WorkflowName, c.RepoOverride, c.Verbose)
if err != nil {
if c.Verbose {
fmt.Fprintf(os.Stderr, "Status check error: %v\n", err)
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(fmt.Sprintf("Status check error: %v", err)))
}
} else if len(statuses) > 0 {
if c.Verbose {
fmt.Fprintf(os.Stderr, "Found %d workflow(s) matching pattern\n", len(statuses))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Found %d workflow(s) matching pattern", len(statuses))))
}
workflowFound = true
break
} else if c.Verbose {
fmt.Fprintln(os.Stderr, "No workflows found matching pattern yet")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("No workflows found matching pattern yet"))
}
}
}
Expand All @@ -74,7 +74,7 @@ func (c *AddInteractiveConfig) checkStatusAndOfferRun(ctx context.Context) error

if !workflowFound {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("Could not verify workflow status."))
fmt.Fprintf(os.Stderr, "You can check status with: %s status\n", string(constants.CLIExtensionPrefix))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("You can check status with: %s status", string(constants.CLIExtensionPrefix))))
c.showFinalInstructions()
return nil
}
Expand All @@ -93,7 +93,7 @@ func (c *AddInteractiveConfig) checkStatusAndOfferRun(ctx context.Context) error
addInteractiveLog.Print("Running in Codespaces, skipping run offer and showing Actions link")
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Running in GitHub Codespaces - please trigger the workflow manually from the Actions page"))
fmt.Fprintf(os.Stderr, "🔗 https://github.com/%s/actions\n", c.RepoOverride)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("🔗 https://github.com/%s/actions", c.RepoOverride)))
c.showFinalInstructions()
return nil
}
Expand Down Expand Up @@ -132,15 +132,15 @@ func (c *AddInteractiveConfig) checkStatusAndOfferRun(ctx context.Context) error
// after the PR merge—avoids a race where git fetch runs before GitHub's git
// objects have been updated, which caused "workflow file not found" errors.
if !c.Verbose {
fmt.Fprintln(os.Stderr, "Updating local branch (this may take a few seconds)...")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Updating local branch (this may take a few seconds)..."))
}
if err := c.updateLocalBranch(); err != nil {
addInteractiveLog.Printf("Failed to update local branch: %v", err)
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Could not update local branch: %v", err)))
fmt.Fprintln(os.Stderr, "You may need to switch to your repository's default branch (for example 'main') and run 'git pull' manually before running the workflow.")
fmt.Fprintln(os.Stderr, console.FormatProgressMessage("You may need to switch to your repository's default branch (for example 'main') and run 'git pull' manually before running the workflow."))
}
if !c.Verbose {
fmt.Fprintln(os.Stderr, "Finished updating local branch.")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Finished updating local branch."))
}

if err := RunSpecificWorkflowInteractively(ctx, parsed.WorkflowName, c.Verbose, c.EngineOverride, c.RepoOverride, "", false, false, false); err != nil {
Expand All @@ -155,7 +155,7 @@ func (c *AddInteractiveConfig) checkStatusAndOfferRun(ctx context.Context) error
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Workflow triggered successfully!"))
fmt.Fprintln(os.Stderr, "")
fmt.Fprintf(os.Stderr, "🔗 View workflow run: %s\n", runInfo.URL)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("🔗 View workflow run: "+runInfo.URL))
}
}
}
Expand All @@ -176,20 +176,20 @@ func findWorkflowsByFilenamePattern(pattern, repoOverride string, verbose bool)
}

if verbose {
fmt.Fprintf(os.Stderr, "Running: gh %s\n", strings.Join(args, " "))
fmt.Fprintln(os.Stderr, console.FormatProgressMessage("Running: gh "+strings.Join(args, " ")))
}

output, err := workflow.RunGH("Checking workflow status...", args...)
if err != nil {
if verbose {
fmt.Fprintf(os.Stderr, "gh workflow list failed: %v\n", err)
fmt.Fprintln(os.Stderr, console.FormatErrorMessage("gh workflow list failed: "+err.Error()))
}
return nil, err
}

if verbose {
fmt.Fprintf(os.Stderr, "gh workflow list output: %s\n", string(output))
fmt.Fprintf(os.Stderr, "Looking for workflow with filename containing: %s\n", pattern)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("gh workflow list output: "+string(output)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Looking for workflow with filename containing: "+pattern))
}

// Check if any workflow path contains the pattern
Expand All @@ -198,13 +198,13 @@ func findWorkflowsByFilenamePattern(pattern, repoOverride string, verbose bool)
// We check if the path contains the pattern
if strings.Contains(string(output), pattern+".lock.yml") || strings.Contains(string(output), pattern+".md") {
if verbose {
fmt.Fprintf(os.Stderr, "Workflow with filename '%s' found in workflow list\n", pattern)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Workflow with filename '%s' found in workflow list", pattern)))
}
return []WorkflowStatus{{Workflow: pattern}}, nil
}

if verbose {
fmt.Fprintf(os.Stderr, "Workflow with filename '%s' NOT found in workflow list\n", pattern)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Workflow with filename '%s' NOT found in workflow list", pattern)))
}
return nil, nil
}
6 changes: 3 additions & 3 deletions pkg/cli/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -745,18 +745,18 @@ func auditJobRun(runID int64, jobID int64, stepNumber int, owner, repo, hostname

// Display file locations
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("\nDownloaded files:"))
fmt.Fprintf(os.Stderr, " - %s (full job log)\n", jobLogPath)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" - %s (full job log)", jobLogPath)))

if stepNumber > 0 {
stepLogPath := filepath.Join(outputDir, fmt.Sprintf("job-%d-step-%d.log", jobID, stepNumber))
if _, err := os.Stat(stepLogPath); err == nil {
fmt.Fprintf(os.Stderr, " - %s (step %d output)\n", stepLogPath, stepNumber)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" - %s (step %d output)", stepLogPath, stepNumber)))
}
} else {
failingStepPath := filepath.Join(outputDir, fmt.Sprintf("job-%d-step-*-failed.log", jobID))
matches, _ := filepath.Glob(failingStepPath)
for _, match := range matches {
fmt.Fprintf(os.Stderr, " - %s (first failing step)\n", match)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" - %s (first failing step)", match)))
}
}
}
Expand Down
24 changes: 12 additions & 12 deletions pkg/cli/audit_cross_run_render.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,13 @@ func renderCrossRunReportPretty(report *CrossRunAuditReport) {

// Executive summary
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Executive Summary"))
fmt.Fprintf(os.Stderr, " Runs analyzed: %d\n", report.RunsAnalyzed)
fmt.Fprintf(os.Stderr, " Runs with firewall data: %d\n", report.RunsWithData)
fmt.Fprintf(os.Stderr, " Runs without firewall data: %d\n", report.RunsWithoutData)
fmt.Fprintf(os.Stderr, " Total requests: %d\n", report.Summary.TotalRequests)
fmt.Fprintf(os.Stderr, " Allowed / Blocked: %d / %d\n", report.Summary.TotalAllowed, report.Summary.TotalBlocked)
fmt.Fprintf(os.Stderr, " Overall denial rate: %.1f%%\n", report.Summary.OverallDenyRate*100)
fmt.Fprintf(os.Stderr, " Unique domains: %d\n", report.Summary.UniqueDomains)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" Runs analyzed: %d", report.RunsAnalyzed)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" Runs with firewall data: %d", report.RunsWithData)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" Runs without firewall data: %d", report.RunsWithoutData)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" Total requests: %d", report.Summary.TotalRequests)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" Allowed / Blocked: %d / %d", report.Summary.TotalAllowed, report.Summary.TotalBlocked)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" Overall denial rate: %.1f%%", report.Summary.OverallDenyRate*100)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" Unique domains: %d", report.Summary.UniqueDomains)))
fmt.Fprintln(os.Stderr)

// Metrics trends
Expand Down Expand Up @@ -278,9 +278,9 @@ func renderCrossRunReportPretty(report *CrossRunAuditReport) {
fmt.Fprintf(os.Stderr, " Runs with errors: %d/%d (%.0f%%)\n",
et.RunsWithErrors, report.RunsAnalyzed,
safePercent(et.RunsWithErrors, report.RunsAnalyzed))
fmt.Fprintf(os.Stderr, " Total errors: %d (avg=%.2f/run)\n", et.TotalErrors, et.AvgErrorsPerRun)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" Total errors: %d (avg=%.2f/run)", et.TotalErrors, et.AvgErrorsPerRun)))
if et.TotalWarnings > 0 {
fmt.Fprintf(os.Stderr, " Total warnings: %d (%d runs)\n", et.TotalWarnings, et.RunsWithWarnings)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" Total warnings: %d (%d runs)", et.TotalWarnings, et.RunsWithWarnings)))
}
fmt.Fprintln(os.Stderr)
}
Expand Down Expand Up @@ -310,10 +310,10 @@ func renderCrossRunReportPretty(report *CrossRunAuditReport) {
case "low":
severityIcon = "🟡"
}
fmt.Fprintf(os.Stderr, " %s [%s/%s] %s\n", severityIcon, insight.Category, insight.Severity, insight.Title)
fmt.Fprintf(os.Stderr, " %s\n", insight.Summary)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" %s [%s/%s] %s", severityIcon, insight.Category, insight.Severity, insight.Title)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(" "+insight.Summary))
if insight.Evidence != "" {
fmt.Fprintf(os.Stderr, " evidence: %s\n", insight.Evidence)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(" evidence: "+insight.Evidence))
}
}
fmt.Fprintln(os.Stderr)
Expand Down
Loading
Loading