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

     1  package pull_request
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	bitbucketv1 "github.com/gfleury/go-bitbucket-v1"
     9  	log "github.com/sirupsen/logrus"
    10  
    11  	"github.com/argoproj/argo-cd/v3/applicationset/services"
    12  )
    13  
    14  type BitbucketService struct {
    15  	client         *bitbucketv1.APIClient
    16  	projectKey     string
    17  	repositorySlug string
    18  	// Not supported for PRs by Bitbucket Server
    19  	// labels         []string
    20  }
    21  
    22  var _ PullRequestService = (*BitbucketService)(nil)
    23  
    24  func NewBitbucketServiceBasicAuth(ctx context.Context, username, password, url, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
    25  	bitbucketConfig := bitbucketv1.NewConfiguration(url)
    26  	// Avoid the XSRF check
    27  	bitbucketConfig.AddDefaultHeader("x-atlassian-token", "no-check")
    28  	bitbucketConfig.AddDefaultHeader("x-requested-with", "XMLHttpRequest")
    29  
    30  	ctx = context.WithValue(ctx, bitbucketv1.ContextBasicAuth, bitbucketv1.BasicAuth{
    31  		UserName: username,
    32  		Password: password,
    33  	})
    34  	return newBitbucketService(ctx, bitbucketConfig, projectKey, repositorySlug, scmRootCAPath, insecure, caCerts)
    35  }
    36  
    37  func NewBitbucketServiceBearerToken(ctx context.Context, bearerToken, url, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
    38  	bitbucketConfig := bitbucketv1.NewConfiguration(url)
    39  	// Avoid the XSRF check
    40  	bitbucketConfig.AddDefaultHeader("x-atlassian-token", "no-check")
    41  	bitbucketConfig.AddDefaultHeader("x-requested-with", "XMLHttpRequest")
    42  
    43  	ctx = context.WithValue(ctx, bitbucketv1.ContextAccessToken, bearerToken)
    44  	return newBitbucketService(ctx, bitbucketConfig, projectKey, repositorySlug, scmRootCAPath, insecure, caCerts)
    45  }
    46  
    47  func NewBitbucketServiceNoAuth(ctx context.Context, url, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
    48  	return newBitbucketService(ctx, bitbucketv1.NewConfiguration(url), projectKey, repositorySlug, scmRootCAPath, insecure, caCerts)
    49  }
    50  
    51  func newBitbucketService(ctx context.Context, bitbucketConfig *bitbucketv1.Configuration, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
    52  	bbClient := services.SetupBitbucketClient(ctx, bitbucketConfig, scmRootCAPath, insecure, caCerts)
    53  
    54  	return &BitbucketService{
    55  		client:         bbClient,
    56  		projectKey:     projectKey,
    57  		repositorySlug: repositorySlug,
    58  	}, nil
    59  }
    60  
    61  func (b *BitbucketService) List(_ context.Context) ([]*PullRequest, error) {
    62  	paged := map[string]any{
    63  		"limit": 100,
    64  	}
    65  
    66  	pullRequests := []*PullRequest{}
    67  	for {
    68  		response, err := b.client.DefaultApi.GetPullRequestsPage(b.projectKey, b.repositorySlug, paged)
    69  		if err != nil {
    70  			if response != nil && response.Response != nil && response.StatusCode == http.StatusNotFound {
    71  				// return a custom error indicating that the repository is not found,
    72  				// but also return the empty result since the decision to continue or not in this case is made by the caller
    73  				return pullRequests, NewRepositoryNotFoundError(err)
    74  			}
    75  			return nil, fmt.Errorf("error listing pull requests for %s/%s: %w", b.projectKey, b.repositorySlug, err)
    76  		}
    77  		pulls, err := bitbucketv1.GetPullRequestsResponse(response)
    78  		if err != nil {
    79  			log.Errorf("error parsing pull request response '%v'", response.Values)
    80  			return nil, fmt.Errorf("error parsing pull request response for %s/%s: %w", b.projectKey, b.repositorySlug, err)
    81  		}
    82  
    83  		for _, pull := range pulls {
    84  			pullRequests = append(pullRequests, &PullRequest{
    85  				Number:       pull.ID,
    86  				Title:        pull.Title,
    87  				Branch:       pull.FromRef.DisplayID, // ID: refs/heads/main DisplayID: main
    88  				TargetBranch: pull.ToRef.DisplayID,
    89  				HeadSHA:      pull.FromRef.LatestCommit, // This is not defined in the official docs, but works in practice
    90  				Labels:       []string{},                // Not supported by library
    91  				Author:       pull.Author.User.Name,
    92  			})
    93  		}
    94  
    95  		hasNextPage, nextPageStart := bitbucketv1.HasNextPage(response)
    96  		if !hasNextPage {
    97  			break
    98  		}
    99  		paged["start"] = nextPageStart
   100  	}
   101  	return pullRequests, nil
   102  }