Commit 4f2b552b authored by Robert Speicher's avatar Robert Speicher

Merge branch 'approvals-api' into 'master'

Add Approvals API endpoint

- Added endpoint to retrieve approval status of MR
- Added endpoint to approve MR

Fixes #255

See merge request !449
parents 74c2e078 dbd91a93
......@@ -4,6 +4,7 @@ v 8.9.0 (unreleased)
- Fix nil user handling in UpdateMirrorService
- Allow LDAP to mark users as external based on their group membership. !432
- Instrument instance methods of Gitlab::InsecureKeyFingerprint class
- Add API endpoint for Merge Request Approvals !449
v 8.8.4
- Remove license overusage message
......
......@@ -485,6 +485,108 @@ Parameters:
}
```
## Merge Request Approvals
>**Note:** This API endpoint is only available on 8.9 EE and above.
You can request information about a merge request's approval status using the
following endpoint:
```
GET /projects/:id/merge_requests/:merge_request_id/approvals
```
**Parameters:**
| Attribute | Type | Required | Description |
|--------------------|---------|----------|---------------------|
| `id` | integer | yes | The ID of a project |
| `merge_request_id` | integer | yes | The ID of MR |
```json
{
"id": 5,
"iid": 5,
"project_id": 1,
"title": "Approvals API",
"description": "Test",
"state": "opened",
"created_at": "2016-06-08T00:19:52.638Z",
"updated_at": "2016-06-08T21:20:42.470Z",
"merge_status": "can_be_merged",
"approvals_required": 2,
"approvals_missing": 1,
"approved_by": [
{
"user": {
"name": "Administrator",
"username": "root",
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
"web_url": "http://localhost:3000/u/root"
}
}
]
}
```
## Approve Merge Request
>**Note:** This API endpoint is only available on 8.9 EE and above.
If you are allowed to, you can approve a merge request using the following
endpoint:
```
POST /projects/:id/merge_requests/:merge_request_id/approvals
```
**Parameters:**
| Attribute | Type | Required | Description |
|--------------------|---------|----------|---------------------|
| `id` | integer | yes | The ID of a project |
| `merge_request_id` | integer | yes | The ID of MR |
```json
{
"id": 5,
"iid": 5,
"project_id": 1,
"title": "Approvals API",
"description": "Test",
"state": "opened",
"created_at": "2016-06-08T00:19:52.638Z",
"updated_at": "2016-06-09T21:32:14.105Z",
"merge_status": "can_be_merged",
"approvals_required": 2,
"approvals_missing": 0,
"approved_by": [
{
"user": {
"name": "Administrator",
"username": "root",
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
"web_url": "http://localhost:3000/u/root"
}
},
{
"user": {
"name": "Nico Cartwright",
"username": "ryley",
"id": 2,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/cf7ad14b34162a76d593e3affca2adca?s=80\u0026d=identicon",
"web_url": "http://localhost:3000/u/ryley"
}
}
]
}
```
## Cancel Merge When Build Succeeds
If successful you'll get `200 OK`.
......
......@@ -216,6 +216,17 @@ module API
end
end
class Approvals < Grape::Entity
expose :user, using: Entities::UserBasic
end
class MergeRequestApprovals < ProjectEntity
expose :merge_status
expose :approvals_required
expose :approvals_left
expose :approvals, as: :approved_by, using: Entities::Approvals
end
class SSHKey < Grape::Entity
expose :id, :title, :key, :created_at
end
......
......@@ -332,6 +332,41 @@ module API
issues = ::Kaminari.paginate_array(merge_request.closes_issues(current_user))
present paginate(issues), with: Entities::Issue, current_user: current_user
end
# Get the status of the merge request's approvals
#
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
# Examples:
# GET /projects/:id/merge_requests/:merge_request_id/approvals
#
get "#{path}/approvals" do
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :read_merge_request, merge_request
present merge_request, with: Entities::MergeRequestApprovals, current_user: current_user
end
# Approve a merge request
#
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
# Examples:
# POST /projects/:id/merge_requests/:merge_request_id/approvals
#
post "#{path}/approve" do
merge_request = user_project.merge_requests.find(params[:merge_request_id])
unauthorized! unless merge_request.can_approve?(current_user)
::MergeRequests::ApprovalService
.new(user_project, current_user)
.execute(merge_request)
present merge_request, with: Entities::MergeRequestApprovals, current_user: current_user
end
end
end
end
......
......@@ -598,6 +598,29 @@ describe API::API, api: true do
end
end
describe 'GET :id/merge_requests/:merge_request_id/approvals' do
it 'retrieves the approval status' do
project.update_attribute(:approvals_before_merge, 2)
get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/approvals", user)
expect(response.status).to eq(200)
expect(json_response['approvals_required']).to eq 2
end
end
describe 'POST :id/merge_requests/:merge_request_id/approve' do
it 'approves the merge request' do
project.update_attribute(:approvals_before_merge, 2)
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/approve", user)
expect(response.status).to eq(201)
expect(json_response['approvals_left']).to eq(1)
expect(json_response['approved_by'][0]['user']['username']).to eq(user.username)
end
end
def mr_with_later_created_and_updated_at_time
merge_request
merge_request.created_at += 1.hour
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment