github.com/argoproj/argo-cd/v3@v3.2.1/applicationset/services/pull_request/gitlab.go (about)

     1  package pull_request
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  	"os"
     8  
     9  	"github.com/hashicorp/go-retryablehttp"
    10  	gitlab "gitlab.com/gitlab-org/api/client-go"
    11  
    12  	"github.com/argoproj/argo-cd/v3/applicationset/utils"
    13  )
    14  
    15  type GitLabService struct {
    16  	client           *gitlab.Client
    17  	project          string
    18  	labels           []string
    19  	pullRequestState string
    20  }
    21  
    22  var _ PullRequestService = (*GitLabService)(nil)
    23  
    24  func NewGitLabService(token, url, project string, labels []string, pullRequestState string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
    25  	var clientOptionFns []gitlab.ClientOptionFunc
    26  
    27  	// Set a custom Gitlab base URL if one is provided
    28  	if url != "" {
    29  		clientOptionFns = append(clientOptionFns, gitlab.WithBaseURL(url))
    30  	}
    31  
    32  	if token == "" {
    33  		token = os.Getenv("GITLAB_TOKEN")
    34  	}
    35  
    36  	tr := http.DefaultTransport.(*http.Transport).Clone()
    37  	tr.TLSClientConfig = utils.GetTlsConfig(scmRootCAPath, insecure, caCerts)
    38  
    39  	retryClient := retryablehttp.NewClient()
    40  	retryClient.HTTPClient.Transport = tr
    41  
    42  	clientOptionFns = append(clientOptionFns, gitlab.WithHTTPClient(retryClient.HTTPClient))
    43  
    44  	client, err := gitlab.NewClient(token, clientOptionFns...)
    45  	if err != nil {
    46  		return nil, fmt.Errorf("error creating Gitlab client: %w", err)
    47  	}
    48  
    49  	return &GitLabService{
    50  		client:           client,
    51  		project:          project,
    52  		labels:           labels,
    53  		pullRequestState: pullRequestState,
    54  	}, nil
    55  }
    56  
    57  func (g *GitLabService) List(ctx context.Context) ([]*PullRequest, error) {
    58  	// Filter the merge requests on labels, if they are specified.
    59  	var labels *gitlab.LabelOptions
    60  	if len(g.labels) > 0 {
    61  		var labelsList gitlab.LabelOptions = g.labels
    62  		labels = &labelsList
    63  	}
    64  	opts := &gitlab.ListProjectMergeRequestsOptions{
    65  		ListOptions: gitlab.ListOptions{
    66  			PerPage: 100,
    67  		},
    68  		Labels: labels,
    69  	}
    70  
    71  	if g.pullRequestState != "" {
    72  		opts.State = &g.pullRequestState
    73  	}
    74  
    75  	pullRequests := []*PullRequest{}
    76  	for {
    77  		mrs, resp, err := g.client.MergeRequests.ListProjectMergeRequests(g.project, opts, gitlab.WithContext(ctx))
    78  		if err != nil {
    79  			if resp != nil && resp.StatusCode == http.StatusNotFound {
    80  				// return a custom error indicating that the repository is not found,
    81  				// but also returning the empty result since the decision to continue or not in this case is made by the caller
    82  				return pullRequests, NewRepositoryNotFoundError(err)
    83  			}
    84  			return nil, fmt.Errorf("error listing merge requests for project '%s': %w", g.project, err)
    85  		}
    86  		for _, mr := range mrs {
    87  			pullRequests = append(pullRequests, &PullRequest{
    88  				Number:       mr.IID,
    89  				Title:        mr.Title,
    90  				Branch:       mr.SourceBranch,
    91  				TargetBranch: mr.TargetBranch,
    92  				HeadSHA:      mr.SHA,
    93  				Labels:       mr.Labels,
    94  				Author:       mr.Author.Username,
    95  			})
    96  		}
    97  		if resp.NextPage == 0 {
    98  			break
    99  		}
   100  		opts.Page = resp.NextPage
   101  	}
   102  	return pullRequests, nil
   103  }