Commit 0c621708658da4b3cf88d805da5dbad920f3d27f
Exists in
spb-stable
and in
2 other branches
Merge branch 'api-mr-merge' into 'master'
Accept merge request API This MR adds new endpoint `PUT /projects/:id/merge_request/:merge_request_id/merge`. After this change you can merge branches using API. Fixes internal issue #1166
Showing
4 changed files
with
119 additions
and
5 deletions
Show diff stats
CHANGELOG
| @@ -15,6 +15,7 @@ v 6.9.0 | @@ -15,6 +15,7 @@ v 6.9.0 | ||
| 15 | - Fix wiki backup skip bug | 15 | - Fix wiki backup skip bug |
| 16 | - Two Step MR creation process | 16 | - Two Step MR creation process |
| 17 | - Remove unwanted files from satellite working directory with git clean -fdx | 17 | - Remove unwanted files from satellite working directory with git clean -fdx |
| 18 | + - Accept merge request via API (sponsored by O'Reilly Media) | ||
| 18 | 19 | ||
| 19 | v 6.8.0 | 20 | v 6.8.0 |
| 20 | - Ability to at mention users that are participating in issue and merge req. discussion | 21 | - Ability to at mention users that are participating in issue and merge req. discussion |
doc/api/merge_requests.md
| @@ -189,6 +189,54 @@ Parameters: | @@ -189,6 +189,54 @@ Parameters: | ||
| 189 | ``` | 189 | ``` |
| 190 | 190 | ||
| 191 | 191 | ||
| 192 | +## Accept MR | ||
| 193 | + | ||
| 194 | +Merge changes submitted with MR usign this API. | ||
| 195 | +If merge success you get 200 OK. | ||
| 196 | +If it has some conflicts and can not be merged - you get 405 and error message 'Branch cannot be merged' | ||
| 197 | +If merge request is already merged or closed - you get 405 and error message 'Method Not Allowed' | ||
| 198 | +If you dont have permissions to accept this merge request - you get 401 | ||
| 199 | + | ||
| 200 | +``` | ||
| 201 | +PUT /projects/:id/merge_request/:merge_request_id/merge | ||
| 202 | +``` | ||
| 203 | + | ||
| 204 | +Parameters: | ||
| 205 | + | ||
| 206 | ++ `id` (required) - The ID of a project | ||
| 207 | ++ `merge_request_id` (required) - ID of MR | ||
| 208 | ++ `merge_commit_message` (optional) - Custom merge commit message | ||
| 209 | + | ||
| 210 | +```json | ||
| 211 | +{ | ||
| 212 | + "id": 1, | ||
| 213 | + "target_branch": "master", | ||
| 214 | + "source_branch": "test1", | ||
| 215 | + "project_id": 3, | ||
| 216 | + "title": "test1", | ||
| 217 | + "state": "merged", | ||
| 218 | + "upvotes": 0, | ||
| 219 | + "downvotes": 0, | ||
| 220 | + "author": { | ||
| 221 | + "id": 1, | ||
| 222 | + "username": "admin", | ||
| 223 | + "email": "admin@local.host", | ||
| 224 | + "name": "Administrator", | ||
| 225 | + "state": "active", | ||
| 226 | + "created_at": "2012-04-29T08:46:00Z" | ||
| 227 | + }, | ||
| 228 | + "assignee": { | ||
| 229 | + "id": 1, | ||
| 230 | + "username": "admin", | ||
| 231 | + "email": "admin@local.host", | ||
| 232 | + "name": "Administrator", | ||
| 233 | + "state": "active", | ||
| 234 | + "created_at": "2012-04-29T08:46:00Z" | ||
| 235 | + } | ||
| 236 | +} | ||
| 237 | +``` | ||
| 238 | + | ||
| 239 | + | ||
| 192 | ## Post comment to MR | 240 | ## Post comment to MR |
| 193 | 241 | ||
| 194 | Adds a comment to a merge request. | 242 | Adds a comment to a merge request. |
lib/api/merge_requests.rb
| @@ -34,7 +34,7 @@ module API | @@ -34,7 +34,7 @@ module API | ||
| 34 | when "closed" then user_project.merge_requests.closed | 34 | when "closed" then user_project.merge_requests.closed |
| 35 | when "merged" then user_project.merge_requests.merged | 35 | when "merged" then user_project.merge_requests.merged |
| 36 | else user_project.merge_requests | 36 | else user_project.merge_requests |
| 37 | - end | 37 | + end |
| 38 | 38 | ||
| 39 | present paginate(mrs), with: Entities::MergeRequest | 39 | present paginate(mrs), with: Entities::MergeRequest |
| 40 | end | 40 | end |
| @@ -111,6 +111,49 @@ module API | @@ -111,6 +111,49 @@ module API | ||
| 111 | end | 111 | end |
| 112 | end | 112 | end |
| 113 | 113 | ||
| 114 | + # Merge MR | ||
| 115 | + # | ||
| 116 | + # Parameters: | ||
| 117 | + # id (required) - The ID of a project | ||
| 118 | + # merge_request_id (required) - ID of MR | ||
| 119 | + # merge_commit_message (optional) - Custom merge commit message | ||
| 120 | + # Example: | ||
| 121 | + # PUT /projects/:id/merge_request/:merge_request_id/merge | ||
| 122 | + # | ||
| 123 | + put ":id/merge_request/:merge_request_id/merge" do | ||
| 124 | + merge_request = user_project.merge_requests.find(params[:merge_request_id]) | ||
| 125 | + | ||
| 126 | + action = if user_project.protected_branch?(merge_request.target_branch) | ||
| 127 | + :push_code_to_protected_branches | ||
| 128 | + else | ||
| 129 | + :push_code | ||
| 130 | + end | ||
| 131 | + | ||
| 132 | + if can?(current_user, action, user_project) | ||
| 133 | + if merge_request.unchecked? | ||
| 134 | + merge_request.check_if_can_be_merged | ||
| 135 | + end | ||
| 136 | + | ||
| 137 | + if merge_request.open? | ||
| 138 | + if merge_request.can_be_merged? | ||
| 139 | + merge_request.automerge!(current_user, params[:merge_commit_message] || merge_request.merge_commit_message) | ||
| 140 | + present merge_request, with: Entities::MergeRequest | ||
| 141 | + else | ||
| 142 | + render_api_error!('Branch cannot be merged', 405) | ||
| 143 | + end | ||
| 144 | + else | ||
| 145 | + # Merge request can not be merged | ||
| 146 | + # because it is already closed/merged | ||
| 147 | + not_allowed! | ||
| 148 | + end | ||
| 149 | + else | ||
| 150 | + # Merge request can not be merged | ||
| 151 | + # because user dont have permissions to push into target branch | ||
| 152 | + unauthorized! | ||
| 153 | + end | ||
| 154 | + end | ||
| 155 | + | ||
| 156 | + | ||
| 114 | # Get a merge request's comments | 157 | # Get a merge request's comments |
| 115 | # | 158 | # |
| 116 | # Parameters: | 159 | # Parameters: |
spec/requests/api/merge_requests_spec.rb
| @@ -183,11 +183,33 @@ describe API::API, api: true do | @@ -183,11 +183,33 @@ describe API::API, api: true do | ||
| 183 | end | 183 | end |
| 184 | end | 184 | end |
| 185 | 185 | ||
| 186 | - describe "PUT /projects/:id/merge_request/:merge_request_id to merge MR" do | ||
| 187 | - it "should return merge_request" do | ||
| 188 | - put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "merge" | 186 | + describe "PUT /projects/:id/merge_request/:merge_request_id/merge" do |
| 187 | + it "should return merge_request in case of success" do | ||
| 188 | + MergeRequest.any_instance.stub(can_be_merged?: true, automerge!: true) | ||
| 189 | + put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) | ||
| 189 | response.status.should == 200 | 190 | response.status.should == 200 |
| 190 | - json_response['state'].should == 'merged' | 191 | + end |
| 192 | + | ||
| 193 | + it "should return 405 if branch can't be merged" do | ||
| 194 | + MergeRequest.any_instance.stub(can_be_merged?: false) | ||
| 195 | + put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) | ||
| 196 | + response.status.should == 405 | ||
| 197 | + json_response['message'].should == 'Branch cannot be merged' | ||
| 198 | + end | ||
| 199 | + | ||
| 200 | + it "should return 405 if merge_request is not open" do | ||
| 201 | + merge_request.close | ||
| 202 | + put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) | ||
| 203 | + response.status.should == 405 | ||
| 204 | + json_response['message'].should == 'Method Not Allowed' | ||
| 205 | + end | ||
| 206 | + | ||
| 207 | + it "should return 401 if user has no permissions to merge" do | ||
| 208 | + user2 = create(:user) | ||
| 209 | + project.team << [user2, :reporter] | ||
| 210 | + put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user2) | ||
| 211 | + response.status.should == 401 | ||
| 212 | + json_response['message'].should == '401 Unauthorized' | ||
| 191 | end | 213 | end |
| 192 | end | 214 | end |
| 193 | 215 |