Add params validations and remove extra params support
Remove label_name and milestone_title params support Add mutually_exclusive validation for author_id and author_username Add mutually_exclusive validation for assignee_id and assignee_username Add validation to allow single value for asignee_username on CE Add separate issue_stats_params helper for statistics params and reuse in issues_params.
This commit is contained in:
parent
a4fbf39eca
commit
f117c032ac
11 changed files with 383 additions and 75 deletions
|
@ -275,14 +275,6 @@ class IssuableFinder
|
|||
params[:assignee_username].present?
|
||||
end
|
||||
|
||||
def assignee_username
|
||||
if params[:assignee_username].is_a?(Array)
|
||||
params[:assignee_username].first
|
||||
else
|
||||
params[:assignee_username]
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def assignee
|
||||
return @assignee if defined?(@assignee)
|
||||
|
@ -291,7 +283,7 @@ class IssuableFinder
|
|||
if assignee_id?
|
||||
User.find_by(id: params[:assignee_id])
|
||||
elsif assignee_username?
|
||||
User.find_by_username(assignee_username)
|
||||
User.find_by_username(params[:assignee_username])
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add issues_statistics api endpoints and extend issues search api
|
||||
merge_request: 27366
|
||||
author:
|
||||
type: added
|
|
@ -37,23 +37,26 @@ GET /issues?confidential=true
|
|||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
|
||||
| `state` | string | no | Return `all` issues or just those that are `opened` or `closed` |
|
||||
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
|
||||
| `with_labels_data` | Boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:text_color`. Default is `false`. |
|
||||
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
|
||||
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
|
||||
| `author_id` | integer | no | Return issues created by the given user `id`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `assignee_id` | integer | no | Return issues assigned to the given user `id`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `author_username` | string | no | Return issues created by the given `username`. Simillar to `author_id` and mutually exclusive with `author_id`. |
|
||||
| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Simillar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
|
||||
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
|
||||
| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
|
||||
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
|
||||
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
|
||||
| `search` | string | no | Search issues against their `title` and `description` |
|
||||
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
|
||||
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
|
||||
| `created_after` | datetime | no | Return issues created on or after the given time |
|
||||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
| `confidential ` | Boolean | no | Filter confidential or public issues. |
|
||||
| `confidential ` | Boolean | no | Filter confidential or public issues. |
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/issues
|
||||
|
@ -109,7 +112,7 @@ Example response:
|
|||
"title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.",
|
||||
"created_at" : "2016-01-04T15:31:51.081Z",
|
||||
"iid" : 6,
|
||||
"labels" : [],
|
||||
"labels" : ["foo", "bar"],
|
||||
"upvotes": 4,
|
||||
"downvotes": 0,
|
||||
"merge_requests_count": 0,
|
||||
|
@ -122,8 +125,17 @@ Example response:
|
|||
"human_time_estimate": null,
|
||||
"human_total_time_spent": null
|
||||
},
|
||||
"has_tasks": true,
|
||||
"task_status": "10 of 15 tasks completed",
|
||||
"confidential": false,
|
||||
"discussion_locked": false
|
||||
"discussion_locked": false,
|
||||
"_links":{
|
||||
"self":"http://example.com/api/v4/projects/1/issues/76",
|
||||
"notes":"`http://example.com/`api/v4/projects/1/issues/76/notes",
|
||||
"award_emoji":"http://example.com/api/v4/projects/1/issues/76/award_emoji",
|
||||
"project":"http://example.com/api/v4/projects/1"
|
||||
},
|
||||
"subscribed": false
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -158,11 +170,14 @@ GET /groups/:id/issues?confidential=true
|
|||
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
|
||||
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
|
||||
| `with_labels_data` | Boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:text_color`. Default is `false`. |
|
||||
| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
|
||||
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
|
||||
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
|
||||
| `author_id` | integer | no | Return issues created by the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `assignee_id` | integer | no | Return issues assigned to the given user `id`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `author_username` | string | no | Return issues created by the given `username`. Simillar to `author_id` and mutually exclusive with `author_id`. |
|
||||
| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Simillar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
|
||||
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
|
||||
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
|
||||
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
|
||||
|
@ -221,7 +236,7 @@ Example response:
|
|||
"id" : 9,
|
||||
"name" : "Dr. Luella Kovacek"
|
||||
},
|
||||
"labels" : [],
|
||||
"labels" : ["foo", "bar"],
|
||||
"upvotes": 4,
|
||||
"downvotes": 0,
|
||||
"merge_requests_count": 0,
|
||||
|
@ -240,8 +255,17 @@ Example response:
|
|||
"human_time_estimate": null,
|
||||
"human_total_time_spent": null
|
||||
},
|
||||
"has_tasks": true,
|
||||
"task_status": "10 of 15 tasks completed",
|
||||
"confidential": false,
|
||||
"discussion_locked": false
|
||||
"discussion_locked": false,
|
||||
"_links":{
|
||||
"self":"http://example.com/api/v4/projects/4/issues/41",
|
||||
"notes":"`http://example.com/`api/v4/projects/4/issues/41/notes",
|
||||
"award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji",
|
||||
"project":"http://example.com/api/v4/projects/4"
|
||||
},
|
||||
"subscribed": false
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -277,10 +301,13 @@ GET /projects/:id/issues?confidential=true
|
|||
| `iids[]` | Array[integer] | no | Return only the milestone having the given `iid` |
|
||||
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
|
||||
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
|
||||
| `with_labels_data` | Boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:text_color`. Default is `false`. |
|
||||
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
|
||||
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
|
||||
| `author_id` | integer | no | Return issues created by the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `assignee_id` | integer | no | Return issues assigned to the given user `id`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `author_username` | string | no | Return issues created by the given `username`. Simillar to `author_id` and mutually exclusive with `author_id`. |
|
||||
| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Simillar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
|
||||
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
|
||||
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
|
||||
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
|
||||
|
@ -340,7 +367,7 @@ Example response:
|
|||
"id" : 9,
|
||||
"name" : "Dr. Luella Kovacek"
|
||||
},
|
||||
"labels" : [],
|
||||
"labels" : ["foo", "bar"],
|
||||
"upvotes": 4,
|
||||
"downvotes": 0,
|
||||
"merge_requests_count": 0,
|
||||
|
@ -366,8 +393,17 @@ Example response:
|
|||
"human_time_estimate": null,
|
||||
"human_total_time_spent": null
|
||||
},
|
||||
"has_tasks": true,
|
||||
"task_status": "10 of 15 tasks completed",
|
||||
"confidential": false,
|
||||
"discussion_locked": false
|
||||
"discussion_locked": false,
|
||||
"_links":{
|
||||
"self":"http://example.com/api/v4/projects/4/issues/41",
|
||||
"notes":"`http://example.com/`api/v4/projects/4/issues/41/notes",
|
||||
"award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji",
|
||||
"project":"http://example.com/api/v4/projects/4"
|
||||
},
|
||||
"subscribed": false
|
||||
}
|
||||
]
|
||||
```
|
||||
|
|
190
doc/api/issues_statistics.md
Normal file
190
doc/api/issues_statistics.md
Normal file
|
@ -0,0 +1,190 @@
|
|||
# Issues Statistics API
|
||||
|
||||
Every API call to issues_statistics must be authenticated.
|
||||
|
||||
If a user is not a member of a project and the project is private, a `GET`
|
||||
request on that project will result to a `404` status code.
|
||||
|
||||
## Get issues statistics
|
||||
|
||||
Gets issues count statistics on all issues the authenticated user has access to. By default it
|
||||
returns only issues created by the current user. To get all issues,
|
||||
use parameter `scope=all`.
|
||||
|
||||
```
|
||||
GET /issues_statistics
|
||||
GET /issues_statistics?labels=foo
|
||||
GET /issues_statistics?labels=foo,bar
|
||||
GET /issues_statistics?labels=foo,bar&state=opened
|
||||
GET /issues_statistics?milestone=1.0.0
|
||||
GET /issues_statistics?milestone=1.0.0&state=opened
|
||||
GET /issues_statistics?iids[]=42&iids[]=43
|
||||
GET /issues_statistics?author_id=5
|
||||
GET /issues_statistics?assignee_id=5
|
||||
GET /issues_statistics?my_reaction_emoji=star
|
||||
GET /issues_statistics?search=foo&in=title
|
||||
GET /issues_statistics?confidential=true
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
|
||||
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
|
||||
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
|
||||
| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `author_username` | string | no | Return issues created by the given `username`. Simillar to `author_id` and mutually exclusive with `author_id`. |
|
||||
| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Simillar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
|
||||
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
|
||||
| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
|
||||
| `search` | string | no | Search issues against their `title` and `description` |
|
||||
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
|
||||
| `created_after` | datetime | no | Return issues created on or after the given time |
|
||||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
| `confidential ` | Boolean | no | Filter confidential or public issues. |
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/issues_statistics
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"statistics": {
|
||||
"counts": {
|
||||
"all": 20,
|
||||
"closed": 5,
|
||||
"opened": 15
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
|
||||
|
||||
**Note**: The `closed_by` attribute was [introduced in GitLab 10.6][ce-17042]. This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
|
||||
|
||||
## List group issues
|
||||
|
||||
Get a list of a group's issues.
|
||||
|
||||
```
|
||||
GET /groups/:id/issues_statistics
|
||||
GET /groups/:id/issues_statistics?labels=foo
|
||||
GET /groups/:id/issues_statistics?labels=foo,bar
|
||||
GET /groups/:id/issues_statistics?labels=foo,bar&state=opened
|
||||
GET /groups/:id/issues_statistics?milestone=1.0.0
|
||||
GET /groups/:id/issues_statistics?milestone=1.0.0&state=opened
|
||||
GET /groups/:id/issues_statistics?iids[]=42&iids[]=43
|
||||
GET /groups/:id/issues_statistics?search=issue+title+or+description
|
||||
GET /groups/:id/issues_statistics?author_id=5
|
||||
GET /groups/:id/issues_statistics?assignee_id=5
|
||||
GET /groups/:id/issues_statistics?my_reaction_emoji=star
|
||||
GET /groups/:id/issues_statistics?confidential=true
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------------- | ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
|
||||
| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
|
||||
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
|
||||
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
|
||||
| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `author_username` | string | no | Return issues created by the given `username`. Simillar to `author_id` and mutually exclusive with `author_id`. |
|
||||
| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Simillar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
|
||||
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
|
||||
| `search` | string | no | Search group issues against their `title` and `description` |
|
||||
| `created_after` | datetime | no | Return issues created on or after the given time |
|
||||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
| `confidential ` | Boolean | no | Filter confidential or public issues. |
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/4/issues_statistics
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"statistics": {
|
||||
"counts": {
|
||||
"all": 20,
|
||||
"closed": 5,
|
||||
"opened": 15
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
|
||||
|
||||
**Note**: The `closed_by` attribute was [introduced in GitLab 10.6][ce-17042]. This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
|
||||
|
||||
## List project issues
|
||||
|
||||
Get a list of a project's issues.
|
||||
|
||||
```
|
||||
GET /projects/:id/issues_statistics
|
||||
GET /projects/:id/issues_statistics?labels=foo
|
||||
GET /projects/:id/issues_statistics?labels=foo,bar
|
||||
GET /projects/:id/issues_statistics?labels=foo,bar&state=opened
|
||||
GET /projects/:id/issues_statistics?milestone=1.0.0
|
||||
GET /projects/:id/issues_statistics?milestone=1.0.0&state=opened
|
||||
GET /projects/:id/issues_statistics?iids[]=42&iids[]=43
|
||||
GET /projects/:id/issues_statistics?search=issue+title+or+description
|
||||
GET /projects/:id/issues_statistics?author_id=5
|
||||
GET /projects/:id/issues_statistics?assignee_id=5
|
||||
GET /projects/:id/issues_statistics?my_reaction_emoji=star
|
||||
GET /projects/:id/issues_statistics?confidential=true
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------------- | ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `iids[]` | Array[integer] | no | Return only the milestone having the given `iid` |
|
||||
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
|
||||
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
|
||||
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
|
||||
| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `author_username` | string | no | Return issues created by the given `username`. Simillar to `author_id` and mutually exclusive with `author_id`. |
|
||||
| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
|
||||
| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Simillar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
|
||||
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
|
||||
| `search` | string | no | Search project issues against their `title` and `description` |
|
||||
| `created_after` | datetime | no | Return issues created on or after the given time |
|
||||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
| `confidential ` | Boolean | no | Filter confidential or public issues. |
|
||||
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues_statistics
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"statistics": {
|
||||
"counts": {
|
||||
"all": 20,
|
||||
"closed": 5,
|
||||
"opened": 15
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
|
||||
|
||||
**Note**: The `closed_by` attribute was [introduced in GitLab 10.6][ce-17042]. This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
|
||||
|
|
@ -24,7 +24,6 @@ module API
|
|||
|
||||
args.delete(:id)
|
||||
args[:milestone_title] ||= args.delete(:milestone)
|
||||
args[:milestone_title] ||= args.delete(:milestone_title)
|
||||
args[:label_name] ||= args.delete(:labels)
|
||||
args[:scope] = args[:scope].underscore if args[:scope]
|
||||
|
||||
|
@ -35,10 +34,8 @@ module API
|
|||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
finder = issue_finder(args)
|
||||
issues = finder.execute.with_api_entity_associations
|
||||
order_by = declared_params[:sort].present? && %w(asc desc).include?(declared_params[:sort].downcase)
|
||||
issues = issues.reorder(order_options_with_tie_breaker) if order_by
|
||||
|
||||
issues
|
||||
issues.reorder(order_options_with_tie_breaker)
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
end
|
||||
|
||||
|
|
|
@ -19,15 +19,10 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
params :issues_params do
|
||||
optional :labels, :label_name, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names'
|
||||
optional :with_labels_data, type: Boolean, desc: 'Return more label data than just lable title', default: false
|
||||
params :issues_stats_params do
|
||||
optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names'
|
||||
optional :milestone, type: String, desc: 'Milestone title'
|
||||
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
|
||||
desc: 'Return issues ordered by `created_at` or `updated_at` fields.'
|
||||
optional :sort, type: String, default: 'desc',
|
||||
desc: 'Return issues sorted in `asc` or `desc` order.'
|
||||
optional :milestone, :milestone_title, type: String, desc: 'Return issues for a specific milestone'
|
||||
optional :milestone, type: String, desc: 'Return issues for a specific milestone'
|
||||
optional :iids, type: Array[Integer], desc: 'The IID array of issues'
|
||||
optional :search, type: String, desc: 'Search issues for text present in the title, description, or any combination of these'
|
||||
optional :in, type: String, desc: '`title`, `description`, or a string joining them with comma'
|
||||
|
@ -35,23 +30,39 @@ module API
|
|||
optional :created_before, type: DateTime, desc: 'Return issues created before the specified time'
|
||||
optional :updated_after, type: DateTime, desc: 'Return issues updated after the specified time'
|
||||
optional :updated_before, type: DateTime, desc: 'Return issues updated before the specified time'
|
||||
|
||||
optional :author_id, type: Integer, desc: 'Return issues which are authored by the user with the given ID'
|
||||
optional :author_username, type: String, desc: 'Return issues which are authored by the user with the given username'
|
||||
mutually_exclusive :author_id, :author_username
|
||||
|
||||
optional :assignee_id, types: [Integer, String], integer_none_any: true,
|
||||
desc: 'Return issues which are assigned to the user with the given ID'
|
||||
optional :assignee_username, type: Array[String],
|
||||
optional :assignee_username, type: Array[String], check_assignees_count: true,
|
||||
coerce_with: Validations::CheckAssigneesCount.coerce,
|
||||
desc: 'Return issues which are assigned to the user with the given username'
|
||||
mutually_exclusive :assignee_id, :assignee_username
|
||||
|
||||
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
|
||||
desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
|
||||
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
|
||||
optional :confidential, type: Boolean, desc: 'Filter confidential or public issues'
|
||||
optional :state, type: String, values: %w[opened closed all], default: 'all',
|
||||
desc: 'Return opened, closed, or all issues'
|
||||
use :pagination
|
||||
|
||||
use :issues_params_ee if Gitlab.ee?
|
||||
end
|
||||
|
||||
params :issues_params do
|
||||
optional :with_labels_data, type: Boolean, desc: 'Return more label data than just lable title', default: false
|
||||
optional :state, type: String, values: %w[opened closed all], default: 'all',
|
||||
desc: 'Return opened, closed, or all issues'
|
||||
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
|
||||
desc: 'Return issues ordered by `created_at` or `updated_at` fields.'
|
||||
optional :sort, type: String, values: %w[asc desc], default: 'desc',
|
||||
desc: 'Return issues sorted in `asc` or `desc` order.'
|
||||
|
||||
use :issues_stats_params
|
||||
use :pagination
|
||||
end
|
||||
|
||||
params :issue_params do
|
||||
optional :description, type: String, desc: 'The description of an issue'
|
||||
optional :assignee_ids, type: Array[Integer], desc: 'The array of user IDs to assign issue'
|
||||
|
@ -68,7 +79,7 @@ module API
|
|||
|
||||
desc "Get currently authenticated user's issues statistics"
|
||||
params do
|
||||
use :issues_params
|
||||
use :issues_stats_params
|
||||
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all], default: 'created_by_me',
|
||||
desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
|
||||
end
|
||||
|
@ -131,7 +142,7 @@ module API
|
|||
|
||||
desc 'Get statistics for the list of group issues'
|
||||
params do
|
||||
use :issues_params
|
||||
use :issues_stats_params
|
||||
end
|
||||
get ":id/issues_statistics" do
|
||||
group = find_group!(params[:id])
|
||||
|
@ -172,7 +183,7 @@ module API
|
|||
|
||||
desc 'Get statistics for the list of project issues'
|
||||
params do
|
||||
use :issues_params
|
||||
use :issues_stats_params
|
||||
end
|
||||
get ":id/issues_statistics" do
|
||||
project = find_project!(params[:id])
|
||||
|
|
36
lib/api/validations/check_assignees_count.rb
Normal file
36
lib/api/validations/check_assignees_count.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
module Validations
|
||||
class CheckAssigneesCount < Grape::Validations::Base
|
||||
def self.coerce
|
||||
lambda do |value|
|
||||
case value
|
||||
when String
|
||||
[value]
|
||||
when Array
|
||||
value
|
||||
when CheckAssigneesCount
|
||||
value
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def validate_param!(attr_name, params)
|
||||
unless param_allowed?(attr_name, params)
|
||||
raise Grape::Exceptions::Validation,
|
||||
params: [@scope.full_name(attr_name)],
|
||||
message: "allows one value, but found #{params[attr_name].size}: #{params[attr_name].join(", ")}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def param_allowed?(attr_name, params)
|
||||
params[attr_name].size <= 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -619,11 +619,33 @@ describe API::Issues do
|
|||
let!(:issue2) { create(:issue, author: user2, project: group_project, created_at: 2.days.ago) }
|
||||
let!(:issue3) { create(:issue, author: user2, assignees: [assignee, another_assignee], project: group_project, created_at: 1.day.ago) }
|
||||
|
||||
it 'returns issues with multiple assignees' do
|
||||
get api("/groups/#{group.id}/issues", user), params: { assignee_username: [assignee.username, another_assignee.username] }
|
||||
it 'returns issues with by assignee_username' do
|
||||
get api(base_url, user), params: { assignee_username: [assignee.username], scope: 'all' }
|
||||
|
||||
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
|
||||
expect_paginated_array_response([issue3.id, group_confidential_issue.id])
|
||||
end
|
||||
|
||||
it 'returns issues by assignee_username as string' do
|
||||
get api(base_url, user), params: { assignee_username: assignee.username, scope: 'all' }
|
||||
|
||||
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
|
||||
expect_paginated_array_response([issue3.id, group_confidential_issue.id])
|
||||
end
|
||||
|
||||
it 'returns error when multiple assignees are passed' do
|
||||
get api(base_url, user), params: { assignee_username: [assignee.username, another_assignee.username], scope: 'all' }
|
||||
|
||||
expect(response).to have_gitlab_http_status(400)
|
||||
expect(json_response["error"]).to include("allows one value, but found 2")
|
||||
end
|
||||
|
||||
it 'returns error when assignee_username and assignee_id are passed together' do
|
||||
get api(base_url, user), params: { assignee_username: [assignee.username], assignee_id: another_assignee.id, scope: 'all' }
|
||||
|
||||
expect(response).to have_gitlab_http_status(400)
|
||||
expect(json_response["error"]).to include("mutually exclusive")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -490,11 +490,33 @@ describe API::Issues do
|
|||
let!(:issue2) { create(:issue, author: user2, project: project, created_at: 2.days.ago) }
|
||||
let!(:issue3) { create(:issue, author: user2, assignees: [assignee, another_assignee], project: project, created_at: 1.day.ago) }
|
||||
|
||||
it 'returns issues with multiple assignees' do
|
||||
get api("#{base_url}/issues", user), params: { assignee_username: [assignee.username, another_assignee.username] }
|
||||
it 'returns issues by assignee_username' do
|
||||
get api("/issues", user), params: { assignee_username: [assignee.username], scope: 'all' }
|
||||
|
||||
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
|
||||
expect_paginated_array_response([confidential_issue.id, issue3.id])
|
||||
end
|
||||
|
||||
it 'returns issues by assignee_username as string' do
|
||||
get api("/issues", user), params: { assignee_username: assignee.username, scope: 'all' }
|
||||
|
||||
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
|
||||
expect_paginated_array_response([confidential_issue.id, issue3.id])
|
||||
end
|
||||
|
||||
it 'returns error when multiple assignees are passed' do
|
||||
get api("/issues", user), params: { assignee_username: [assignee.username, another_assignee.username], scope: 'all' }
|
||||
|
||||
expect(response).to have_gitlab_http_status(400)
|
||||
expect(json_response["error"]).to include("allows one value, but found 2")
|
||||
end
|
||||
|
||||
it 'returns error when assignee_username and assignee_id are passed together' do
|
||||
get api("/issues", user), params: { assignee_username: [assignee.username], assignee_id: another_assignee.id, scope: 'all' }
|
||||
|
||||
expect(response).to have_gitlab_http_status(400)
|
||||
expect(json_response["error"]).to include("mutually exclusive")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -691,11 +691,32 @@ describe API::Issues do
|
|||
let!(:issue2) { create(:issue, author: user2, project: project, created_at: 2.days.ago) }
|
||||
let!(:issue3) { create(:issue, author: user2, assignees: [assignee, another_assignee], project: project, created_at: 1.day.ago) }
|
||||
|
||||
it 'returns issues with multiple assignees' do
|
||||
it 'returns issues with by assignee_username' do
|
||||
get api("/issues", user), params: { assignee_username: [assignee.username], scope: 'all' }
|
||||
|
||||
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
|
||||
expect_paginated_array_response([confidential_issue.id, issue3.id])
|
||||
end
|
||||
|
||||
it 'returns issues by assignee_username as string' do
|
||||
get api("/issues", user), params: { assignee_username: assignee.username, scope: 'all' }
|
||||
|
||||
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
|
||||
expect_paginated_array_response([confidential_issue.id, issue3.id])
|
||||
end
|
||||
|
||||
it 'returns error when multiple assignees are passed' do
|
||||
get api("/issues", user), params: { assignee_username: [assignee.username, another_assignee.username], scope: 'all' }
|
||||
|
||||
expect(issue3.reload.assignees).to eq([assignee, another_assignee])
|
||||
expect_paginated_array_response([confidential_issue.id, issue3.id])
|
||||
expect(response).to have_gitlab_http_status(400)
|
||||
expect(json_response["error"]).to include("allows one value, but found 2")
|
||||
end
|
||||
|
||||
it 'returns error when assignee_username and assignee_id are passed together' do
|
||||
get api("/issues", user), params: { assignee_username: [assignee.username], assignee_id: another_assignee.id, scope: 'all' }
|
||||
|
||||
expect(response).to have_gitlab_http_status(400)
|
||||
expect(json_response["error"]).to include("mutually exclusive")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,19 +28,7 @@ shared_examples 'labeled issues with labels and label_name params' do
|
|||
it_behaves_like 'returns label names'
|
||||
end
|
||||
|
||||
context 'array of labeled issues when all labels match the label_name param' do
|
||||
let(:params) { { label_name: "#{label.title},#{label_b.title},#{label_c.title}" } }
|
||||
|
||||
it_behaves_like 'returns label names'
|
||||
end
|
||||
|
||||
context 'array of labeled issues when all labels match with label_name param as array' do
|
||||
let(:params) { { label_name: [label.title, label_b.title, label_c.title] } }
|
||||
|
||||
it_behaves_like 'returns label names'
|
||||
end
|
||||
|
||||
context 'with labels data' do
|
||||
context 'when with_labels_data provided' do
|
||||
context 'array of labeled issues when all labels match' do
|
||||
let(:params) { { labels: "#{label.title},#{label_b.title},#{label_c.title}", with_labels_data: true } }
|
||||
|
||||
|
@ -52,17 +40,5 @@ shared_examples 'labeled issues with labels and label_name params' do
|
|||
|
||||
it_behaves_like 'returns basic label entity'
|
||||
end
|
||||
|
||||
context 'array of labeled issues when all labels match the label_name param' do
|
||||
let(:params) { { label_name: "#{label.title},#{label_b.title},#{label_c.title}", with_labels_data: true } }
|
||||
|
||||
it_behaves_like 'returns basic label entity'
|
||||
end
|
||||
|
||||
context 'array of labeled issues when all labels match with label_name param as array' do
|
||||
let(:params) { { label_name: [label.title, label_b.title, label_c.title], with_labels_data: true } }
|
||||
|
||||
it_behaves_like 'returns basic label entity'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue