fetchLatestRunsByRef fetches the latest workflow run for each workflow from a specific ref (branch or tag)
(ref string, repoOverride string, verbose bool)
| 483 | |
| 484 | // fetchLatestRunsByRef fetches the latest workflow run for each workflow from a specific ref (branch or tag) |
| 485 | func fetchLatestRunsByRef(ref string, repoOverride string, verbose bool) (map[string]*WorkflowRun, error) { |
| 486 | statusLog.Printf("Fetching latest workflow runs for ref: %s, repo: %s", ref, repoOverride) |
| 487 | |
| 488 | // Start spinner for network operation (only if not in verbose mode) |
| 489 | spinner := console.NewSpinner("Fetching workflow runs for ref...") |
| 490 | if !verbose { |
| 491 | spinner.Start() |
| 492 | } |
| 493 | |
| 494 | // Fetch workflow runs for the ref (uses --branch flag which also works for tags) |
| 495 | args := []string{"run", "list", "--branch", ref, "--json", "databaseId,number,url,status,conclusion,workflowName,createdAt,headBranch", "--limit", "100"} |
| 496 | if repoOverride != "" { |
| 497 | args = append(args, "--repo", repoOverride) |
| 498 | } |
| 499 | cmd := workflow.ExecGH(args...) |
| 500 | output, err := cmd.Output() |
| 501 | |
| 502 | if err != nil { |
| 503 | // Stop spinner on error |
| 504 | if !verbose { |
| 505 | spinner.Stop() |
| 506 | } |
| 507 | |
| 508 | // Extract detailed error information including exit code and stderr |
| 509 | var exitCode int |
| 510 | var stderr string |
| 511 | var exitErr *exec.ExitError |
| 512 | if errors.As(err, &exitErr) { |
| 513 | exitCode = exitErr.ExitCode() |
| 514 | stderr = string(exitErr.Stderr) |
| 515 | statusLog.Printf("gh run list command failed with exit code %d. Command: gh %v", exitCode, args) |
| 516 | statusLog.Printf("stderr output: %s", stderr) |
| 517 | |
| 518 | // Check for invalid field errors first (before generic error) |
| 519 | // GitHub CLI returns these when JSON fields don't exist or are misspelled |
| 520 | combinedMsg := err.Error() + " " + stderr |
| 521 | if strings.Contains(combinedMsg, "invalid field") || |
| 522 | strings.Contains(combinedMsg, "unknown field") || |
| 523 | strings.Contains(combinedMsg, "field not found") || |
| 524 | strings.Contains(combinedMsg, "no such field") { |
| 525 | return nil, fmt.Errorf("invalid field in JSON query (exit code %d): %s", exitCode, stderr) |
| 526 | } |
| 527 | |
| 528 | return nil, fmt.Errorf("failed to execute gh run list command (exit code %d): %w. stderr: %s", exitCode, err, stderr) |
| 529 | } |
| 530 | |
| 531 | // If not an ExitError, log what we can |
| 532 | statusLog.Printf("gh run list command failed with error (not ExitError): %v. Command: gh %v", err, args) |
| 533 | return nil, fmt.Errorf("failed to execute gh run list command: %w", err) |
| 534 | } |
| 535 | |
| 536 | // Check if output is empty |
| 537 | if len(output) == 0 { |
| 538 | if !verbose { |
| 539 | spinner.Stop() |
| 540 | } |
| 541 | return nil, errors.New("gh run list returned empty output") |
| 542 | } |
no test coverage detected