Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions .github/workflows/cgo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,9 @@ jobs:
- name: Run custom linters
run: make golint-custom LINTER_FLAGS="-errstringmatch -panicinlibrarycode -manualmutexunlock -osexitinlibrary -rawloginlib -logfatallibrary -regexpcompileinfunction -fprintlnsprintf -strconvparseignorederror -jsonmarshalignoredeerror -uncheckedtypeassertion -fmterrorfnoverbs -tolowerequalfold -httpnoctx -httprespbodyclose -httpstatuscode -timeafterleak -errortypeassertion -execcommandwithoutcontext -sprintfint -stringsindexcontains -stringscountcontains -bytesbufferstring -ioutildeprecated -mapclearloop -mapdeletecheck -sprintfbool -appendoneelement -timenowsub -stringsjoinone -writebytestring -lenstringsplit -stringreplaceminusone -osgetenvlibrary -ossetenvlibrary -stringsindexhasprefix -contextcancelnotdeferred -ctxbackground -wgdonenotdeferred -goroutinemissingrecover -trimleftright -walkfuncerrshadow -uncheckedflushreturn -bytescomparestring -nilctxpassed -stringbytesroundtrip -fileclosenotdeferred -timesleepnocontext -sprintferrorsnew -globwalkignorederror -appendbytestring -slicemakezerolength -sortslice -deferinloop -regexpdynamicpattern -generatedyamlheredoc -test=false"

- name: Check console stderr formatting
run: make golint-custom LINTER_FLAGS="-consolestderr -test=false"

- name: Report unchecked printf errors as warnings
run: |
set +e
Expand Down
10 changes: 5 additions & 5 deletions cmd/gh-aw/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -686,20 +686,20 @@ func rootUsageFunc(cmd *cobra.Command) error {

func customHelpRunE(c *cobra.Command, args []string) error {
if len(args) == 1 && args[0] == "all" {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("GitHub Agentic Workflows CLI - Complete Command Reference"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("GitHub Agentic Workflows CLI - Complete Command Reference"))
fmt.Fprintln(os.Stderr, "")
for _, subCmd := range rootCmd.Commands() {
if subCmd.Hidden || subCmd.Name() == "help" {
continue
}
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("═══════════════════════════════════════════════════════════════"))
fmt.Fprintf(os.Stderr, "\n%s\n\n", console.FormatInfoMessage(fmt.Sprintf("Command: %s %s", string(constants.CLIExtensionPrefix), subCmd.Name())))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("═══════════════════════════════════════════════════════════════"))
fmt.Fprintf(os.Stderr, "\n%s\n\n", console.FormatInfoMessageStderr(fmt.Sprintf("Command: %s %s", string(constants.CLIExtensionPrefix), subCmd.Name())))
_ = subCmd.Help()
fmt.Fprintln(os.Stderr, "")
}
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("═══════════════════════════════════════════════════════════════"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("═══════════════════════════════════════════════════════════════"))
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("For more information, visit: https://github.github.com/gh-aw/"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("For more information, visit: https://github.github.com/gh-aw/"))
return nil
}
cmd, _, e := rootCmd.Find(args)
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/access_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func processSquidAccessLogLine(line string, verbose bool, analysis *DomainAnalys
entry, err := parseSquidLogLine(line)
if err != nil {
if verbose {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to parse log line: %v", err)))
fmt.Fprintln(os.Stderr, console.FormatWarningMessageStderr(fmt.Sprintf("Failed to parse log line: %v", err)))
}
return
}
Expand Down Expand Up @@ -209,7 +209,7 @@ func analyzeAccessLogs(runDir string, verbose bool) (*DomainAnalysis, error) {
// No access logs found
accessLogLog.Printf("No access logs directory found in: %s", runDir)
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("No access logs found in "+runDir))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("No access logs found in "+runDir))
}
return nil, nil
}
Expand Down
32 changes: 16 additions & 16 deletions pkg/cli/actionlint.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,12 @@ func displayActionlintSummary() {
separator := strings.Repeat("━", 60)

fmt.Fprintf(os.Stderr, "\n%s\n", separator)
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessage("Actionlint Summary"))
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessageStderr("Actionlint Summary"))
fmt.Fprintf(os.Stderr, "%s\n\n", separator)

