Add top-level /merge_requests API endpoint
And add support for additional query parameters: - `author_id`: Returns merge requests created by the given user `id` - `assignee_id`: Returns merge requests assigned to the given user `id` - `scope`: Return merge requests for the given scope: `created-by-me`, `assigned-to-me` or `all`
This commit is contained in:
parent
27df74ad41
commit
d7505de8b3
5 changed files with 244 additions and 31 deletions
|
@ -10,6 +10,7 @@
|
|||
# group_id: integer
|
||||
# project_id: integer
|
||||
# milestone_title: string
|
||||
# author_id: integer
|
||||
# assignee_id: integer
|
||||
# search: string
|
||||
# label_name: string
|
||||
|
|
4
changelogs/unreleased/tc-api-root-merge-requests.yml
Normal file
4
changelogs/unreleased/tc-api-root-merge-requests.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add top-level merge_requests API endpoint
|
||||
merge_request: 13060
|
||||
author:
|
|
@ -1,7 +1,99 @@
|
|||
# Merge requests API
|
||||
|
||||
Every API call to merge requests must be authenticated.
|
||||
|
||||
## List merge requests
|
||||
|
||||
Get all merge requests the authenticated user has access to.
|
||||
The `state` parameter can be used to get only merge requests with a
|
||||
given state (`opened`, `closed`, or `merged`) or all of them (`all`).
|
||||
The pagination parameters `page` and `per_page` can be used to
|
||||
restrict the list of merge requests.
|
||||
|
||||
```
|
||||
GET /merge_requests
|
||||
GET /merge_requests?state=opened
|
||||
GET /merge_requests?state=all
|
||||
GET /merge_requests?milestone=release
|
||||
GET /merge_requests?labels=bug,reproduced
|
||||
GET /merge_requests?author_id=5
|
||||
GET /merge_requests?scope=assigned-to-me
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, or `merged`|
|
||||
| `order_by`| string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
|
||||
| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
|
||||
| `milestone` | string | no | Return merge requests for a specific milestone |
|
||||
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
|
||||
| `labels` | string | no | Return merge requests matching a comma separated list of labels |
|
||||
| `created_after` | datetime | no | Return merge requests created after the given time (inclusive) |
|
||||
| `created_before` | datetime | no | Return merge requests created before the given time (inclusive) |
|
||||
| `author_id` | integer | no | Returns merge requests created by the given user `id` |
|
||||
| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id` |
|
||||
| `scope` | string | no | Return merge requests for the given scope: `created-by-me`, `assigned-to-me` or `all` |
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"iid": 1,
|
||||
"target_branch": "master",
|
||||
"source_branch": "test1",
|
||||
"project_id": 3,
|
||||
"title": "test1",
|
||||
"state": "opened",
|
||||
"upvotes": 0,
|
||||
"downvotes": 0,
|
||||
"author": {
|
||||
"id": 1,
|
||||
"username": "admin",
|
||||
"email": "admin@example.com",
|
||||
"name": "Administrator",
|
||||
"state": "active",
|
||||
"created_at": "2012-04-29T08:46:00Z"
|
||||
},
|
||||
"assignee": {
|
||||
"id": 1,
|
||||
"username": "admin",
|
||||
"email": "admin@example.com",
|
||||
"name": "Administrator",
|
||||
"state": "active",
|
||||
"created_at": "2012-04-29T08:46:00Z"
|
||||
},
|
||||
"source_project_id": 2,
|
||||
"target_project_id": 3,
|
||||
"labels": [ ],
|
||||
"description": "fixed login page css paddings",
|
||||
"work_in_progress": false,
|
||||
"milestone": {
|
||||
"id": 5,
|
||||
"iid": 1,
|
||||
"project_id": 3,
|
||||
"title": "v2.0",
|
||||
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
|
||||
"state": "closed",
|
||||
"created_at": "2015-02-02T19:49:26.013Z",
|
||||
"updated_at": "2015-02-02T19:49:26.013Z",
|
||||
"due_date": null
|
||||
},
|
||||
"merge_when_pipeline_succeeds": true,
|
||||
"merge_status": "can_be_merged",
|
||||
"sha": "8888888888888888888888888888888888888888",
|
||||
"merge_commit_sha": null,
|
||||
"user_notes_count": 1,
|
||||
"should_remove_source_branch": true,
|
||||
"force_remove_source_branch": false,
|
||||
"web_url": "http://example.com/example/example/merge_requests/1"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## List project merge requests
|
||||
|
||||
Get all merge requests for this project.
|
||||
The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`).
|
||||
The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests.
|
||||
|
|
|
@ -4,14 +4,75 @@ module API
|
|||
|
||||
before { authenticate! }
|
||||
|
||||
helpers ::Gitlab::IssuableMetadata
|
||||
|
||||
helpers do
|
||||
def find_merge_requests(args = {})
|
||||
args = params.merge(args)
|
||||
|
||||
args[:milestone_title] = args.delete(:milestone)
|
||||
args[:label_name] = args.delete(:labels)
|
||||
|
||||
merge_requests = MergeRequestsFinder.new(current_user, args).execute
|
||||
.reorder(args[:order_by] => args[:sort])
|
||||
merge_requests = paginate(merge_requests)
|
||||
.preload(:target_project)
|
||||
|
||||
return merge_requests if args[:view] == 'simple'
|
||||
|
||||
merge_requests
|
||||
.preload(:notes, :author, :assignee, :milestone, :merge_request_diff, :labels)
|
||||
end
|
||||
|
||||
params :merge_requests_params do
|
||||
optional :state, type: String, values: %w[opened closed merged all], default: 'all',
|
||||
desc: 'Return opened, closed, merged, or all merge requests'
|
||||
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
|
||||
desc: 'Return merge requests ordered by `created_at` or `updated_at` fields.'
|
||||
optional :sort, type: String, values: %w[asc desc], default: 'desc',
|
||||
desc: 'Return merge requests sorted in `asc` or `desc` order.'
|
||||
optional :milestone, type: String, desc: 'Return merge requests for a specific milestone'
|
||||
optional :labels, type: String, desc: 'Comma-separated list of label names'
|
||||
optional :created_after, type: DateTime, desc: 'Return merge requests created after the specified time'
|
||||
optional :created_before, type: DateTime, desc: 'Return merge requests created before the specified time'
|
||||
optional :view, type: String, values: %w[simple], desc: 'If simple, returns the `iid`, URL, title, description, and basic state of merge request'
|
||||
optional :author_id, type: Integer, desc: 'Return merge requests which are authored by the user with the given ID'
|
||||
optional :assignee_id, type: Integer, desc: 'Return merge requests which are assigned to the user with the given ID'
|
||||
optional :scope, type: String, values: %w[created-by-me assigned-to-me all], default: 'all',
|
||||
desc: 'Return merge requests for the given scope: `created-by-me`, `assigned-to-me` or `all`'
|
||||
use :pagination
|
||||
end
|
||||
end
|
||||
|
||||
resource :merge_requests do
|
||||
desc 'List merge requests' do
|
||||
success Entities::MergeRequestBasic
|
||||
end
|
||||
params do
|
||||
use :merge_requests_params
|
||||
end
|
||||
get do
|
||||
merge_requests = find_merge_requests
|
||||
|
||||
options = { with: Entities::MergeRequestBasic,
|
||||
current_user: current_user }
|
||||
|
||||
if params[:view] == 'simple'
|
||||
options[:with] = Entities::MergeRequestSimple
|
||||
else
|
||||
options[:issuable_metadata] = issuable_meta_data(merge_requests, 'MergeRequest')
|
||||
end
|
||||
|
||||
present merge_requests, options
|
||||
end
|
||||
end
|
||||
|
||||
params do
|
||||
requires :id, type: String, desc: 'The ID of a project'
|
||||
end
|
||||
resource :projects, requirements: { id: %r{[^/]+} } do
|
||||
include TimeTrackingEndpoints
|
||||
|
||||
helpers ::Gitlab::IssuableMetadata
|
||||
|
||||
helpers do
|
||||
def handle_merge_request_errors!(errors)
|
||||
if errors[:project_access].any?
|
||||
|
@ -29,23 +90,6 @@ module API
|
|||
render_api_error!(errors, 400)
|
||||
end
|
||||
|
||||
def find_merge_requests(args = {})
|
||||
args = params.merge(args)
|
||||
|
||||
args[:milestone_title] = args.delete(:milestone)
|
||||
args[:label_name] = args.delete(:labels)
|
||||
|
||||
merge_requests = MergeRequestsFinder.new(current_user, args).execute
|
||||
.reorder(args[:order_by] => args[:sort])
|
||||
merge_requests = paginate(merge_requests)
|
||||
.preload(:target_project)
|
||||
|
||||
return merge_requests if args[:view] == 'simple'
|
||||
|
||||
merge_requests
|
||||
.preload(:notes, :author, :assignee, :milestone, :merge_request_diff, :labels)
|
||||
end
|
||||
|
||||
params :optional_params_ce do
|
||||
optional :description, type: String, desc: 'The description of the merge request'
|
||||
optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request'
|
||||
|
@ -63,19 +107,8 @@ module API
|
|||
success Entities::MergeRequestBasic
|
||||
end
|
||||
params do
|
||||
optional :state, type: String, values: %w[opened closed merged all], default: 'all',
|
||||
desc: 'Return opened, closed, merged, or all merge requests'
|
||||
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
|
||||
desc: 'Return merge requests ordered by `created_at` or `updated_at` fields.'
|
||||
optional :sort, type: String, values: %w[asc desc], default: 'desc',
|
||||
desc: 'Return merge requests sorted in `asc` or `desc` order.'
|
||||
use :merge_requests_params
|
||||
optional :iids, type: Array[Integer], desc: 'The IID array of merge requests'
|
||||
optional :milestone, type: String, desc: 'Return merge requests for a specific milestone'
|
||||
optional :labels, type: String, desc: 'Comma-separated list of label names'
|
||||
optional :created_after, type: DateTime, desc: 'Return merge requests created after the specified time'
|
||||
optional :created_before, type: DateTime, desc: 'Return merge requests created before the specified time'
|
||||
optional :view, type: String, values: %w[simple], desc: 'If simple, returns the `iid`, URL, title, description, and basic state of merge request'
|
||||
use :pagination
|
||||
end
|
||||
get ":id/merge_requests" do
|
||||
authorize! :read_merge_request, user_project
|
||||
|
|
|
@ -26,6 +26,89 @@ describe API::MergeRequests do
|
|||
project.team << [user, :reporter]
|
||||
end
|
||||
|
||||
describe 'GET /merge_requests' do
|
||||
context 'when unauthenticated' do
|
||||
it 'returns authentication error' do
|
||||
get api('/merge_requests')
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated' do
|
||||
let!(:project2) { create(:empty_project, :public, namespace: user.namespace) }
|
||||
let!(:merge_request2) { create(:merge_request, :simple, author: user, assignee: user, source_project: project2, target_project: project2) }
|
||||
let(:user2) { create(:user) }
|
||||
|
||||
it 'returns an array of all merge requests' do
|
||||
get api('/merge_requests', user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.map { |mr| mr['id'] })
|
||||
.to contain_exactly(merge_request.id, merge_request_closed.id, merge_request_merged.id, merge_request2.id)
|
||||
end
|
||||
|
||||
it 'does not return unauthorized merge requests' do
|
||||
private_project = create(:empty_project, :private)
|
||||
merge_request3 = create(:merge_request, :simple, source_project: private_project, target_project: private_project, source_branch: 'other-branch')
|
||||
|
||||
get api('/merge_requests', user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.map { |mr| mr['id'] })
|
||||
.not_to include(merge_request3.id)
|
||||
end
|
||||
|
||||
it 'returns an array of merge requests authored by the given user' do
|
||||
merge_request3 = create(:merge_request, :simple, author: user2, assignee: user, source_project: project2, target_project: project2, source_branch: 'other-branch')
|
||||
|
||||
get api('/merge_requests', user), author_id: user2.id
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.length).to eq(1)
|
||||
expect(json_response.first['id']).to eq(merge_request3.id)
|
||||
end
|
||||
|
||||
it 'returns an array of merge requests assigned to the given user' do
|
||||
merge_request3 = create(:merge_request, :simple, author: user, assignee: user2, source_project: project2, target_project: project2, source_branch: 'other-branch')
|
||||
|
||||
get api('/merge_requests', user), assignee_id: user2.id
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.length).to eq(1)
|
||||
expect(json_response.first['id']).to eq(merge_request3.id)
|
||||
end
|
||||
|
||||
it 'returns an array of merge requests assigned to me' do
|
||||
merge_request3 = create(:merge_request, :simple, author: user, assignee: user2, source_project: project2, target_project: project2, source_branch: 'other-branch')
|
||||
|
||||
get api('/merge_requests', user2), scope: 'assigned-to-me'
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.length).to eq(1)
|
||||
expect(json_response.first['id']).to eq(merge_request3.id)
|
||||
end
|
||||
|
||||
it 'returns an array of merge requests created by me' do
|
||||
merge_request3 = create(:merge_request, :simple, author: user2, assignee: user, source_project: project2, target_project: project2, source_branch: 'other-branch')
|
||||
|
||||
get api('/merge_requests', user2), scope: 'created-by-me'
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.length).to eq(1)
|
||||
expect(json_response.first['id']).to eq(merge_request3.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/merge_requests" do
|
||||
context "when unauthenticated" do
|
||||
it "returns authentication error" do
|
||||
|
|
Loading…
Reference in a new issue