Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean McGivern <sean@gitlab.com>2018-11-29 11:36:04 +0300
committerSean McGivern <sean@gitlab.com>2018-11-29 11:36:04 +0300
commit6852680584a1b22788f451457a6042eabf862a73 (patch)
tree8619487978bf962708c3f56482ae0f5085af9c8a
parentc07183f0d3ce24e8cfcb93e71ae950d7067a8ce1 (diff)
parent04ceb69f3eea903d541614f42bbcdd008ad93839 (diff)
Merge branch '33705-merge-request-rebase-api' into 'master'
Add a rebase API endpoint for merge requests Closes #33705 See merge request gitlab-org/gitlab-ce!23296
-rw-r--r--changelogs/unreleased/33705-merge-request-rebase-api.yml5
-rw-r--r--doc/api/merge_requests.md65
-rw-r--r--lib/api/entities.rb4
-rw-r--r--lib/api/merge_requests.rb35
-rw-r--r--spec/requests/api/merge_requests_spec.rb30
5 files changed, 137 insertions, 2 deletions
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..fc03cf6cc39 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -408,6 +408,7 @@ Parameters:
- `merge_request_iid` (required) - The internal ID of the merge request
- `render_html` (optional) - If `true` response includes rendered HTML for title and description
- `include_diverged_commits_count` (optional) - If `true` response includes the commits behind the target branch
+- `include_rebase_in_progress` (optional) - If `true` response includes whether a rebase operation is in progress
```json
{
@@ -461,6 +462,7 @@ Parameters:
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
@@ -505,7 +507,8 @@ Parameters:
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
- "diverged_commits_count": 2
+ "diverged_commits_count": 2,
+ "rebase_in_progress": false
}
```
@@ -773,6 +776,7 @@ POST /projects/:id/merge_requests
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
@@ -900,6 +904,7 @@ Must include at least one non-required attribute from above.
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
@@ -1043,6 +1048,7 @@ Parameters:
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
@@ -1158,6 +1164,7 @@ Parameters:
},
"merge_when_pipeline_succeeds": false,
"merge_status": "can_be_merged",
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
@@ -1206,6 +1213,62 @@ 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 can poll the [Get single MR](#get-single-mr) endpoint with the
+`include_rebase_in_progress` parameter to check the status of the
+asynchronous request.
+
+If the rebase operation is ongoing, the response will include the following:
+
+```json
+{
+ "rebase_in_progress": true
+ "merge_error": null
+}
+```
+
+Once the rebase operation has completed successfully, the response will include
+the following:
+
+```json
+{
+ "rebase_in_progress": false,
+ "merge_error": null,
+}
+```
+
+If the rebase operation fails, the response will include the following:
+
+```json
+{
+ "rebase_in_progress": false,
+ "merge_error": "Rebase failed. Please rebase locally",
+}
+```
+
## Comments on merge requests
Comments are done via the [notes](notes.md) resource.
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 4788b0e16a1..5dbfbb85e9e 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -715,6 +715,10 @@ module API
expose :diff_refs, using: Entities::DiffRefs
+ # Allow the status of a rebase to be determined
+ expose :merge_error
+ expose :rebase_in_progress?, as: :rebase_in_progress, if: -> (_, options) { options[:include_rebase_in_progress] }
+
expose :diverged_commits_count, as: :diverged_commits_count, if: -> (_, options) { options[:include_diverged_commits_count] }
def build_available?(options)
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 16f07f16387..595b3641c52 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'
@@ -239,6 +252,7 @@ module API
requires :merge_request_iid, type: Integer, desc: 'The IID of a merge request'
optional :render_html, type: Boolean, desc: 'Returns the description and title rendered HTML'
optional :include_diverged_commits_count, type: Boolean, desc: 'Returns the commits count behind the target branch'
+ optional :include_rebase_in_progress, type: Boolean, desc: 'Returns whether a rebase operation is ongoing '
end
desc 'Get a single merge request' do
success Entities::MergeRequest
@@ -246,7 +260,13 @@ module API
get ':id/merge_requests/:merge_request_iid' do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
- present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project, render_html: params[:render_html], include_diverged_commits_count: params[:include_diverged_commits_count]
+ present merge_request,
+ with: Entities::MergeRequest,
+ current_user: current_user,
+ project: user_project,
+ render_html: params[:render_html],
+ include_diverged_commits_count: params[:include_diverged_commits_count],
+ include_rebase_in_progress: params[:include_rebase_in_progress]
end
desc 'Get the participants of a merge request' do
@@ -378,6 +398,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..27bcde77860 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -359,6 +359,8 @@ describe API::MergeRequests do
expect(json_response['should_close_merge_request']).to be_falsy
expect(json_response['force_close_merge_request']).to be_falsy
expect(json_response['changes_count']).to eq(merge_request.merge_request_diff.real_size)
+ expect(json_response['merge_error']).to eq(merge_request.merge_error)
+ expect(json_response).not_to include('rebase_in_progress')
end
it 'exposes description and title html when render_html is true' do
@@ -369,6 +371,14 @@ describe API::MergeRequests do
expect(json_response).to include('title_html', 'description_html')
end
+ it 'exposes rebase_in_progress when include_rebase_in_progress is true' do
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), include_rebase_in_progress: true
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response).to include('rebase_in_progress')
+ end
+
context 'merge_request_metrics' do
before do
merge_request.metrics.update!(merged_by: user,
@@ -1181,6 +1191,26 @@ describe API::MergeRequests do
end
end
+ describe 'PUT :id/merge_requests/:merge_request_iid/rebase' do
+ it 'enqueues 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 }