(owner, repo, ref, workflowPath, host string)
| 1463 | } |
| 1464 | |
| 1465 | func listWorkflowFilesViaGitForHost(owner, repo, ref, workflowPath, host string) ([]string, error) { |
| 1466 | remoteLog.Printf("Attempting git fallback for listing workflow files: %s/%s@%s (path: %s)", owner, repo, ref, workflowPath) |
| 1467 | |
| 1468 | githubHost := GetGitHubHostForRepo(owner, repo) |
| 1469 | if host != "" { |
| 1470 | githubHost = stringutil.NormalizeGitHubHostURL(host) |
| 1471 | } |
| 1472 | repoURL := fmt.Sprintf("%s/%s/%s.git", githubHost, owner, repo) |
| 1473 | |
| 1474 | // Create a temporary directory for minimal clone |
| 1475 | tmpDir, err := os.MkdirTemp("", "gh-aw-list-*") |
| 1476 | if err != nil { |
| 1477 | return nil, fmt.Errorf("failed to create temp directory: %w", err) |
| 1478 | } |
| 1479 | defer os.RemoveAll(tmpDir) |
| 1480 | |
| 1481 | // Do a minimal clone using filter=blob:none for faster cloning (metadata only, no blobs) |
| 1482 | // Use --depth=1 for shallow clone and --no-checkout to skip checkout initially |
| 1483 | cloneCmd := exec.Command("git", "clone", "--depth", "1", "--branch", ref, "--single-branch", "--filter=blob:none", "--no-checkout", repoURL, tmpDir) |
| 1484 | cloneOutput, err := cloneCmd.CombinedOutput() |
| 1485 | if err != nil { |
| 1486 | remoteLog.Printf("Failed to clone repository: %s", string(cloneOutput)) |
| 1487 | return nil, fmt.Errorf("failed to clone repository for %s/%s@%s: %w", owner, repo, ref, err) |
| 1488 | } |
| 1489 | |
| 1490 | // Use git ls-tree to list files in the specified workflows directory |
| 1491 | lsTreeCmd := exec.Command("git", "-C", tmpDir, "ls-tree", "-r", "--name-only", "HEAD", workflowPath+"/") |
| 1492 | lsTreeOutput, err := lsTreeCmd.CombinedOutput() |
| 1493 | if err != nil { |
| 1494 | remoteLog.Printf("Failed to list files: %s", string(lsTreeOutput)) |
| 1495 | return nil, fmt.Errorf("failed to list workflow files: %w", err) |
| 1496 | } |
| 1497 | |
| 1498 | // Parse output and filter for .md files (not in subdirectories) |
| 1499 | lines := strings.Split(strings.TrimSpace(string(lsTreeOutput)), "\n") |
| 1500 | var workflowFiles []string |
| 1501 | for _, line := range lines { |
| 1502 | line = strings.TrimSpace(line) |
| 1503 | if line == "" { |
| 1504 | continue |
| 1505 | } |
| 1506 | // Only include .md files directly in the workflow path (not in subdirectories) |
| 1507 | if strings.HasSuffix(strings.ToLower(line), ".md") { |
| 1508 | // Check if it's a top-level file (no additional slashes after workflowPath/) |
| 1509 | afterWorkflowPath := strings.TrimPrefix(line, workflowPath+"/") |
| 1510 | if !strings.Contains(afterWorkflowPath, "/") { |
| 1511 | workflowFiles = append(workflowFiles, line) |
| 1512 | } |
| 1513 | } |
| 1514 | } |
| 1515 | |
| 1516 | remoteLog.Printf("Found %d workflow files via git for %s/%s@%s (path: %s)", len(workflowFiles), owner, repo, ref, workflowPath) |
| 1517 | return workflowFiles, nil |
| 1518 | } |
| 1519 | |
| 1520 | // listWorkflowFilesViaPublicAPI lists workflow .md files using an unauthenticated |
| 1521 | // call to the public GitHub API. Used as a last-resort fallback when both |
no test coverage detected