github.com/argoproj/argo-cd/v3@v3.2.1/applicationset/services/pull_request/github.go (about) 1 package pull_request 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "os" 8 9 "github.com/google/go-github/v69/github" 10 11 appsetutils "github.com/argoproj/argo-cd/v3/applicationset/utils" 12 ) 13 14 type GithubService struct { 15 client *github.Client 16 owner string 17 repo string 18 labels []string 19 } 20 21 var _ PullRequestService = (*GithubService)(nil) 22 23 func NewGithubService(token, url, owner, repo string, labels []string, optionalHTTPClient ...*http.Client) (PullRequestService, error) { 24 // Undocumented environment variable to set a default token, to be used in testing to dodge anonymous rate limits. 25 if token == "" { 26 token = os.Getenv("GITHUB_TOKEN") 27 } 28 29 var client *github.Client 30 httpClient := appsetutils.GetOptionalHTTPClient(optionalHTTPClient...) 31 32 if url == "" { 33 if token == "" { 34 client = github.NewClient(httpClient) 35 } else { 36 client = github.NewClient(httpClient).WithAuthToken(token) 37 } 38 } else { 39 var err error 40 if token == "" { 41 client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url) 42 } else { 43 client, err = github.NewClient(httpClient).WithAuthToken(token).WithEnterpriseURLs(url, url) 44 } 45 if err != nil { 46 return nil, err 47 } 48 } 49 return &GithubService{ 50 client: client, 51 owner: owner, 52 repo: repo, 53 labels: labels, 54 }, nil 55 } 56 57 func (g *GithubService) List(ctx context.Context) ([]*PullRequest, error) { 58 opts := &github.PullRequestListOptions{ 59 ListOptions: github.ListOptions{ 60 PerPage: 100, 61 }, 62 } 63 pullRequests := []*PullRequest{} 64 for { 65 pulls, resp, err := g.client.PullRequests.List(ctx, g.owner, g.repo, opts) 66 if err != nil { 67 if resp != nil && resp.StatusCode == http.StatusNotFound { 68 // return a custom error indicating that the repository is not found, 69 // but also returning the empty result since the decision to continue or not in this case is made by the caller 70 return pullRequests, NewRepositoryNotFoundError(err) 71 } 72 return nil, fmt.Errorf("error listing pull requests for %s/%s: %w", g.owner, g.repo, err) 73 } 74 for _, pull := range pulls { 75 if !containLabels(g.labels, pull.Labels) { 76 continue 77 } 78 pullRequests = append(pullRequests, &PullRequest{ 79 Number: *pull.Number, 80 Title: *pull.Title, 81 Branch: *pull.Head.Ref, 82 TargetBranch: *pull.Base.Ref, 83 HeadSHA: *pull.Head.SHA, 84 Labels: getGithubPRLabelNames(pull.Labels), 85 Author: *pull.User.Login, 86 }) 87 } 88 if resp.NextPage == 0 { 89 break 90 } 91 opts.Page = resp.NextPage 92 } 93 return pullRequests, nil 94 } 95 96 // containLabels returns true if gotLabels contains expectedLabels 97 func containLabels(expectedLabels []string, gotLabels []*github.Label) bool { 98 for _, expected := range expectedLabels { 99 found := false 100 for _, got := range gotLabels { 101 if got.Name == nil { 102 continue 103 } 104 if expected == *got.Name { 105 found = true 106 break 107 } 108 } 109 if !found { 110 return false 111 } 112 } 113 return true 114 } 115 116 // Get the Github pull request label names. 117 func getGithubPRLabelNames(gitHubLabels []*github.Label) []string { 118 var labelNames []string 119 for _, gitHubLabel := range gitHubLabels { 120 labelNames = append(labelNames, *gitHubLabel.Name) 121 } 122 return labelNames 123 }