Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GetPullRequestByID #106

Merged
merged 11 commits into from
Jul 30, 2023
9 changes: 7 additions & 2 deletions vcsclient/bitbucketserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,13 @@ func (client *BitbucketServerClient) GetPullRequestByID(ctx context.Context, own
client.logger.Debug("fetching pull request by ID in ", repository)
bitbucketClient := client.buildBitbucketClient(ctx)
apiResponse, err := bitbucketClient.GetPullRequest(owner, repository, pullRequestId)
if err != nil || apiResponse.StatusCode != http.StatusOK {
return
if err != nil {
return PullRequestInfo{}, err
}
if apiResponse != nil {
if err = vcsutils.CheckResponseStatusWithBody(apiResponse.Response, http.StatusOK); err != nil {
return PullRequestInfo{}, err
}
}
pullRequest, err := bitbucketv1.GetPullRequestResponse(apiResponse)
if err != nil {
Expand Down
9 changes: 7 additions & 2 deletions vcsclient/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,15 @@ func (client *GitHubClient) GetPullRequestByID(ctx context.Context, owner, repos
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 {
pullRequest, ghResponse, err := ghClient.PullRequests.Get(ctx, owner, repository, pullRequestId)
if err != nil {
return PullRequestInfo{}, err
}
if ghResponse != nil {
if err = vcsutils.CheckResponseStatusWithBody(ghResponse.Response, http.StatusOK); err != nil {
return PullRequestInfo{}, err
}
}

sourceBranch, err1 := extractBranchFromLabel(vcsutils.DefaultIfNotNil(pullRequest.Head.Label))
targetBranch, err2 := extractBranchFromLabel(vcsutils.DefaultIfNotNil(pullRequest.Base.Label))
Expand Down
45 changes: 39 additions & 6 deletions vcsclient/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,19 +269,30 @@ func (client *GitLabClient) getOpenPullRequests(ctx context.Context, owner, repo
if err != nil {
return []PullRequestInfo{}, err
}
return mapGitLabMergeRequestToPullRequestInfoList(mergeRequests, owner, repository, withBody), nil
return mapGitLabMergeRequestToPullRequestInfoList(mergeRequests, client, owner, repository, withBody)
}

// GetPullRequestInfoById on GitLab
func (client *GitLabClient) GetPullRequestByID(_ 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 {
mergeRequest, glResponse, err := client.glClient.MergeRequests.GetMergeRequest(getProjectID(owner, repository), pullRequestId, nil)
if err != nil {
return PullRequestInfo{}, err
}
if glResponse != nil {
if err = vcsutils.CheckResponseStatusWithBody(glResponse.Response, http.StatusOK); err != nil {
return PullRequestInfo{}, err
}
}
sourceOwner := owner
if mergeRequest.SourceProjectID != mergeRequest.TargetProjectID {
if sourceOwner, err = getProjectOwnerByID(mergeRequest.SourceProjectID, client); err != nil {
return PullRequestInfo{}, err
}
}
pullRequestInfo = PullRequestInfo{
ID: int64(mergeRequest.ID),
Source: BranchInfo{Name: mergeRequest.SourceBranch, Repository: repository, Owner: owner},
Source: BranchInfo{Name: mergeRequest.SourceBranch, Repository: repository, Owner: sourceOwner},
Target: BranchInfo{Name: mergeRequest.TargetBranch, Repository: repository, Owner: owner},
}
return
Expand Down Expand Up @@ -588,19 +599,25 @@ func mapGitLabNotesToCommentInfoList(notes []*gitlab.Note) (res []CommentInfo) {
return
}

func mapGitLabMergeRequestToPullRequestInfoList(mergeRequests []*gitlab.MergeRequest, owner, repository string, withBody bool) (res []PullRequestInfo) {
func mapGitLabMergeRequestToPullRequestInfoList(mergeRequests []*gitlab.MergeRequest, client *GitLabClient, owner, repository string, withBody bool) (res []PullRequestInfo, err error) {
for _, mergeRequest := range mergeRequests {
var body string
if withBody {
body = mergeRequest.Description
}
sourceOwner := owner
if mergeRequest.SourceProjectID != mergeRequest.TargetProjectID {
if sourceOwner, err = getProjectOwnerByID(mergeRequest.SourceProjectID, client); err != nil {
return
}
}
res = append(res, PullRequestInfo{
ID: int64(mergeRequest.IID),
Body: body,
Source: BranchInfo{
Name: mergeRequest.SourceBranch,
Repository: repository,
Owner: owner,
Owner: sourceOwner,
},
Target: BranchInfo{
Name: mergeRequest.TargetBranch,
Expand All @@ -611,3 +628,19 @@ func mapGitLabMergeRequestToPullRequestInfoList(mergeRequests []*gitlab.MergeReq
}
return
}

func getProjectOwnerByID(projectID int, client *GitLabClient) (string, error) {
project, glResponse, err := client.glClient.Projects.GetProject(projectID, &gitlab.GetProjectOptions{})
if err != nil {
return "", err
}
if glResponse != nil {
if err = vcsutils.CheckResponseStatusWithBody(glResponse.Response, http.StatusOK); err != nil {
return "", err
}
}
if project.Namespace == nil {
return "", fmt.Errorf("could not fetch the name of the project owner. Project ID: %d", projectID)
}
return project.Namespace.Name, nil
}
22 changes: 21 additions & 1 deletion vcsclient/gitlab_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,6 @@ func createGitLabHandler(t *testing.T, expectedURI string, response []byte, expe
}
}
func createGitLabWithPaginationHandler(t *testing.T, _ string, response []byte, _ []byte, expectedStatusCode int, expectedHttpMethod string) http.HandlerFunc {

var repos []gitlab.Project
err := json.Unmarshal(response, &repos)
assert.NoError(t, err)
Expand Down Expand Up @@ -723,3 +722,24 @@ func TestGitLabClient_TestGetCommitStatus(t *testing.T) {
assert.Error(t, err)
})
}

func TestGitLabClient_getProjectOwnerByID(t *testing.T) {
projectID := 47457684

// Successful response
response, err := os.ReadFile(filepath.Join("testdata", "gitlab", "get_project_response.json"))
assert.NoError(t, err)
client, cleanUp := createServerAndClient(t, vcsutils.GitLab, false, response,
fmt.Sprintf("/api/v4/projects/%d", projectID), createGitLabHandler)
defer cleanUp()
projectOwner, err := getProjectOwnerByID(projectID, client.(*GitLabClient))
assert.NoError(t, err)
assert.Equal(t, "test", projectOwner)

badClient, badClientCleanUp :=
createServerAndClient(t, vcsutils.GitLab, false, nil, fmt.Sprintf("/api/v4/projects/%d", projectID), createGitLabHandler)
defer badClientCleanUp()
projectOwner, err = getProjectOwnerByID(projectID, badClient.(*GitLabClient))
assert.Error(t, err)
assert.NotEqual(t, "test", projectOwner)
}
147 changes: 147 additions & 0 deletions vcsclient/testdata/gitlab/get_project_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
{
"id": 47457684,
"description": null,
"name": "frogbot-demo",
"name_with_namespace": "test / frogbot-demo",
"path": "frogbot-demo",
"path_with_namespace": "test/frogbot-demo",
"created_at": "2023-07-06T06:55:07.521Z",
"default_branch": "main",
"tag_list": [],
"topics": [],
"ssh_url_to_repo": "[email protected]:test/frogbot-demo.git",
"http_url_to_repo": "https://gitlab.com/test/frogbot-demo.git",
"web_url": "https://gitlab.com/test/frogbot-demo",
"readme_url": "https://gitlab.com/test/frogbot-demo/-/blob/main/README.md",
"forks_count": 0,
"avatar_url": null,
"star_count": 0,
"last_activity_at": "2023-07-06T08:23:22.766Z",
"namespace": {
"id": 62039166,
"name": "test",
"path": "test",
"kind": "group",
"full_path": "test",
"parent_id": null,
"avatar_url": null,
"web_url": "https://gitlab.com/groups/test"
},
"container_registry_image_prefix": "registry.gitlab.com/test/frogbot-demo",
"_links": {
"self": "https://gitlab.com/api/v4/projects/47457684",
"issues": "https://gitlab.com/api/v4/projects/47457684/issues",
"merge_requests": "https://gitlab.com/api/v4/projects/47457684/merge_requests",
"repo_branches": "https://gitlab.com/api/v4/projects/47457684/repository/branches",
"labels": "https://gitlab.com/api/v4/projects/47457684/labels",
"events": "https://gitlab.com/api/v4/projects/47457684/events",
"members": "https://gitlab.com/api/v4/projects/47457684/members",
"cluster_agents": "https://gitlab.com/api/v4/projects/47457684/cluster_agents"
},
"packages_enabled": true,
"empty_repo": false,
"archived": false,
"visibility": "private",
"resolve_outdated_diff_discussions": false,
"container_expiration_policy": {
"cadence": "1d",
"enabled": false,
"keep_n": 10,
"older_than": "90d",
"name_regex": ".*",
"name_regex_keep": null,
"next_run_at": "2023-07-07T06:55:07.560Z"
},
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
"jobs_enabled": true,
"snippets_enabled": true,
"container_registry_enabled": true,
"service_desk_enabled": true,
"service_desk_address": "contact-project+test-frogbot-demo-47457684-issue-@incoming.gitlab.com",
"can_create_merge_request_in": true,
"issues_access_level": "enabled",
"repository_access_level": "enabled",
"merge_requests_access_level": "enabled",
"forking_access_level": "enabled",
"wiki_access_level": "enabled",
"builds_access_level": "enabled",
"snippets_access_level": "enabled",
"pages_access_level": "private",
"analytics_access_level": "enabled",
"container_registry_access_level": "enabled",
"security_and_compliance_access_level": "private",
"releases_access_level": "enabled",
"environments_access_level": "enabled",
"feature_flags_access_level": "enabled",
"infrastructure_access_level": "enabled",
"monitor_access_level": "enabled",
"emails_disabled": false,
"emails_enabled": true,
"shared_runners_enabled": true,
"lfs_enabled": true,
"creator_id": 13377328,
"import_url": null,
"import_type": null,
"import_status": "none",
"import_error": null,
"open_issues_count": 0,
"description_html": "",
"updated_at": "2023-07-06T08:53:22.050Z",
"ci_default_git_depth": 20,
"ci_forward_deployment_enabled": true,
"ci_forward_deployment_rollback_allowed": true,
"ci_job_token_scope_enabled": false,
"ci_separated_caches": true,
"ci_allow_fork_pipelines_to_run_in_parent_project": true,
"build_git_strategy": "fetch",
"keep_latest_artifact": true,
"restrict_user_defined_variables": false,
"runners_token": "GR1348941eo_AAkjv4niyY222E4nz",
"runner_token_expiration_interval": null,
"group_runners_enabled": true,
"auto_cancel_pending_pipelines": "enabled",
"build_timeout": 3600,
"auto_devops_enabled": false,
"auto_devops_deploy_strategy": "continuous",
"ci_config_path": "",
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": null,
"request_access_enabled": true,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": true,
"printing_merge_request_link_enabled": true,
"merge_method": "merge",
"squash_option": "default_off",
"enforce_auth_checks_on_uploads": true,
"suggestion_commit_message": null,
"merge_commit_template": null,
"squash_commit_template": null,
"issue_branch_template": null,
"autoclose_referenced_issues": true,
"approvals_before_merge": 0,
"mirror": false,
"external_authorization_classification_label": "",
"marked_for_deletion_at": null,
"marked_for_deletion_on": null,
"requirements_enabled": true,
"requirements_access_level": "enabled",
"security_and_compliance_enabled": true,
"compliance_frameworks": [],
"issues_template": null,
"merge_requests_template": null,
"merge_pipelines_enabled": false,
"merge_trains_enabled": false,
"only_allow_merge_if_all_status_checks_passed": false,
"allow_pipeline_trigger_approve_deployment": false,
"permissions": {
"project_access": null,
"group_access": {
"access_level": 50,
"notification_level": 3
}
}
}
2 changes: 1 addition & 1 deletion vcsclient/testdata/gitlab/pull_requests_list_response.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"web_url": "https://gitlab.example.com//kenyatta_oconnell"
}],
"source_project_id": 2,
"target_project_id": 3,
"target_project_id": 2,
"labels": [
"Community contribution",
"Manage"
Expand Down
11 changes: 7 additions & 4 deletions vcsutils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/go-git/go-git/v5/config"
"github.com/google/uuid"
"github.com/mitchellh/mapstructure"
"golang.org/x/exp/slices"
"io"
"net/http"
"os"
Expand Down Expand Up @@ -241,10 +242,12 @@ func unzipFile(f *zip.File, destination string) (err error) {
}

func CheckResponseStatusWithBody(resp *http.Response, expectedStatusCodes ...int) error {
for _, statusCode := range expectedStatusCodes {
if statusCode == resp.StatusCode {
return nil
}
if resp == nil {
return errors.New("received an empty response")
}

if slices.Contains(expectedStatusCodes, resp.StatusCode) {
return nil
}

body, err := io.ReadAll(resp.Body)
Expand Down