// Show total workflows checked
fmt.Fprintf(os.Stderr, "%s\n",
console.FormatSuccessMessage(fmt.Sprintf("Checked %d workflow(s)", actionlintStats.TotalWorkflows)))
console.FormatSuccessMessageStderr(fmt.Sprintf("Checked %d workflow(s)", actionlintStats.TotalWorkflows)))

// Show total issues found
totalIssues := actionlintStats.TotalErrors + actionlintStats.TotalWarnings
Expand All @@ -140,11 +140,11 @@ func displayActionlintSummary() {
} else if actionlintStats.TotalWarnings > 0 {
issueText += fmt.Sprintf(" (%d warning(s))", actionlintStats.TotalWarnings)
}
fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(issueText))
fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessageStderr(issueText))

// Break down by error kind if we have multiple kinds
if len(actionlintStats.ErrorsByKind) > 0 {
fmt.Fprintf(os.Stderr, "\n%s\n", console.FormatInfoMessage("Issues by type:"))
fmt.Fprintf(os.Stderr, "\n%s\n", console.FormatInfoMessageStderr("Issues by type:"))
for kind, count := range actionlintStats.ErrorsByKind {
fmt.Fprintf(os.Stderr, " • %s: %d\n", kind, count)
}
Expand All @@ -155,17 +155,17 @@ func displayActionlintSummary() {
msg := fmt.Sprintf("No lint issues found, but %d actionlint invocation(s) failed. "+
"This likely indicates a tooling or integration error, not a workflow problem.",
actionlintStats.IntegrationErrors)
fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessage(msg))
fmt.Fprintf(os.Stderr, "%s\n", console.FormatWarningMessageStderr(msg))
} else {
fmt.Fprintf(os.Stderr, "%s\n",
console.FormatSuccessMessage("No issues found"))
console.FormatSuccessMessageStderr("No issues found"))
}

// Report any integration failures alongside lint findings
if totalIssues > 0 && actionlintStats.IntegrationErrors > 0 {
msg := fmt.Sprintf("%d actionlint invocation(s) also failed with tooling errors (not workflow validation failures)",
actionlintStats.IntegrationErrors)
fmt.Fprintf(os.Stderr, "\n%s\n", console.FormatWarningMessage(msg))
fmt.Fprintf(os.Stderr, "\n%s\n", console.FormatWarningMessageStderr(msg))
}

fmt.Fprintf(os.Stderr, "\n%s\n", separator)
Expand Down Expand Up @@ -236,7 +236,7 @@ func runActionlintOnFilesWithOptions(ctx context.Context, lockFiles []string, ve
return nil
}
actionlintLog.Printf("Running actionlint on %d file(s): %v (verbose=%t, strict=%t)", len(lockFiles), lockFiles, verbose, strict)
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessage(fmt.Sprintf("Running actionlint on %d file(s)", len(lockFiles))))
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessageStderr(fmt.Sprintf("Running actionlint on %d file(s)", len(lockFiles))))
maybePrintActionlintVersion(ctx)

gitRoot, relPaths, err := resolveActionlintPaths(lockFiles)
Expand All @@ -263,7 +263,7 @@ func runActionlintOnFilesWithOptions(ctx context.Context, lockFiles []string, ve
if actionlintStats != nil {
actionlintStats.IntegrationErrors++
}
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(
fmt.Fprintln(os.Stderr, console.FormatWarningMessageStderr(
"actionlint output could not be parsed — this is a tooling error, not a workflow validation failure: "+parseErr.Error()))
// Fall back to showing raw output.
if runResult.stdout != "" {
Expand Down Expand Up @@ -297,7 +297,7 @@ func maybePrintActionlintVersion(ctx context.Context) {
actionlintLog.Printf("Could not fetch actionlint version: %v", err)
return
}
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessage("Using actionlint "+version))
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessageStderr("Using actionlint "+version))
}

