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 | 15 | - Fix wiki backup skip bug |
16 | 16 | - Two Step MR creation process |
17 | 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 | 20 | v 6.8.0 |
20 | 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 | 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 | 240 | ## Post comment to MR |
193 | 241 | |
194 | 242 | Adds a comment to a merge request. | ... | ... |
lib/api/merge_requests.rb
... | ... | @@ -34,7 +34,7 @@ module API |
34 | 34 | when "closed" then user_project.merge_requests.closed |
35 | 35 | when "merged" then user_project.merge_requests.merged |
36 | 36 | else user_project.merge_requests |
37 | - end | |
37 | + end | |
38 | 38 | |
39 | 39 | present paginate(mrs), with: Entities::MergeRequest |
40 | 40 | end |
... | ... | @@ -111,6 +111,49 @@ module API |
111 | 111 | end |
112 | 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 | 157 | # Get a merge request's comments |
115 | 158 | # |
116 | 159 | # Parameters: | ... | ... |
spec/requests/api/merge_requests_spec.rb
... | ... | @@ -183,11 +183,33 @@ describe API::API, api: true do |
183 | 183 | end |
184 | 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 | 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 | 213 | end |
192 | 214 | end |
193 | 215 | ... | ... |