From 9f287298270b3a833bc53b9280c6e3c6a2f055b8 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 22 Nov 2018 06:02:58 +0000 Subject: [PATCH] Add a rebase API endpoint for merge requests --- .../33705-merge-request-rebase-api.yml | 5 ++++ doc/api/merge_requests.md | 25 ++++++++++++++++++ lib/api/merge_requests.rb | 26 +++++++++++++++++++ spec/requests/api/merge_requests_spec.rb | 20 ++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 changelogs/unreleased/33705-merge-request-rebase-api.yml diff --git a/changelogs/unreleased/33705-merge-request-rebase-api.yml b/changelogs/unreleased/33705-merge-request-rebase-api.yml new file mode 100644 index 00000000000..322fe31ce87 --- /dev/null +++ b/changelogs/unreleased/33705-merge-request-rebase-api.yml @@ -0,0 +1,5 @@ +--- +title: Add a rebase API endpoint for merge requests +merge_request: 23296 +author: +type: added diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index da70c74c4ce..2f5b1608882 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -1206,6 +1206,31 @@ Parameters: } ``` +## Rebase a merge request + +Automatically rebase the `source_branch` of the merge request against its +`target_branch`. + +If you don't have permissions to push to the merge request's source branch - +you'll get a `403 Forbidden` response. + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/rebase +``` + +| 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 | +| `merge_request_iid` | integer | yes | The internal ID of the merge request | + +```bash +curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase +``` + +This is an asynchronous request. The API will return an empty `202 Accepted` +response if the request is enqueued successfully. You should poll the +[Get single MR](#get-single-mr) endpoint to determine success or failure. + ## Comments on merge requests Comments are done via the [notes](notes.md) resource. diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 16f07f16387..23e65dca424 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -74,6 +74,19 @@ module API options end + def authorize_push_to_merge_request!(merge_request) + forbidden!('Source branch does not exist') unless + merge_request.source_branch_exists? + + user_access = Gitlab::UserAccess.new( + current_user, + project: merge_request.source_project + ) + + forbidden!('Cannot push to source branch') unless + user_access.can_push_to_branch?(merge_request.source_branch) + end + params :merge_requests_params do optional :state, type: String, values: %w[opened closed locked merged all], default: 'all', desc: 'Return opened, closed, locked, merged, or all merge requests' @@ -378,6 +391,19 @@ module API .cancel(merge_request) end + desc 'Rebase the merge request against its target branch' do + detail 'This feature was added in GitLab 11.6' + end + put ':id/merge_requests/:merge_request_iid/rebase' do + merge_request = find_project_merge_request(params[:merge_request_iid]) + + authorize_push_to_merge_request!(merge_request) + + RebaseWorker.perform_async(merge_request.id, current_user.id) + + status :accepted + end + desc 'List issues that will be closed on merge' do success Entities::MRNote end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index e4e0ca285e0..19602e7152a 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -1181,6 +1181,26 @@ describe API::MergeRequests do end end + describe 'PUT :id/merge_requests/:merge_request_iid/rebase' do + it 'enques a rebase of the merge request against the target branch' do + Sidekiq::Testing.fake! do + put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/rebase", user) + end + + expect(response).to have_gitlab_http_status(202) + expect(RebaseWorker.jobs.size).to eq(1) + end + + it 'returns 403 if the user cannot push to the branch' do + guest = create(:user) + project.add_guest(guest) + + put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/rebase", guest) + + expect(response).to have_gitlab_http_status(403) + end + end + describe 'Time tracking' do let(:issuable) { merge_request }