downloadFileViaGit downloads a file from a Git repository using git commands This is a fallback for when GitHub API authentication fails
(ctx context.Context, owner, repo, path, ref, host string)
| 603 | // downloadFileViaGit downloads a file from a Git repository using git commands |
| 604 | // This is a fallback for when GitHub API authentication fails |
| 605 | func downloadFileViaGit(ctx context.Context, owner, repo, path, ref, host string) ([]byte, error) { |
| 606 | remoteLog.Printf("Attempting git fallback for %s/%s/%s@%s", owner, repo, path, ref) |
| 607 | |
| 608 | // First, try via raw.githubusercontent.com — no auth required for public repos and |
| 609 | // no dependency on git being installed. |
| 610 | // Only attempt raw URL for github.com repos (not GHE) since raw.githubusercontent.com |
| 611 | // only serves public GitHub content. |
| 612 | if host == "" || host == "github.com" { |
| 613 | content, rawErr := downloadFileViaRawURL(ctx, owner, repo, path, ref) |
| 614 | if rawErr == nil { |
| 615 | return content, nil |
| 616 | } |
| 617 | remoteLog.Printf("Raw URL download failed for %s/%s/%s@%s, trying git archive: %v", owner, repo, path, ref, rawErr) |
| 618 | } |
| 619 | |
| 620 | // Use git archive to get the file content without cloning |
| 621 | // This works for public repositories without authentication |
| 622 | var githubHost string |
| 623 | if host != "" { |
| 624 | githubHost = "https://" + host |
| 625 | } else { |
| 626 | githubHost = GetGitHubHostForRepo(owner, repo) |
| 627 | } |
| 628 | repoURL := fmt.Sprintf("%s/%s/%s.git", githubHost, owner, repo) |
| 629 | |
| 630 | // git archive command: git archive --remote=<repo> <ref> <path> |
| 631 | // #nosec G204 -- repoURL, ref, and path are from workflow import configuration authored by the |
| 632 | // developer; exec.CommandContext with separate args (not shell execution) prevents shell injection. |
| 633 | cmd := exec.CommandContext(ctx, "git", "archive", "--remote="+repoURL, ref, path) |
| 634 | archiveOutput, err := cmd.Output() |
| 635 | if err != nil { |
| 636 | // If git archive fails, try with git clone + git show as a fallback |
| 637 | return downloadFileViaGitClone(owner, repo, path, ref, host) |
| 638 | } |
| 639 | |
| 640 | // Extract the file from the tar archive using Go's archive/tar (cross-platform) |
| 641 | content, err := fileutil.ExtractFileFromTar(archiveOutput, path) |
| 642 | if err != nil { |
| 643 | return nil, fmt.Errorf("failed to extract file from git archive: %w", err) |
| 644 | } |
| 645 | |
| 646 | remoteLog.Printf("Successfully downloaded file via git archive: %s/%s/%s@%s", owner, repo, path, ref) |
| 647 | return content, nil |
| 648 | } |
| 649 | |
| 650 | // downloadFileViaRawURL fetches a file using the raw.githubusercontent.com URL. |
| 651 | // This requires no authentication for public repositories and no git installation. |
no test coverage detected