diff --git a/README.md b/README.md index 234ee6b4..64aecc29 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Currently supported providers are: [GitHub](#github), [Bitbucket Server](#bitbuc - [Get Commit Status](#get-commit-status) - [Create Pull Request](#create-pull-request) - [Update Pull Request](#update-pull-request) + - [Get Pull Request By ID](#get-pull-request) - [List Open Pull Requests](#list-open-pull-requests) - [List Open Pull Requests With Body](#list-open-pull-requests-with-body) - [Add Pull Request Comment](#add-pull-request-comment) @@ -383,6 +384,21 @@ repository := "jfrog-cli" openPullRequests, err := client.ListOpenPullRequests(ctx, owner, repository) ``` +#### Get Pull Request By ID + +```go +// Go context +ctx := context.Background() +// Organization or username +owner := "jfrog" +// VCS repository +repository := "jfrog-cli" +// Pull Request ID +pullRequestId := 1 + +openPullRequests, err := client.GetPullRequestByID(ctx, owner, repository, pullRequestId) +``` + ##### Add Pull Request Comment ```go diff --git a/vcsclient/azurerepos.go b/vcsclient/azurerepos.go index 158242fe..0af12767 100644 --- a/vcsclient/azurerepos.go +++ b/vcsclient/azurerepos.go @@ -283,29 +283,29 @@ func (client *AzureReposClient) getOpenPullRequests(ctx context.Context, reposit } var pullRequestsInfo []PullRequestInfo for _, pullRequest := range *pullRequests { - var body string - if withBody { - body = *pullRequest.Description - } - // Trim the branches prefix and get the actual branches name - shortSourceName := (*pullRequest.SourceRefName)[strings.LastIndex(*pullRequest.SourceRefName, "/")+1:] - shortTargetName := (*pullRequest.TargetRefName)[strings.LastIndex(*pullRequest.TargetRefName, "/")+1:] - pullRequestsInfo = append(pullRequestsInfo, PullRequestInfo{ - ID: int64(*pullRequest.PullRequestId), - Body: body, - Source: BranchInfo{ - Name: shortSourceName, - Repository: repository, - }, - Target: BranchInfo{ - Name: shortTargetName, - Repository: repository, - }, - }) + pullRequestDetails := parsePullRequestDetails(pullRequest, repository) + pullRequestsInfo = append(pullRequestsInfo, pullRequestDetails) } return pullRequestsInfo, nil } +func (client *AzureReposClient) GetPullRequestByID(ctx context.Context, owner, repository string, pullRequestId int) (pullRequestInfo PullRequestInfo, err error) { + azureReposGitClient, err := client.buildAzureReposClient(ctx) + if err != nil { + return + } + client.logger.Debug(fetchingPullRequestById, repository) + pullRequest, err := azureReposGitClient.GetPullRequestById(ctx, git.GetPullRequestByIdArgs{ + PullRequestId: &pullRequestId, + Project: &client.vcsInfo.Project, + }) + if err != nil { + return + } + pullRequestInfo = parsePullRequestDetails(*pullRequest, repository) + return +} + // GetLatestCommit on Azure Repos func (client *AzureReposClient) GetLatestCommit(ctx context.Context, _, repository, branch string) (CommitInfo, error) { azureReposGitClient, err := client.buildAzureReposClient(ctx) @@ -557,6 +557,31 @@ func (client *AzureReposClient) GetModifiedFiles(ctx context.Context, _, reposit return fileNamesList, nil } +func parsePullRequestDetails(pullRequest git.GitPullRequest, repository string) PullRequestInfo { + // Trim the branches prefix and get the actual branches name + shortSourceName := (*pullRequest.SourceRefName)[strings.LastIndex(*pullRequest.SourceRefName, "/")+1:] + shortTargetName := (*pullRequest.TargetRefName)[strings.LastIndex(*pullRequest.TargetRefName, "/")+1:] + + var prBody string + bodyPtr := pullRequest.Description + if bodyPtr != nil { + prBody = *bodyPtr + } + + return PullRequestInfo{ + ID: int64(*pullRequest.PullRequestId), + Body: prBody, + Source: BranchInfo{ + Name: shortSourceName, + Repository: repository, + }, + Target: BranchInfo{ + Name: shortTargetName, + Repository: repository, + }, + } +} + // mapStatusToString maps commit status enum to string, specific for azure. func mapStatusToString(status CommitStatus) string { conversionMap := map[CommitStatus]string{ diff --git a/vcsclient/azurerepos_test.go b/vcsclient/azurerepos_test.go index 196309be..1aa8b536 100644 --- a/vcsclient/azurerepos_test.go +++ b/vcsclient/azurerepos_test.go @@ -242,6 +242,31 @@ func TestAzureRepos_TestListOpenPullRequests(t *testing.T) { assert.Error(t, err) } +func TestAzureReposClient_GetPullRequest(t *testing.T) { + pullRequestId := 1 + repoName := "repoName" + sourceName := "source" + targetName := "master" + res := git.GitPullRequest{ + SourceRefName: &sourceName, + TargetRefName: &targetName, + PullRequestId: &pullRequestId, + } + jsonRes, err := json.Marshal(res) + assert.NoError(t, err) + ctx := context.Background() + client, cleanUp := createServerAndClient(t, vcsutils.AzureRepos, true, jsonRes, fmt.Sprintf("getPullRequests/%d", pullRequestId), createAzureReposHandler) + defer cleanUp() + pullRequestsInfo, err := client.GetPullRequestByID(ctx, "", repoName, pullRequestId) + assert.NoError(t, err) + assert.True(t, reflect.DeepEqual(pullRequestsInfo, PullRequestInfo{ID: 1, Source: BranchInfo{Name: sourceName, Repository: repoName}, Target: BranchInfo{Name: targetName, Repository: repoName}})) + + badClient, cleanUp := createBadAzureReposClient(t, []byte{}) + defer cleanUp() + _, err = badClient.GetPullRequestByID(ctx, "", repo1, pullRequestId) + assert.Error(t, err) +} + func TestListPullRequestComments(t *testing.T) { type ListPullRequestCommentsResponse struct { Value []git.GitPullRequestCommentThread diff --git a/vcsclient/bitbucketcloud.go b/vcsclient/bitbucketcloud.go index ffd860a3..084270b1 100644 --- a/vcsclient/bitbucketcloud.go +++ b/vcsclient/bitbucketcloud.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "github.com/jfrog/gofrog/datastructures" + "github.com/ktrysmt/go-bitbucket" "net/http" "net/url" "sort" @@ -16,7 +17,6 @@ import ( "github.com/mitchellh/mapstructure" "github.com/jfrog/froggit-go/vcsutils" - "github.com/ktrysmt/go-bitbucket" ) // BitbucketCloudClient API version 2.0 @@ -348,6 +348,41 @@ func (client *BitbucketCloudClient) getOpenPullRequests(ctx context.Context, own return mapBitbucketCloudPullRequestToPullRequestInfo(&parsedPullRequests, withBody), nil } +func (client *BitbucketCloudClient) GetPullRequestByID(ctx context.Context, owner, repository string, pullRequestId int) (pullRequestInfo PullRequestInfo, err error) { + err = validateParametersNotBlank(map[string]string{"owner": owner, "repository": repository}) + if err != nil { + return + } + bitbucketClient := client.buildBitbucketCloudClient(ctx) + client.logger.Debug(fetchingPullRequestById, repository) + prIdStr := strconv.Itoa(pullRequestId) + options := &bitbucket.PullRequestsOptions{ + Owner: owner, + RepoSlug: repository, + ID: prIdStr, + } + pullRequestRaw, err := bitbucketClient.Repositories.PullRequests.Get(options) + if err != nil { + return + } + pullRequestDetails, err := vcsutils.RemapFields[pullRequestsDetails](pullRequestRaw, "json") + if err != nil { + return + } + pullRequestInfo = PullRequestInfo{ + ID: pullRequestDetails.ID, + Source: BranchInfo{ + Name: pullRequestDetails.Source.Name.Str, + Repository: pullRequestDetails.Source.Repository.Name, + }, + Target: BranchInfo{ + Name: pullRequestDetails.Target.Name.Str, + Repository: pullRequestDetails.Target.Repository.Name, + }, + } + return +} + // AddPullRequestComment on Bitbucket cloud func (client *BitbucketCloudClient) AddPullRequestComment(ctx context.Context, owner, repository, content string, pullRequestID int) error { err := validateParametersNotBlank(map[string]string{"owner": owner, "repository": repository, "content": content}) diff --git a/vcsclient/bitbucketcloud_test.go b/vcsclient/bitbucketcloud_test.go index b9bf4a2b..832d456d 100644 --- a/vcsclient/bitbucketcloud_test.go +++ b/vcsclient/bitbucketcloud_test.go @@ -196,6 +196,42 @@ func TestBitbucketCloud_ListOpenPullRequests(t *testing.T) { }, result[0])) } +func TestBitbucketCloudClient_GetPullRequest(t *testing.T) { + pullRequestId := 1 + repoName := "froggit" + ctx := context.Background() + + // Successful Response + response, err := os.ReadFile(filepath.Join("testdata", "bitbucketcloud", "get_pull_request_response.json")) + assert.NoError(t, err) + client, cleanUp := createServerAndClient(t, vcsutils.BitbucketCloud, true, response, + fmt.Sprintf("/repositories/%s/%s/pullrequests/%d", owner, repoName, pullRequestId), createBitbucketCloudHandler) + defer cleanUp() + result, err := client.GetPullRequestByID(ctx, owner, repoName, pullRequestId) + assert.NoError(t, err) + assert.True(t, reflect.DeepEqual(PullRequestInfo{ + ID: int64(pullRequestId), + Source: BranchInfo{Name: "pr", Repository: "workspace/froggit"}, + Target: BranchInfo{Name: "main", Repository: "workspace/froggit"}, + }, result)) + + // Bad Response + badClient, badClientCleanUp := createServerAndClient(t, vcsutils.BitbucketCloud, true, "{", + fmt.Sprintf("/repositories/%s/%s/pullrequests/%d", owner, repoName, pullRequestId), createBitbucketCloudHandler) + defer badClientCleanUp() + _, err = badClient.GetPullRequestByID(ctx, owner, repoName, pullRequestId) + assert.Error(t, err) + + // Bad Fields + badRepoName := "" + badParseClient, badParseClientCleanUp := createServerAndClient(t, vcsutils.BitbucketCloud, true, response, + fmt.Sprintf("/repositories/%s/%s/pullrequests/%d", owner, badRepoName, pullRequestId), createBitbucketCloudHandler) + defer badParseClientCleanUp() + _, err = badParseClient.GetPullRequestByID(ctx, owner, badRepoName, pullRequestId) + assert.Error(t, err) + +} + func TestBitbucketCloud_AddPullRequestComment(t *testing.T) { ctx := context.Background() client, cleanUp := createServerAndClient(t, vcsutils.BitbucketCloud, true, nil, "/repositories/jfrog/repo-1/pullrequests/1/comments", createBitbucketCloudHandler) diff --git a/vcsclient/bitbucketserver.go b/vcsclient/bitbucketserver.go index 48f6bdd4..9a3aa8a2 100644 --- a/vcsclient/bitbucketserver.go +++ b/vcsclient/bitbucketserver.go @@ -397,6 +397,29 @@ func (client *BitbucketServerClient) getOpenPullRequests(ctx context.Context, ow return results, nil } +// GetPullRequestInfoById on bitbucket server +func (client *BitbucketServerClient) GetPullRequestByID(ctx context.Context, owner, repository string, pullRequestId int) (pullRequestInfo PullRequestInfo, err error) { + client.logger.Debug("fetching pull request by ID in ", repository) + bitbucketClient, err := client.buildBitbucketClient(ctx) + if err != nil { + return + } + apiResponse, err := bitbucketClient.GetPullRequest(owner, repository, pullRequestId) + if err != nil || apiResponse.StatusCode != http.StatusOK { + return + } + pullRequest, err := bitbucketv1.GetPullRequestResponse(apiResponse) + if err != nil { + return + } + pullRequestInfo = PullRequestInfo{ + ID: int64(pullRequest.ID), + Source: BranchInfo{Name: pullRequest.FromRef.ID, Repository: pullRequest.ToRef.Repository.Slug}, + Target: BranchInfo{Name: pullRequest.ToRef.ID, Repository: pullRequest.ToRef.Repository.Slug}, + } + return +} + // AddPullRequestComment on Bitbucket server func (client *BitbucketServerClient) AddPullRequestComment(ctx context.Context, owner, repository, content string, pullRequestID int) error { err := validateParametersNotBlank(map[string]string{"owner": owner, "repository": repository, "content": content}) diff --git a/vcsclient/bitbucketserver_test.go b/vcsclient/bitbucketserver_test.go index b6554476..bca3f9d3 100644 --- a/vcsclient/bitbucketserver_test.go +++ b/vcsclient/bitbucketserver_test.go @@ -242,6 +242,36 @@ func TestBitbucketServer_ListOpenPullRequests(t *testing.T) { }, result[0])) } +func TestBitbucketServerClient_GetPullRequest(t *testing.T) { + ctx := context.Background() + response, err := os.ReadFile(filepath.Join("testdata", "bitbucketserver", "get_pull_request_response.json")) + assert.NoError(t, err) + pullRequestId := 6 + + // Successful + client, cleanUp := createServerAndClient(t, vcsutils.BitbucketServer, true, response, + fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/pull-requests/%d", owner, repo1, pullRequestId), createBitbucketServerHandler) + defer cleanUp() + result, err := client.GetPullRequestByID(ctx, owner, repo1, pullRequestId) + require.NoError(t, err) + assert.True(t, reflect.DeepEqual(PullRequestInfo{ + ID: int64(pullRequestId), + Source: BranchInfo{Name: "refs/heads/new_vul_2", Repository: "repoName"}, + Target: BranchInfo{Name: "refs/heads/master", Repository: "repoName"}, + }, result)) + + // Bad response + badClient, badClientCleanUp := createServerAndClient(t, vcsutils.BitbucketServer, true, "{", + fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/pull-requests/%d", owner, repo1, pullRequestId), createBitbucketServerHandler) + defer badClientCleanUp() + _, err2 := badClient.GetPullRequestByID(ctx, owner, repo1, pullRequestId) + require.Error(t, err2) + + // Bad Client + _, err = createBadBitbucketServerClient(t).GetPullRequestByID(ctx, owner, repo1, pullRequestId) + assert.Error(t, err) +} + func TestBitbucketServer_ListPullRequestComments(t *testing.T) { ctx := context.Background() response, err := os.ReadFile(filepath.Join("testdata", "bitbucketserver", "pull_request_comments_list_response.json")) diff --git a/vcsclient/github.go b/vcsclient/github.go index 08ddc16f..34585fcf 100644 --- a/vcsclient/github.go +++ b/vcsclient/github.go @@ -3,6 +3,7 @@ package vcsclient import ( "context" "encoding/json" + "errors" "fmt" "github.com/jfrog/gofrog/datastructures" "io" @@ -318,6 +319,47 @@ func (client *GitHubClient) getOpenPullRequests(ctx context.Context, owner, repo return mapGitHubPullRequestToPullRequestInfoList(pullRequests, withBody) } +func (client *GitHubClient) GetPullRequestByID(ctx context.Context, owner, repository string, pullRequestId int) (PullRequestInfo, error) { + ghClient, err := client.buildGithubClient(ctx) + if err != nil { + return PullRequestInfo{}, err + } + client.logger.Debug(fetchingPullRequestById, repository) + pullRequest, response, err := ghClient.PullRequests.Get(ctx, owner, repository, pullRequestId) + if err != nil || response.StatusCode != http.StatusOK { + return PullRequestInfo{}, err + } + + sourceBranch, err1 := extractBranchFromLabel(*pullRequest.Head.Label) + targetBranch, err2 := extractBranchFromLabel(*pullRequest.Base.Label) + err = errors.Join(err1, err2) + if err != nil { + return PullRequestInfo{}, err + } + + prInfo := PullRequestInfo{ + ID: int64(pullRequestId), + Source: BranchInfo{ + Name: sourceBranch, + Repository: *pullRequest.Head.Repo.Name, + }, + Target: BranchInfo{ + Name: targetBranch, + Repository: *pullRequest.Base.Repo.Name, + }, + } + return prInfo, nil +} + +// Extracts branch name from the following expected label format repo:branch +func extractBranchFromLabel(label string) (string, error) { + split := strings.Split(label, ":") + if len(split) <= 1 { + return "", fmt.Errorf("bad label format %s", label) + } + return split[1], nil +} + // AddPullRequestComment on GitHub func (client *GitHubClient) AddPullRequestComment(ctx context.Context, owner, repository, content string, pullRequestID int) error { err := validateParametersNotBlank(map[string]string{"owner": owner, "repository": repository, "content": content}) diff --git a/vcsclient/github_test.go b/vcsclient/github_test.go index e7183b75..2c9b9480 100644 --- a/vcsclient/github_test.go +++ b/vcsclient/github_test.go @@ -562,6 +562,47 @@ func TestGitHubClient_ListOpenPullRequests(t *testing.T) { assert.Error(t, err) } +func TestGitHubClient_GetPullRequestByID(t *testing.T) { + ctx := context.Background() + pullRequestId := 1 + repoName := "Hello-World" + + // Successful response + response, err := os.ReadFile(filepath.Join("testdata", "github", "pull_request_info_response.json")) + assert.NoError(t, err) + client, cleanUp := createServerAndClient(t, vcsutils.GitHub, false, response, + fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repoName, pullRequestId), createGitHubHandler) + defer cleanUp() + result, err := client.GetPullRequestByID(ctx, owner, repoName, pullRequestId) + assert.NoError(t, err) + assert.True(t, reflect.DeepEqual(PullRequestInfo{ + ID: int64(pullRequestId), + Source: BranchInfo{Name: "new-topic", Repository: "Hello-World"}, + Target: BranchInfo{Name: "master", Repository: "Hello-World"}, + }, result)) + + // Bad Labels + badLabels, err := os.ReadFile(filepath.Join("testdata", "github", "pull_request_info_response_bad_labels.json")) + assert.NoError(t, err) + badLabelsClient, badLabelClientCleanUp := createServerAndClient(t, vcsutils.GitHub, false, badLabels, + fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repoName, pullRequestId), createGitHubHandler) + defer badLabelClientCleanUp() + _, err = badLabelsClient.GetPullRequestByID(ctx, owner, repoName, pullRequestId) + assert.Error(t, err) + + // Bad client + _, err = createBadGitHubClient(t).GetPullRequestByID(ctx, owner, repoName, pullRequestId) + assert.Error(t, err) + + // Bad Response + badResponseClient, badResponseCleanUp := createServerAndClient(t, vcsutils.GitHub, false, "{", + fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repoName, pullRequestId), createGitHubHandler) + defer badResponseCleanUp() + _, err = badResponseClient.GetPullRequestByID(ctx, owner, repoName, pullRequestId) + assert.Error(t, err) + +} + func TestGitHubClient_ListPullRequestComments(t *testing.T) { ctx := context.Background() response, err := os.ReadFile(filepath.Join("testdata", "github", "pull_request_comments_list_response.json")) diff --git a/vcsclient/gitlab.go b/vcsclient/gitlab.go index 936e0733..f6af421a 100644 --- a/vcsclient/gitlab.go +++ b/vcsclient/gitlab.go @@ -274,6 +274,21 @@ func (client *GitLabClient) getOpenPullRequests(ctx context.Context, repository return mapGitLabMergeRequestToPullRequestInfoList(mergeRequests, withBody), nil } +// GetPullRequestInfoById on GitLab +func (client *GitLabClient) GetPullRequestByID(ctx context.Context, owner, repository string, pullRequestId int) (pullRequestInfo PullRequestInfo, err error) { + client.logger.Debug("fetching merge requests by ID in", repository) + mergeRequest, response, err := client.glClient.MergeRequests.GetMergeRequest(getProjectID(owner, repository), pullRequestId, nil) + if err != nil || response.StatusCode != http.StatusOK { + return PullRequestInfo{}, err + } + pullRequestInfo = PullRequestInfo{ + ID: int64(mergeRequest.ID), + Source: BranchInfo{Name: mergeRequest.SourceBranch}, + Target: BranchInfo{Name: mergeRequest.TargetBranch}, + } + return +} + // AddPullRequestComment on GitLab func (client *GitLabClient) AddPullRequestComment(ctx context.Context, owner, repository, content string, pullRequestID int) error { err := validateParametersNotBlank(map[string]string{"owner": owner, "repository": repository, "content": content}) diff --git a/vcsclient/gitlab_test.go b/vcsclient/gitlab_test.go index c701bf14..1c071f12 100644 --- a/vcsclient/gitlab_test.go +++ b/vcsclient/gitlab_test.go @@ -243,6 +243,34 @@ func TestGitLabClient_ListOpenPullRequests(t *testing.T) { }, result[0])) } +func TestGitLabClient_GetPullRequestByID(t *testing.T) { + ctx := context.Background() + repoName := "repo" + pullRequestId := 1 + + // Successful response + response, err := os.ReadFile(filepath.Join("testdata", "gitlab", "get_merge_request_response.json")) + assert.NoError(t, err) + client, cleanUp := createServerAndClient(t, vcsutils.GitLab, false, response, + fmt.Sprintf("/api/v4/projects/%s/merge_requests/%d", url.PathEscape(owner+"/"+repoName), pullRequestId), createGitLabHandler) + defer cleanUp() + result, err := client.GetPullRequestByID(ctx, owner, repoName, pullRequestId) + assert.NoError(t, err) + assert.True(t, reflect.DeepEqual(PullRequestInfo{ + ID: 1, + Source: BranchInfo{Name: "manual-job-rules", Repository: ""}, + Target: BranchInfo{Name: "master", Repository: ""}, + }, result)) + + // Bad client + badClient, badClientCleanUp := createServerAndClient(t, vcsutils.GitLab, false, "", + fmt.Sprintf("/api/v4/projects/%s/merge_requests/%d", url.PathEscape(owner+"/"+repoName), pullRequestId), createGitLabHandler) + defer badClientCleanUp() + _, err = badClient.GetPullRequestByID(ctx, owner, repoName, pullRequestId) + assert.Error(t, err) + +} + func TestGitLabClient_GetLatestCommit(t *testing.T) { ctx := context.Background() response, err := os.ReadFile(filepath.Join("testdata", "gitlab", "commit_list_response.json")) diff --git a/vcsclient/logger.go b/vcsclient/logger.go index daccb3b1..4555e313 100644 --- a/vcsclient/logger.go +++ b/vcsclient/logger.go @@ -7,6 +7,7 @@ const ( updatingPullRequest = "Updating details of pull request ID:" fetchingOpenPullRequests = "Fetching open pull requests in" + fetchingPullRequestById = "Fetching pull requests by id in" uploadingCodeScanning = "Uploading code scanning for:" ) diff --git a/vcsclient/testdata/azurerepos/resourcesResponse.json b/vcsclient/testdata/azurerepos/resourcesResponse.json index 78bf637b..6715abbb 100644 --- a/vcsclient/testdata/azurerepos/resourcesResponse.json +++ b/vcsclient/testdata/azurerepos/resourcesResponse.json @@ -99,6 +99,15 @@ "minVersion": "3.2", "maxVersion": "7.1", "releasedVersion": "0.0" + } , { + "id": "01a46dea-7d46-4d40-bc84-319e7c260d99", + "area": "Location", + "resourceName": "ResourceAreas", + "routeTemplate": "_apis/{resource}/{areaId}/getPullRequests/{pullRequestId}", + "resourceVersion": 1, + "minVersion": "3.2", + "maxVersion": "7.1", + "releasedVersion": "0.0" } ], "count": 2 diff --git a/vcsclient/testdata/bitbucketcloud/get_pull_request_response.json b/vcsclient/testdata/bitbucketcloud/get_pull_request_response.json new file mode 100644 index 00000000..97db1e97 --- /dev/null +++ b/vcsclient/testdata/bitbucketcloud/get_pull_request_response.json @@ -0,0 +1,161 @@ +{ + "comment_count": 0, + "task_count": 0, + "type": "pullrequest", + "id": 1, + "title": "s", + "description": "s", + "rendered": { + "title": { + "type": "rendered", + "raw": "s", + "markup": "markdown", + "html": "

s

" + }, + "description": { + "type": "rendered", + "raw": "s", + "markup": "markdown", + "html": "

s

" + } + }, + "state": "CLOSED", + "merge_commit": null, + "close_source_branch": false, + "closed_by": null, + "author": { + "display_name": "fname lname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0488ed53-e751-4504-a343-1a43d72590a4%7D" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/4a0ffac6cc540dd6983b35ec3bd4df94?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FED-1.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0488ed53-e751-4504-a343-1a43d72590a4%7D/" + } + }, + "type": "user", + "uuid": "{0488ed53-e751-4504-a343-1a43d72590a4}", + "account_id": "63f32b584e86f362d399cdc2", + "nickname": "fname lname" + }, + "reason": "", + "created_on": "2023-06-20T09:00:47.082738+00:00", + "updated_on": "2023-06-20T09:00:47.725250+00:00", + "destination": { + "branch": { + "name": "main" + }, + "commit": { + "type": "commit", + "hash": "9a1e81efaa1c", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/commit/9a1e81efaa1c" + }, + "html": { + "href": "https://bitbucket.org/workspace/froggit/commits/9a1e81efaa1c" + } + } + }, + "repository": { + "type": "repository", + "full_name": "workspace/froggit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit" + }, + "html": { + "href": "https://bitbucket.org/workspace/froggit" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7Bacb2b52e-67f2-48bf-96f1-b441b5acb810%7D?ts=default" + } + }, + "name": "froggit", + "uuid": "{acb2b52e-67f2-48bf-96f1-b441b5acb810}" + } + }, + "source": { + "branch": { + "name": "pr" + }, + "commit": { + "type": "commit", + "hash": "18f5e1ecb37e", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/commit/18f5e1ecb37e" + }, + "html": { + "href": "https://bitbucket.org/workspace/froggit/commits/18f5e1ecb37e" + } + } + }, + "repository": { + "type": "repository", + "full_name": "workspace/froggit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit" + }, + "html": { + "href": "https://bitbucket.org/workspace/froggit" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7Bacb2b52e-67f2-48bf-96f1-b441b5acb810%7D?ts=default" + } + }, + "name": "froggit", + "uuid": "{acb2b52e-67f2-48bf-96f1-b441b5acb810}" + } + }, + "reviewers": [], + "participants": [], + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/pullrequests/1" + }, + "html": { + "href": "https://bitbucket.org/workspace/froggit/pull-requests/1" + }, + "commits": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/pullrequests/1/commits" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/pullrequests/1/approve" + }, + "request-changes": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/pullrequests/1/request-changes" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/diff/workspace/froggit:18f5e1ecb37e%0D9a1e81efaa1c?from_pullrequest_id=1&topic=true" + }, + "diffstat": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/diffstat/workspace/froggit:18f5e1ecb37e%0D9a1e81efaa1c?from_pullrequest_id=1&topic=true" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/pullrequests/1/comments" + }, + "activity": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/pullrequests/1/activity" + }, + "merge": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/pullrequests/1/merge" + }, + "decline": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/pullrequests/1/decline" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/workspace/froggit/pullrequests/1/statuses" + } + }, + "summary": { + "type": "rendered", + "raw": "s", + "markup": "markdown", + "html": "

s

" + } +} \ No newline at end of file diff --git a/vcsclient/testdata/bitbucketserver/get_pull_request_response.json b/vcsclient/testdata/bitbucketserver/get_pull_request_response.json new file mode 100644 index 00000000..b90da2f0 --- /dev/null +++ b/vcsclient/testdata/bitbucketserver/get_pull_request_response.json @@ -0,0 +1,258 @@ +{ + "id": 6, + "version": 0, + "title": "New vul 2", + "description": "* add vul\n* test", + "state": "OPEN", + "open": true, + "closed": false, + "createdDate": 1686651080688, + "updatedDate": 1686651080688, + "fromRef": { + "id": "refs/heads/new_vul_2", + "displayId": "new_vul_2", + "latestCommit": "7121b72f7c2a4bdd953bcddd80c037cb598db690", + "type": "BRANCH", + "repository": { + "slug": "repoName", + "id": 35731, + "name": "repoName", + "hierarchyId": "38d6f6b604eee2af0b68", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "origin": { + "slug": "repoName", + "id": 115, + "name": "repoName", + "hierarchyId": "38d6f3b609eee2af0b68", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "repoName", + "id": 100, + "name": "repoName", + "description": "repoName", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "https://git.bbServerHost.info/projects/repoName" + } + ] + } + }, + "public": false, + "archived": false, + "links": { + "clone": [ + { + "href": "https://git.bbServerHost.info/scm/repoName/repoName.git", + "name": "http" + }, + { + "href": "ssh://git@git.bbServerHost.info/repoName/repoName.git", + "name": "ssh" + } + ], + "self": [ + { + "href": "https://git.bbServerHost.info/projects/repoName/repos/repoName/browse" + } + ] + } + }, + "project": { + "key": "~owner", + "id": 2424, + "name": "some name", + "type": "PERSONAL", + "owner": { + "name": "owner", + "emailAddress": "owner@bbServerHost.com", + "active": true, + "displayName": "some name", + "id": 2118757, + "slug": "owner", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "https://git.bbServerHost.info/users/owner" + } + ] + } + }, + "links": { + "self": [ + { + "href": "https://git.bbServerHost.info/users/owner" + } + ] + } + }, + "public": false, + "archived": false, + "links": { + "clone": [ + { + "href": "ssh://git@git.bbServerHost.info/~owner/repoName.git", + "name": "ssh" + }, + { + "href": "https://git.bbServerHost.info/scm/~owner/repoName.git", + "name": "http" + } + ], + "self": [ + { + "href": "https://git.bbServerHost.info/users/owner/repos/repoName/browse" + } + ] + } + } + }, + "toRef": { + "id": "refs/heads/master", + "displayId": "master", + "latestCommit": "49ee0968441e2cae00e714c1d7852a6565ce12c7", + "type": "BRANCH", + "repository": { + "slug": "repoName", + "id": 32731, + "name": "repoName", + "hierarchyId": "38d6f4b609eee2af0b68", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "origin": { + "slug": "repoName", + "id": 1215, + "name": "repoName", + "hierarchyId": "38f6f6b609eee2af0b68", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "repoName", + "id": 1210, + "name": "repoName", + "description": "repoName", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "https://git.bbServerHost.info/projects/repoName" + } + ] + } + }, + "public": false, + "archived": false, + "links": { + "clone": [ + { + "href": "https://git.bbServerHost.info/scm/repoName/repoName.git", + "name": "http" + }, + { + "href": "ssh://git@git.bbServerHost.info/repoName/repoName.git", + "name": "ssh" + } + ], + "self": [ + { + "href": "https://git.bbServerHost.info/projects/repoName/repos/repoName/browse" + } + ] + } + }, + "project": { + "key": "~owner", + "id": 2424, + "name": "some name", + "type": "PERSONAL", + "owner": { + "name": "owner", + "emailAddress": "owner@bbServerHost.com", + "active": true, + "displayName": "some name", + "id": 2198757, + "slug": "owner", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "https://git.bbServerHost.info/users/owner" + } + ] + } + }, + "links": { + "self": [ + { + "href": "https://git.bbServerHost.info/users/owner" + } + ] + } + }, + "public": false, + "archived": false, + "links": { + "clone": [ + { + "href": "ssh://git@git.bbServerHost.info/~owner/repoName.git", + "name": "ssh" + }, + { + "href": "https://git.bbServerHost.info/scm/~owner/repoName.git", + "name": "http" + } + ], + "self": [ + { + "href": "https://git.bbServerHost.info/users/owner/repos/repoName/browse" + } + ] + } + } + }, + "locked": false, + "author": { + "user": { + "name": "owner", + "emailAddress": "owner@bbServerHost.com", + "active": true, + "displayName": "some name", + "id": 2114757, + "slug": "owner", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "https://git.bbServerHost.info/users/owner" + } + ] + } + }, + "role": "AUTHOR", + "approved": false, + "status": "UNAPPROVED" + }, + "reviewers": [], + "participants": [], + "links": { + "self": [ + { + "href": "https://git.bbServerHost.info/users/owner/repos/repoName/pull-requests/6" + } + ] + } +} \ No newline at end of file diff --git a/vcsclient/testdata/github/pull_request_info_response.json b/vcsclient/testdata/github/pull_request_info_response.json new file mode 100644 index 00000000..cd5f5c8a --- /dev/null +++ b/vcsclient/testdata/github/pull_request_info_response.json @@ -0,0 +1,536 @@ +{ + "url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347", + "id": 1, + "node_id": "MDExOlB1bGxSZXF1ZXN0MQ==", + "html_url": "https://github.com/octocat/Hello-World/pull/1347", + "diff_url": "https://github.com/octocat/Hello-World/pull/1347.diff", + "patch_url": "https://github.com/octocat/Hello-World/pull/1347.patch", + "issue_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/commits", + "review_comments_url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments", + "review_comment_url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347/comments", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "number": 1347, + "state": "open", + "locked": true, + "title": "Amazing new feature", + "user": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "body": "Please pull these awesome changes in!", + "labels": [ + { + "id": 208045946, + "node_id": "MDU6TGFiZWwyMDgwNDU5NDY=", + "url": "https://api.github.com/repos/octocat/Hello-World/labels/bug", + "name": "bug", + "description": "Something isn't working", + "color": "f29513", + "default": true + } + ], + "milestone": { + "url": "https://api.github.com/repos/octocat/Hello-World/milestones/1", + "html_url": "https://github.com/octocat/Hello-World/milestones/v1.0", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/milestones/1/labels", + "id": 1002604, + "node_id": "MDk6TWlsZXN0b25lMTAwMjYwNA==", + "number": 1, + "state": "open", + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "open_issues": 4, + "closed_issues": 8, + "created_at": "2011-04-10T20:09:31Z", + "updated_at": "2014-03-03T18:58:10Z", + "closed_at": "2013-02-12T13:22:01Z", + "due_on": "2012-10-09T23:39:01Z" + }, + "active_lock_reason": "too heated", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:01:12Z", + "closed_at": "2011-01-26T19:01:12Z", + "merged_at": "2011-01-26T19:01:12Z", + "merge_commit_sha": "e5bd3914e2e596debea16f433f57875b5b90bcd6", + "assignee": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "assignees": [ + { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + { + "login": "hubot", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/hubot_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/hubot", + "html_url": "https://github.com/hubot", + "followers_url": "https://api.github.com/users/hubot/followers", + "following_url": "https://api.github.com/users/hubot/following{/other_user}", + "gists_url": "https://api.github.com/users/hubot/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hubot/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hubot/subscriptions", + "organizations_url": "https://api.github.com/users/hubot/orgs", + "repos_url": "https://api.github.com/users/hubot/repos", + "events_url": "https://api.github.com/users/hubot/events{/privacy}", + "received_events_url": "https://api.github.com/users/hubot/received_events", + "type": "User", + "site_admin": true + } + ], + "requested_reviewers": [ + { + "login": "other_user", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/other_user_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/other_user", + "html_url": "https://github.com/other_user", + "followers_url": "https://api.github.com/users/other_user/followers", + "following_url": "https://api.github.com/users/other_user/following{/other_user}", + "gists_url": "https://api.github.com/users/other_user/gists{/gist_id}", + "starred_url": "https://api.github.com/users/other_user/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/other_user/subscriptions", + "organizations_url": "https://api.github.com/users/other_user/orgs", + "repos_url": "https://api.github.com/users/other_user/repos", + "events_url": "https://api.github.com/users/other_user/events{/privacy}", + "received_events_url": "https://api.github.com/users/other_user/received_events", + "type": "User", + "site_admin": false + } + ], + "requested_teams": [ + { + "id": 1, + "node_id": "MDQ6VGVhbTE=", + "url": "https://api.github.com/teams/1", + "html_url": "https://github.com/orgs/github/teams/justice-league", + "name": "Justice League", + "slug": "justice-league", + "description": "A great team.", + "privacy": "closed", + "notification_setting": "notifications_enabled", + "permission": "admin", + "members_url": "https://api.github.com/teams/1/members{/member}", + "repositories_url": "https://api.github.com/teams/1/repos" + } + ], + "head": { + "label": "octocat:new-topic", + "ref": "new-topic", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "topics": [ + "octocat", + "atom", + "electron", + "api" + ], + "has_issues": true, + "has_projects": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "has_discussions": false, + "archived": false, + "disabled": false, + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": false, + "push": false, + "pull": true + }, + "allow_rebase_merge": true, + "temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_forking": true, + "forks": 123, + "open_issues": 123, + "license": { + "key": "mit", + "name": "MIT License", + "url": "https://api.github.com/licenses/mit", + "spdx_id": "MIT", + "node_id": "MDc6TGljZW5zZW1pdA==" + }, + "watchers": 123 + } + }, + "base": { + "label": "octocat:master", + "ref": "master", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "topics": [ + "octocat", + "atom", + "electron", + "api" + ], + "has_issues": true, + "has_projects": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "has_discussions": false, + "archived": false, + "disabled": false, + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": false, + "push": false, + "pull": true + }, + "allow_rebase_merge": true, + "temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O", + "allow_squash_merge": true, + "allow_merge_commit": true, + "forks": 123, + "open_issues": 123, + "license": { + "key": "mit", + "name": "MIT License", + "url": "https://api.github.com/licenses/mit", + "spdx_id": "MIT", + "node_id": "MDc6TGljZW5zZW1pdA==" + }, + "watchers": 123 + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/octocat/Hello-World/pulls/1347" + }, + "html": { + "href": "https://github.com/octocat/Hello-World/pull/1347" + }, + "issue": { + "href": "https://api.github.com/repos/octocat/Hello-World/issues/1347" + }, + "comments": { + "href": "https://api.github.com/repos/octocat/Hello-World/issues/1347/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e" + } + }, + "author_association": "OWNER", + "auto_merge": null, + "draft": false, + "merged": false, + "mergeable": true, + "rebaseable": true, + "mergeable_state": "clean", + "merged_by": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "comments": 10, + "review_comments": 0, + "maintainer_can_modify": true, + "commits": 3, + "additions": 100, + "deletions": 3, + "changed_files": 5 +} \ No newline at end of file diff --git a/vcsclient/testdata/github/pull_request_info_response_bad_labels.json b/vcsclient/testdata/github/pull_request_info_response_bad_labels.json new file mode 100644 index 00000000..e3ac3f30 --- /dev/null +++ b/vcsclient/testdata/github/pull_request_info_response_bad_labels.json @@ -0,0 +1,196 @@ +{ + "url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347", + "id": 1, + "node_id": "MDExOlB1bGxSZXF1ZXN0MQ==", + "number": 1347, + "state": "open", + "locked": true, + "title": "Amazing new feature", + "user": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "head": { + "label": "octocatnew-topic", + "ref": "new-topic", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "topics": [ + "octocat", + "atom", + "electron", + "api" + ], + "has_issues": true, + "has_projects": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "has_discussions": false, + "archived": false, + "disabled": false, + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": false, + "push": false, + "pull": true + }, + "allow_rebase_merge": true, + "temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_forking": true, + "forks": 123, + "open_issues": 123, + "license": { + "key": "mit", + "name": "MIT License", + "url": "https://api.github.com/licenses/mit", + "spdx_id": "MIT", + "node_id": "MDc6TGljZW5zZW1pdA==" + }, + "watchers": 123 + } + }, + "base": { + "label": "octocat:master", + "ref": "master", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + } + } +} \ No newline at end of file diff --git a/vcsclient/testdata/gitlab/get_merge_request_response.json b/vcsclient/testdata/gitlab/get_merge_request_response.json new file mode 100644 index 00000000..47afe42c --- /dev/null +++ b/vcsclient/testdata/gitlab/get_merge_request_response.json @@ -0,0 +1,135 @@ +{ + "id": 1, + "iid": 133, + "project_id": 15513260, + "title": "Manual job rules", + "description": "", + "state": "opened", + "created_at": "2022-05-13T07:26:38.402Z", + "updated_at": "2022-05-14T03:38:31.354Z", + "merged_by": null, + "merge_user": null, + "merged_at": null, + "prepared_at": "2018-09-04T11:16:17.520Z", + "closed_by": null, + "closed_at": null, + "target_branch": "master", + "source_branch": "manual-job-rules", + "user_notes_count": 0, + "upvotes": 0, + "downvotes": 0, + "author": { + "id": 4155490, + "username": "marcel.amirault", + "name": "Marcel Amirault", + "state": "active", + "avatar_url": "https://gitlab.com/uploads/-/system/user/avatar/4155490/avatar.png", + "web_url": "https://gitlab.com/marcel.amirault" + }, + "assignees": [], + "assignee": null, + "reviewers": [], + "source_project_id": 15513260, + "target_project_id": 15513260, + "labels": [], + "draft": false, + "work_in_progress": false, + "milestone": null, + "merge_when_pipeline_succeeds": false, + "merge_status": "can_be_merged", + "detailed_merge_status": "can_be_merged", + "sha": "e82eb4a098e32c796079ca3915e07487fc4db24c", + "merge_commit_sha": null, + "squash_commit_sha": null, + "discussion_locked": null, + "should_remove_source_branch": null, + "force_remove_source_branch": true, + "reference": "!133", + "references": { + "short": "!133", + "relative": "!133", + "full": "marcel.amirault/test-project!133" + }, + "web_url": "https://gitlab.com/marcel.amirault/test-project/-/merge_requests/133", + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + }, + "squash": false, + "task_completion_status": { + "count": 0, + "completed_count": 0 + }, + "has_conflicts": false, + "blocking_discussions_resolved": true, + "approvals_before_merge": null, + "subscribed": true, + "changes_count": "1", + "latest_build_started_at": "2022-05-13T09:46:50.032Z", + "latest_build_finished_at": null, + "first_deployed_to_production_at": null, + "pipeline": { + "id": 538317940, + "iid": 1877, + "project_id": 15513260, + "sha": "1604b0c46c395822e4e9478777f8e54ac99fe5b9", + "ref": "refs/merge-requests/133/merge", + "status": "failed", + "source": "merge_request_event", + "created_at": "2022-05-13T09:46:39.560Z", + "updated_at": "2022-05-13T09:47:20.706Z", + "web_url": "https://gitlab.com/marcel.amirault/test-project/-/pipelines/538317940" + }, + "head_pipeline": { + "id": 538317940, + "iid": 1877, + "project_id": 15513260, + "sha": "1604b0c46c395822e4e9478777f8e54ac99fe5b9", + "ref": "refs/merge-requests/133/merge", + "status": "failed", + "source": "merge_request_event", + "created_at": "2022-05-13T09:46:39.560Z", + "updated_at": "2022-05-13T09:47:20.706Z", + "web_url": "https://gitlab.com/marcel.amirault/test-project/-/pipelines/538317940", + "before_sha": "1604b0c46c395822e4e9478777f8e54ac99fe5b9", + "tag": false, + "yaml_errors": null, + "user": { + "id": 4155490, + "username": "marcel.amirault", + "name": "Marcel Amirault", + "state": "active", + "avatar_url": "https://gitlab.com/uploads/-/system/user/avatar/4155490/avatar.png", + "web_url": "https://gitlab.com/marcel.amirault" + }, + "started_at": "2022-05-13T09:46:50.032Z", + "finished_at": "2022-05-13T09:47:20.697Z", + "committed_at": null, + "duration": 30, + "queued_duration": 10, + "coverage": null, + "detailed_status": { + "icon": "status_failed", + "text": "failed", + "label": "failed", + "group": "failed", + "tooltip": "failed", + "has_details": true, + "details_path": "/marcel.amirault/test-project/-/pipelines/538317940", + "illustration": null, + "favicon": "/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png" + } + }, + "diff_refs": { + "base_sha": "1162f719d711319a2efb2a35566f3bfdadee8bab", + "head_sha": "e82eb4a098e32c796079ca3915e07487fc4db24c", + "start_sha": "1162f719d711319a2efb2a35566f3bfdadee8bab" + }, + "merge_error": null, + "first_contribution": false, + "user": { + "can_merge": true + } +} \ No newline at end of file diff --git a/vcsclient/vcsclient.go b/vcsclient/vcsclient.go index d2cc6731..ce60b3d7 100644 --- a/vcsclient/vcsclient.go +++ b/vcsclient/vcsclient.go @@ -180,6 +180,12 @@ type VcsClient interface { // repository - VCS repository name ListOpenPullRequests(ctx context.Context, owner, repository string) ([]PullRequestInfo, error) + // GetPullRequestByID Gets pull request info by ID. + // owner - User or organization + // repository - VCS repository name + // pullRequestId - ID of the pull request + GetPullRequestByID(ctx context.Context, owner, repository string, pullRequestId int) (PullRequestInfo, error) + // GetLatestCommit Gets the most recent commit of a branch // owner - User or organization // repository - VCS repository name