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  }