diff options
-rw-r--r-- | changelogs/unreleased/expose-commits-mr-api.yml | 5 | ||||
-rw-r--r-- | doc/api/commits.md | 68 | ||||
-rw-r--r-- | lib/api/commits.rb | 14 | ||||
-rw-r--r-- | spec/requests/api/commits_spec.rb | 29 |
4 files changed, 116 insertions, 0 deletions
diff --git a/changelogs/unreleased/expose-commits-mr-api.yml b/changelogs/unreleased/expose-commits-mr-api.yml new file mode 100644 index 00000000000..77ea2f27431 --- /dev/null +++ b/changelogs/unreleased/expose-commits-mr-api.yml @@ -0,0 +1,5 @@ +--- +title: Allow merge requests related to a commit to be found via API +merge_request: +author: +type: added diff --git a/doc/api/commits.md b/doc/api/commits.md index 55c673fd06a..a6b96ba539f 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -536,6 +536,74 @@ Example response: } ``` +## List Merge Requests associated with a commit + +Get a list of Merge Requests related to the specified commit. + +``` +GET /projects/:id/repository/commits/:sha/merge_requests +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user +| `sha` | string | yes | The commit SHA + + +```bash +curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/af5b13261899fb2c0db30abdd0af8b07cb44fdc5/merge_requests" +``` + +Example response: + +```json +[ + { + "id":45, + "iid":1, + "project_id":35, + "title":"Add new file", + "description":"", + "state":"opened", + "created_at":"2018-03-26T17:26:30.916Z", + "updated_at":"2018-03-26T17:26:30.916Z", + "target_branch":"master", + "source_branch":"test-branch", + "upvotes":0, + "downvotes":0, + "author" : { + "web_url" : "https://gitlab.example.com/thedude", + "name" : "Jeff Lebowski", + "avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png", + "username" : "thedude", + "state" : "active", + "id" : 28 + }, + "assignee":null, + "source_project_id":35, + "target_project_id":35, + "labels":[ ], + "work_in_progress":false, + "milestone":null, + "merge_when_pipeline_succeeds":false, + "merge_status":"can_be_merged", + "sha":"af5b13261899fb2c0db30abdd0af8b07cb44fdc5", + "merge_commit_sha":null, + "user_notes_count":0, + "discussion_locked":null, + "should_remove_source_branch":null, + "force_remove_source_branch":false, + "web_url":"http://https://gitlab.example.com/root/test-project/merge_requests/1", + "time_stats":{ + "time_estimate":0, + "total_time_spent":0, + "human_time_estimate":null, + "human_total_time_spent":null + } + } +] +``` + [ce-6096]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6096 "Multi-file commit" [ce-8047]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8047 [ce-15026]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15026 diff --git a/lib/api/commits.rb b/lib/api/commits.rb index 982f45425a3..684955a1b24 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -231,6 +231,20 @@ module API render_api_error!("Failed to save note #{note.errors.messages}", 400) end end + + desc 'Get Merge Requests associated with a commit' do + success Entities::MergeRequestBasic + end + params do + requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag on which to find Merge Requests' + use :pagination + end + get ':id/repository/commits/:sha/merge_requests', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do + commit = user_project.commit(params[:sha]) + not_found! 'Commit' unless commit + + present paginate(commit.merge_requests), with: Entities::MergeRequestBasic + end end end end diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 852f67db958..8ad19e3f0f5 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -1141,4 +1141,33 @@ describe API::Commits do end end end + + describe 'GET /projects/:id/repository/commits/:sha/merge_requests' do + let!(:project) { create(:project, :repository, :private) } + let!(:merged_mr) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'feature') } + let(:commit) { merged_mr.merge_request_diff.commits.last } + + it 'returns the correct merge request' do + get api("/projects/#{project.id}/repository/commits/#{commit.id}/merge_requests", user) + + expect(response).to have_gitlab_http_status(200) + expect(response).to include_pagination_headers + expect(json_response.length).to eq(1) + expect(json_response[0]['id']).to eq(merged_mr.id) + end + + it 'returns 403 for an unauthorized user' do + project.add_guest(user) + + get api("/projects/#{project.id}/repository/commits/#{commit.id}/merge_requests", user) + + expect(response).to have_gitlab_http_status(403) + end + + it 'responds 404 when the commit does not exist' do + get api("/projects/#{project.id}/repository/commits/a7d26f00c35b/merge_requests", user) + + expect(response).to have_gitlab_http_status(404) + end + end end |