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
7 changes: 7 additions & 0 deletions pkg/cli/dispatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type fileDownloadFn func(owner, repo, path, ref string) ([]byte, error)
// An optional downloader function may be provided as the last argument to override the default
// parser.DownloadFileFromGitHub implementation (used in tests to avoid real network calls).
func fetchAndSaveRemoteDispatchWorkflows(ctx context.Context, content string, spec *WorkflowSpec, targetDir string, verbose bool, force bool, tracker *FileTracker, downloaders ...fileDownloadFn) error {
remoteWorkflowLog.Printf("Fetching remote dispatch workflows: repo=%s, targetDir=%s, force=%v", spec.RepoSlug, targetDir, force)
downloader := fileDownloadFn(parser.DownloadFileFromGitHub)
if len(downloaders) > 0 && downloaders[0] != nil {
downloader = downloaders[0]
Expand Down Expand Up @@ -106,6 +107,8 @@ func fetchAndSaveRemoteDispatchWorkflows(ctx context.Context, content string, sp
return nil
}

remoteWorkflowLog.Printf("Found %d dispatch workflow(s) to fetch from %s@%s", len(workflowNames), spec.RepoSlug, ref)

// workflowBaseDir is the directory of the source workflow in the remote repo
// (e.g. ".github/workflows"). Dispatch-workflow names are resolved relative to it.
workflowBaseDir := getParentDir(spec.WorkflowPath)
Expand Down Expand Up @@ -169,6 +172,7 @@ func fetchAndSaveRemoteDispatchWorkflows(ctx context.Context, content string, sp
// (the dispatch-workflow validator accepts either .md or .yml files locally).
workflowContent, err := downloader(owner, repo, remoteFilePath, ref)
if err != nil {
remoteWorkflowLog.Printf(".md fetch failed for dispatch workflow %s, trying .yml fallback", workflowName)
// .md not found — try .yml fallback (e.g. plain GitHub Actions workflow)
ymlRemotePath := path.Clean(strings.TrimSuffix(remoteFilePath, ".md") + ".yml")
ymlLocalPath := filepath.Join(targetDir, filepath.Clean(workflowName+".yml"))
Expand Down Expand Up @@ -263,6 +267,7 @@ func fetchAndSaveRemoteDispatchWorkflows(ctx context.Context, content string, sp
// Parse failures are logged at debug level so they can be investigated when needed.
// Source conflicts are reported as warnings (not errors) because the main file is already written.
func fetchAndSaveDispatchWorkflowsFromParsedFile(destFile string, spec *WorkflowSpec, targetDir string, verbose bool, force bool, tracker *FileTracker) {
remoteWorkflowLog.Printf("Fetching import-derived dispatch workflows from parsed file: %s, repo=%s", destFile, spec.RepoSlug)
if spec.RepoSlug == "" {
return
}
Expand Down Expand Up @@ -304,6 +309,8 @@ func fetchAndSaveDispatchWorkflowsFromParsedFile(destFile string, spec *Workflow
return
}

remoteWorkflowLog.Printf("Processing %d import-derived dispatch workflow(s) (filtered from %d)", len(filtered), len(workflowNames))

workflowBaseDir := getParentDir(spec.WorkflowPath)

absTargetDir, absErr := filepath.Abs(targetDir)
Expand Down
3 changes: 3 additions & 0 deletions pkg/cli/includes.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ func fetchFrontmatterImportsRecursive(content, owner, repo, ref, currentBaseDir,

// Cycle/duplicate prevention: use the fully-resolved remote path as the key.
if seen[remoteFilePath] {
remoteWorkflowLog.Printf("Skipping already-seen import: %s", remoteFilePath)
continue
}
seen[remoteFilePath] = true
Expand Down Expand Up @@ -331,6 +332,7 @@ func fetchFrontmatterImportsRecursive(content, owner, repo, ref, currentBaseDir,
// Download from the source repository
importContent, err := parser.DownloadFileFromGitHub(owner, repo, remoteFilePath, ref)
if err != nil {
remoteWorkflowLog.Printf("Failed to download import %s from %s/%s@%s: %v", remoteFilePath, owner, repo, ref, err)
if verbose {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to fetch import %s: %v", remoteFilePath, err)))
}
Expand Down Expand Up @@ -487,6 +489,7 @@ func fetchAndSaveRemoteIncludes(content string, spec *WorkflowSpec, targetDir st
// verbose is true but do not stop the overall operation.
// - Dispatch-workflow and resource errors are fatal and are returned to the caller.
func fetchAllRemoteDependencies(ctx context.Context, content string, spec *WorkflowSpec, targetDir string, verbose bool, force bool, tracker *FileTracker) error {
remoteWorkflowLog.Printf("Fetching all remote dependencies: spec=%s, targetDir=%s, force=%v", spec.String(), targetDir, force)
// Fetch and save @include directive dependencies (best-effort: errors are not fatal).
if err := fetchAndSaveRemoteIncludes(content, spec, targetDir, verbose, force, tracker); err != nil {
if verbose {
Expand Down
9 changes: 9 additions & 0 deletions pkg/cli/lint_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import (
"strings"

"github.com/github/gh-aw/pkg/constants"
"github.com/github/gh-aw/pkg/logger"
"github.com/spf13/cobra"
)

var lintCommandLog = logger.New("cli:lint_command")

var defaultGhAwActionlintIgnorePatterns = []string{
// gh-aw extends GitHub Actions permissions with copilot-requests.
`unknown permission scope "copilot-requests"`,
Expand Down Expand Up @@ -40,11 +43,16 @@ Examples:
includePyflakes, _ := cmd.Flags().GetBool("pyflakes")
verbose, _ := cmd.Flags().GetBool("verbose")

lintCommandLog.Printf("Executing lint: dir=%s, shellcheck=%v, pyflakes=%v, args=%d", workflowDir, includeShellcheck, includePyflakes, len(args))

lockFiles, err := resolveLockFilesForLint(args, workflowDir)
if err != nil {
lintCommandLog.Printf("Failed to resolve lock files: %v", err)
return err
}

lintCommandLog.Printf("Resolved %d lock file(s) for linting", len(lockFiles))

initActionlintStats()
defer displayActionlintSummary()

Expand Down Expand Up @@ -108,6 +116,7 @@ func expandLintCandidate(candidate string) ([]string, error) {
if err != nil {
return nil, fmt.Errorf("failed to scan %q for .lock.yml files: %w", candidate, err)
}
lintCommandLog.Printf("Expanded directory %s to %d .lock.yml file(s)", candidate, len(lockFiles))
return lockFiles, nil
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/cli/logs_run_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func downloadRunArtifactsConcurrent(ctx context.Context, runs []WorkflowRun, out

// Try to load cached summary first
if summary, ok := loadRunSummary(runOutputDir, verbose); ok {
logsOrchestratorLog.Printf("Cache hit for run %d, using cached summary", run.DatabaseID)
// Valid cached summary exists, use it directly
result := DownloadResult{
Run: summary.Run,
Expand Down Expand Up @@ -150,6 +151,7 @@ func downloadRunArtifactsConcurrent(ctx context.Context, runs []WorkflowRun, out
runOwner, runRepo, runHost = c.Owner, c.Repo, c.Host
}
}
logsOrchestratorLog.Printf("Downloading artifacts for run %d: owner=%s, repo=%s", run.DatabaseID, runOwner, runRepo)
err := downloadRunArtifacts(ctx, run.DatabaseID, runOutputDir, verbose, runOwner, runRepo, runHost, artifactFilter)

result := DownloadResult{
Expand All @@ -160,6 +162,7 @@ func downloadRunArtifactsConcurrent(ctx context.Context, runs []WorkflowRun, out
if err != nil {
// Check if this is a "no artifacts" case
if errors.Is(err, ErrNoArtifacts) {
logsOrchestratorLog.Printf("No artifacts available for run %d (conclusion=%s)", run.DatabaseID, run.Conclusion)
// For runs with important conclusions (timed_out, failure, cancelled),
// still process them even without artifacts to show the failure in reports
if isFailureConclusion(run.Conclusion) {
Expand Down Expand Up @@ -431,6 +434,7 @@ func downloadRunArtifactsConcurrent(ctx context.Context, runs []WorkflowRun, out
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Completed parallel processing: %d successful, %d total", successCount, len(results))))
}

logsOrchestratorLog.Printf("Concurrent download complete: total=%d, results=%d", len(actualRuns), len(results))
return results
}

Expand Down
3 changes: 3 additions & 0 deletions pkg/cli/trial_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ func executeTrialRun(ctx context.Context, parsedSpecs []*WorkflowSpec, hostRepoS
}

func triggerWorkflowRun(repoSlug, workflowName string, triggerContext string, verbose bool) (string, error) {
trialLog.Printf("Triggering workflow run: workflow=%s, repo=%s, hasTriggerContext=%v", workflowName, repoSlug, triggerContext != "")
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Triggering workflow run for: "+workflowName))
}
Expand Down Expand Up @@ -271,6 +272,7 @@ func saveTrialResult(filename string, result any, verbose bool) error {

// copyTrialResultsToHostRepo copies trial result files to the host repository and commits them
func copyTrialResultsToHostRepo(tempDir, dateTimeID string, workflowNames []string, targetRepoSlug string, verbose bool) error {
trialLog.Printf("Copying trial results to host repo: workflows=%d, dateTimeID=%s, targetRepo=%s", len(workflowNames), dateTimeID, targetRepoSlug)
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Copying trial results to host repository"))
}
Expand Down Expand Up @@ -340,6 +342,7 @@ func copyTrialResultsToHostRepo(tempDir, dateTimeID string, workflowNames []stri

// If no changes, skip commit and push
if len(strings.TrimSpace(string(statusOutput))) == 0 {
trialLog.Print("No new trial results to commit, skipping push")
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("No new trial results to commit"))
}
Expand Down