Commit 0c621708658da4b3cf88d805da5dbad920f3d27f

Authored by Dmitriy Zaporozhets
2 parents 17858d49 2d2b2da4

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
@@ -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