func resolveActionlintPaths(lockFiles []string) (string, []string, error) {
Expand Down Expand Up @@ -382,14 +382,14 @@ func actionlintShellQuoteArg(arg string) string {
func printActionlintRunMessage(lockFiles, relPaths []string, verboseHint string, options actionlintRunOptions) {
integrationStatus := buildActionlintIntegrationStatus(options.IncludeShellcheck, options.IncludePyflakes)
if len(lockFiles) == 1 {
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessage("Running actionlint ("+integrationStatus+") on "+relPaths[0]))
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessageStderr("Running actionlint ("+integrationStatus+") on "+relPaths[0]))
} else {
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessage(fmt.Sprintf("Running actionlint (%s) on %d files", integrationStatus, len(lockFiles))))
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessageStderr(fmt.Sprintf("Running actionlint (%s) on %d files", integrationStatus, len(lockFiles))))
}
if verboseHint == "" {
return
}
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessage("Run actionlint directly: "+verboseHint))
fmt.Fprintf(os.Stderr, "%s\n", console.FormatInfoMessageStderr("Run actionlint directly: "+verboseHint))
}

func actionlintShouldParseOutput(err error) bool {
Expand Down Expand Up @@ -423,7 +423,7 @@ func handleActionlintExecutionError(err error, strict bool, lockFiles []string,
if actionlintStats != nil {
actionlintStats.IntegrationErrors++
}
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(
fmt.Fprintln(os.Stderr, console.FormatWarningMessageStderr(
"actionlint could not be invoked — this is a tooling error, not a workflow validation failure: "+err.Error()))
return fmt.Errorf("actionlint failed: %w", err)
}
Expand All @@ -438,7 +438,7 @@ func handleActionlintExecutionError(err error, strict bool, lockFiles []string,
if actionlintStats != nil {
actionlintStats.IntegrationErrors++
}
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(
fmt.Fprintln(os.Stderr, console.FormatWarningMessageStderr(
fmt.Sprintf("actionlint failed with exit code %d on %s — this is a tooling error, not a workflow validation failure", exitCode, fileDescription)))
return fmt.Errorf("actionlint failed with exit code %d on %s", exitCode, fileDescription)
}
Expand Down Expand Up @@ -496,7 +496,7 @@ func parseAndDisplayActionlintOutput(stdout string, verbose bool) (int, map[stri
if err.Kind != "" {
errorsByKind[err.Kind]++
}
fmt.Fprint(os.Stderr, console.FormatError(buildActionlintCompilerError(err)))
fmt.Fprint(os.Stderr, console.FormatErrorStderr(buildActionlintCompilerError(err)))
}

return totalErrors, errorsByKind, nil
Expand Down
46 changes: 23 additions & 23 deletions pkg/cli/actions_build_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ func ActionsBuildCommand() error {
}

if len(actionDirs) == 0 {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("No action directories found in actions/"))
fmt.Fprintln(os.Stderr, console.FormatWarningMessageStderr("No action directories found in actions/"))
return nil
}

fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Building all actions..."))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("Building all actions..."))

// Build each action
for _, actionName := range actionDirs {
Expand All @@ -49,7 +49,7 @@ func ActionsBuildCommand() error {
}
}

fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("✨ All actions built successfully (%d actions)", len(actionDirs))))
fmt.Fprintln(os.Stderr, console.FormatSuccessMessageStderr(fmt.Sprintf("✨ All actions built successfully (%d actions)", len(actionDirs))))
return nil
}

Expand All @@ -66,28 +66,28 @@ func ActionsValidateCommand() error {
}

if len(actionDirs) == 0 {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("No action directories found in actions/"))
fmt.Fprintln(os.Stderr, console.FormatWarningMessageStderr("No action directories found in actions/"))
return nil
}

fmt.Fprintln(os.Stderr, console.FormatInfoMessage("✅ Validating all actions"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("Validating all actions"))

allValid := true
for _, actionName := range actionDirs {
actionPath := filepath.Join(actionsDir, actionName)
if err := validateActionYml(actionPath); err != nil {
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(fmt.Sprintf("✗ %s/action.yml: %s", actionName, err)))
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(fmt.Sprintf("%s/action.yml: %s", actionName, err)))
allValid = false
} else {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" ✓ %s/action.yml is valid", actionName)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(fmt.Sprintf(" %s/action.yml is valid", actionName)))
}
}

if !allValid {
return errors.New("validation failed for one or more actions")
}

fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("✨ All actions valid"))
fmt.Fprintln(os.Stderr, console.FormatSuccessMessageStderr("✨ All actions valid"))
return nil
}

Expand All @@ -104,11 +104,11 @@ func ActionsCleanCommand() error {
}

if len(actionDirs) == 0 {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage("No action directories found in actions/"))
fmt.Fprintln(os.Stderr, console.FormatWarningMessageStderr("No action directories found in actions/"))
return nil
}

fmt.Fprintln(os.Stderr, console.FormatInfoMessage("🧹 Cleaning generated action files"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("🧹 Cleaning generated action files"))

cleanedCount := 0
for _, actionName := range actionDirs {
Expand All @@ -119,7 +119,7 @@ func ActionsCleanCommand() error {
if err := os.Remove(indexPath); err != nil {
return fmt.Errorf("failed to remove %s: %w", indexPath, err)
}
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" ✓ Removed %s/index.js", actionName)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(fmt.Sprintf(" Removed %s/index.js", actionName)))
cleanedCount++
}
}
Expand All @@ -128,7 +128,7 @@ func ActionsCleanCommand() error {
// Do not clean them
}

fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("✨ Cleanup complete (%d files removed)", cleanedCount)))
fmt.Fprintln(os.Stderr, console.FormatSuccessMessageStderr(fmt.Sprintf("✨ Cleanup complete (%d files removed)", cleanedCount)))
return nil
}

Expand Down Expand Up @@ -202,12 +202,12 @@ func validateActionYml(actionPath string) error {
func buildAction(actionsDir, actionName string) error {
actionsBuildLog.Printf("Building action: %s", actionName)

fmt.Fprintln(os.Stderr, console.FormatInfoMessage("\n📦 Building action: "+actionName))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("\n📦 Building action: "+actionName))

actionPath := filepath.Join(actionsDir, actionName)

// Validate action.yml
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(" ✓ Validating action.yml"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(" Validating action.yml"))
if err := validateActionYml(actionPath); err != nil {
return err
}
Expand All @@ -224,7 +224,7 @@ func buildAction(actionsDir, actionName string) error {
}

if isComposite {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(" ✓ Composite action - no JavaScript bundling needed"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(" Composite action - no JavaScript bundling needed"))
return nil
}

Expand All @@ -244,15 +244,15 @@ func buildJavaScriptAction(actionPath, actionName string) error {
return fmt.Errorf("source file not found: %s", srcPath)
}

fmt.Fprintln(os.Stderr, console.FormatInfoMessage(" ✓ Reading source file"))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(" Reading source file"))
sourceContent, err := os.ReadFile(srcPath)
if err != nil {
return fmt.Errorf("failed to read source file: %w", err)
}

// Get dependencies for this action
dependencies := getActionDependencies(actionName)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" ✓ Found %d dependencies", len(dependencies))))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(fmt.Sprintf(" Found %d dependencies", len(dependencies))))

// Get all JavaScript sources
sources := workflow.GetJavaScriptSources()
Expand All @@ -262,9 +262,9 @@ func buildJavaScriptAction(actionPath, actionName string) error {
for _, dep := range dependencies {
if content, ok := sources[dep]; ok {
files[dep] = content
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(" - "+dep))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(" - "+dep))
} else {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(" ⚠ Warning: Could not find "+dep))
fmt.Fprintln(os.Stderr, console.FormatWarningMessageStderr(" Could not find "+dep))
}
}

Expand All @@ -287,8 +287,8 @@ func buildJavaScriptAction(actionPath, actionName string) error {
return fmt.Errorf("failed to write output file: %w", err)
}

fmt.Fprintln(os.Stderr, console.FormatInfoMessage(" ✓ Built "+outputPath))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" ✓ Embedded %d files", len(files))))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(" Built "+outputPath))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(fmt.Sprintf(" Embedded %d files", len(files))))

return nil
}
Expand Down Expand Up @@ -326,7 +326,7 @@ func buildSetupAction(actionsDir, actionName string) error {
jsCount++
}
}
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" ✓ JavaScript files in js/ (source of truth): %d", jsCount)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(fmt.Sprintf(" JavaScript files in js/ (source of truth): %d", jsCount)))
}
}

Expand All @@ -341,7 +341,7 @@ func buildSetupAction(actionsDir, actionName string) error {
shCount++
}
}
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" ✓ Shell scripts in sh/ (source of truth): %d", shCount)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr(fmt.Sprintf(" Shell scripts in sh/ (source of truth): %d", shCount)))
}
}

Expand Down
Loading
Loading