diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/api/epic_issues.md | 412 | ||||
-rw-r--r-- | doc/api/epic_links.md | 252 | ||||
-rw-r--r-- | doc/api/epics.md | 360 | ||||
-rw-r--r-- | doc/api/geo_nodes.md | 408 | ||||
-rw-r--r-- | doc/api/issue_links.md | 215 | ||||
-rw-r--r-- | doc/api/license.md | 176 | ||||
-rw-r--r-- | doc/api/license_templates.md | 5 | ||||
-rw-r--r-- | doc/api/managed_licenses.md | 136 | ||||
-rw-r--r-- | doc/api/merge_request_approvals.md | 425 | ||||
-rw-r--r-- | doc/api/packages.md | 152 | ||||
-rw-r--r-- | doc/api/scim.md | 235 | ||||
-rw-r--r-- | doc/api/vulnerabilities.md | 113 |
12 files changed, 2889 insertions, 0 deletions
diff --git a/doc/api/epic_issues.md b/doc/api/epic_issues.md new file mode 100644 index 00000000000..438a3361dcc --- /dev/null +++ b/doc/api/epic_issues.md @@ -0,0 +1,412 @@ +# Epic Issues API **[ULTIMATE]** + +Every API call to epic_issues must be authenticated. + +If a user is not a member of a group and the group is private, a `GET` request on that group will result to a `404` status code. + +Epics are available only in Ultimate. If epics feature is not available a `403` status code will be returned. + +## List issues for an epic +Gets all issues that are assigned to an epic and the authenticated user has access to. + +``` +GET /groups/:id/epics/:epic_iid/issues +``` + +| 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 | +| `epic_iid` | integer/string | yes | The internal ID of the epic. | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/issues/ +``` + +Example response: + +```json +[ + { + "id": 76, + "iid": 6, + "project_id": 8, + "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", + "description" : "Ratione dolores corrupti mollitia soluta quia.", + "state": "opened", + "created_at": "2017-11-15T13:39:24.670Z", + "updated_at": "2018-01-04T10:49:19.506Z", + "closed_at": null, + "labels": [], + "milestone": { + "id": 38, + "iid": 3, + "project_id": 8, + "title": "v2.0", + "description": "In tempore culpa inventore quo accusantium.", + "state": "closed", + "created_at": "2017-11-15T13:39:13.825Z", + "updated_at": "2017-11-15T13:39:13.825Z", + "due_date": null, + "start_date": null + }, + "assignees": [{ + "id": 7, + "name": "Pamella Huel", + "username": "arnita", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", + "web_url": "http://localhost:3001/arnita" + }], + "assignee": { + "id": 7, + "name": "Pamella Huel", + "username": "arnita", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", + "web_url": "http://localhost:3001/arnita" + }, + "author": { + "id": 13, + "name": "Michell Johns", + "username": "chris_hahn", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/30e3b2122ccd6b8e45e8e14a3ffb58fc?s=80&d=identicon", + "web_url": "http://localhost:3001/chris_hahn" + }, + "user_notes_count": 8, + "upvotes": 0, + "downvotes": 0, + "due_date": null, + "confidential": false, + "weight": null, + "discussion_locked": null, + "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/6", + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + }, + "_links":{ + "self": "http://localhost:3001/api/v4/projects/8/issues/6", + "notes": "http://localhost:3001/api/v4/projects/8/issues/6/notes", + "award_emoji": "http://localhost:3001/api/v4/projects/8/issues/6/award_emoji", + "project": "http://localhost:3001/api/v4/projects/8" + }, + "subscribed": true, + "epic_issue_id": 2 + } +] +``` + +**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. + +## Assign an issue to the epic + +Creates an epic - issue association. If the issue in question belongs to another epic it is unassigned from that epic. + +``` +POST /groups/:id/epics/:epic_iid/issues/:issue_id +``` + +| 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 | +| `epic_iid` | integer/string | yes | The internal ID of the epic. | +| `issue_id` | integer/string | yes | The ID of the issue. | + +```bash +curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/issues/55 +``` + +Example response: + +```json +{ + "id": 11, + "epic": { + "id": 30, + "iid": 5, + "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", + "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", + "author": { + "id": 7, + "name": "Pamella Huel", + "username": "arnita", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", + "web_url": "http://localhost:3001/arnita" + }, + "start_date": null, + "end_date": null + }, + "issue": { + "id": 55, + "iid": 13, + "project_id": 8, + "title": "Beatae laborum voluptatem voluptate eligendi ex accusamus.", + "description": "Quam veritatis debitis omnis aliquam sit.", + "state": "opened", + "created_at": "2017-11-05T13:59:12.782Z", + "updated_at": "2018-01-05T10:33:03.900Z", + "closed_at": null, + "labels": [], + "milestone": { + "id": 48, + "iid": 6, + "project_id": 8, + "title": "Sprint - Sed sed maxime temporibus ipsa ullam qui sit.", + "description": "Quos veritatis qui expedita sunt deleniti accusamus.", + "state": "active", + "created_at": "2017-11-05T13:59:12.445Z", + "updated_at": "2017-11-05T13:59:12.445Z", + "due_date": "2017-11-13", + "start_date": "2017-11-05" + }, + "assignees": [{ + "id": 10, + "name": "Lu Mayer", + "username": "kam", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", + "web_url": "http://localhost:3001/kam" + }], + "assignee": { + "id": 10, + "name": "Lu Mayer", + "username": "kam", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", + "web_url": "http://localhost:3001/kam" + }, + "author": { + "id": 25, + "name": "User 3", + "username": "user3", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80&d=identicon", + "web_url": "http://localhost:3001/user3" + }, + "user_notes_count": 0, + "upvotes": 0, + "downvotes": 0, + "due_date": null, + "confidential": false, + "weight": null, + "discussion_locked": null, + "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/13", + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + } + } +} +``` + +**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. + +## Remove an issue from the epic + +Removes an epic - issue association. + +``` +DELETE /groups/:id/epics/:epic_iid/issues/:epic_issue_id +``` + +| 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 | +| `epic_iid` | integer/string | yes | The internal ID of the epic. | +| `epic_issue_id` | integer/string | yes | The ID of the issue - epic association. | + +```bash +curl --header DELETE "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/issues/11 +``` + +Example response: + +```json +{ + "id": 11, + "epic": { + "id": 30, + "iid": 5, + "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", + "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", + "author": { + "id": 7, + "name": "Pamella Huel", + "username": "arnita", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", + "web_url": "http://localhost:3001/arnita" + }, + "start_date": null, + "end_date": null + }, + "issue": { + "id": 223, + "iid": 13, + "project_id": 8, + "title": "Beatae laborum voluptatem voluptate eligendi ex accusamus.", + "description": "Quam veritatis debitis omnis aliquam sit.", + "state": "opened", + "created_at": "2017-11-05T13:59:12.782Z", + "updated_at": "2018-01-05T10:33:03.900Z", + "closed_at": null, + "labels": [], + "milestone": { + "id": 48, + "iid": 6, + "project_id": 8, + "title": "Sprint - Sed sed maxime temporibus ipsa ullam qui sit.", + "description": "Quos veritatis qui expedita sunt deleniti accusamus.", + "state": "active", + "created_at": "2017-11-05T13:59:12.445Z", + "updated_at": "2017-11-05T13:59:12.445Z", + "due_date": "2017-11-13", + "start_date": "2017-11-05" + }, + "assignees": [{ + "id": 10, + "name": "Lu Mayer", + "username": "kam", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", + "web_url": "http://localhost:3001/kam" + }], + "assignee": { + "id": 10, + "name": "Lu Mayer", + "username": "kam", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", + "web_url": "http://localhost:3001/kam" + }, + "author": { + "id": 25, + "name": "User 3", + "username": "user3", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80&d=identicon", + "web_url": "http://localhost:3001/user3" + }, + "user_notes_count": 0, + "upvotes": 0, + "downvotes": 0, + "due_date": null, + "confidential": false, + "weight": null, + "discussion_locked": null, + "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/13", + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + } + } +} +``` + +**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. + +## Update epic - issue association + +Updates an epic - issue association. + +``` +PUT /groups/:id/epics/:epic_iid/issues/:epic_issue_id +``` + +| 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 | +| `epic_iid` | integer/string | yes | The internal ID of the epic. | +| `epic_issue_id` | integer/string | yes | The ID of the issue - epic association. | +| `move_before_id` | integer/string | no | The ID of the issue - epic association that should be placed before the link in the question. | +| `move_after_id` | integer/string | no | The ID of the issue - epic association that should be placed after the link in the question. | + +```bash +curl --header PUT "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/issues/11?move_before_id=20 +``` + +Example response: + +```json +[ + { + "id": 30, + "iid": 6, + "project_id": 8, + "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", + "description" : "Ratione dolores corrupti mollitia soluta quia.", + "state": "opened", + "created_at": "2017-11-15T13:39:24.670Z", + "updated_at": "2018-01-04T10:49:19.506Z", + "closed_at": null, + "labels": [], + "milestone": { + "id": 38, + "iid": 3, + "project_id": 8, + "title": "v2.0", + "description": "In tempore culpa inventore quo accusantium.", + "state": "closed", + "created_at": "2017-11-15T13:39:13.825Z", + "updated_at": "2017-11-15T13:39:13.825Z", + "due_date": null, + "start_date": null + }, + "assignees": [{ + "id": 7, + "name": "Pamella Huel", + "username": "arnita", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", + "web_url": "http://localhost:3001/arnita" + }], + "assignee": { + "id": 7, + "name": "Pamella Huel", + "username": "arnita", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", + "web_url": "http://localhost:3001/arnita" + }, + "author": { + "id": 13, + "name": "Michell Johns", + "username": "chris_hahn", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/30e3b2122ccd6b8e45e8e14a3ffb58fc?s=80&d=identicon", + "web_url": "http://localhost:3001/chris_hahn" + }, + "user_notes_count": 8, + "upvotes": 0, + "downvotes": 0, + "due_date": null, + "confidential": false, + "weight": null, + "discussion_locked": null, + "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/6", + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + }, + "_links":{ + "self": "http://localhost:3001/api/v4/projects/8/issues/6", + "notes": "http://localhost:3001/api/v4/projects/8/issues/6/notes", + "award_emoji": "http://localhost:3001/api/v4/projects/8/issues/6/award_emoji", + "project": "http://localhost:3001/api/v4/projects/8" + }, + "subscribed": true, + "epic_issue_id": 11, + "relative_position": 55 + } +] +``` diff --git a/doc/api/epic_links.md b/doc/api/epic_links.md new file mode 100644 index 00000000000..619ae6ea2dc --- /dev/null +++ b/doc/api/epic_links.md @@ -0,0 +1,252 @@ +# Epic Links API **[ULTIMATE]** + +>**Note:** +> This endpoint was [introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9188) in GitLab 11.8. + +Manages parent-child [epic relationships](../user/group/epics/index.md#multi-level-child-epics). + +Every API call to `epic_links` must be authenticated. + +If a user is not a member of a group and the group is private, a `GET` request on that group will result to a `404` status code. + +Epics are available only in the [Ultimate/Gold tier](https://about.gitlab.com/pricing/). If the epics feature is not available, a `403` status code will be returned. + +## List epics related to a given epic +Gets all child epics of an epic. + +``` +GET /groups/:id/epics/:epic_iid/epics +``` + +| 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 | +| `epic_iid` | integer | yes | The internal ID of the epic. | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/epics/ +``` + +Example response: + +```json +[ + { + "id": 29, + "iid": 6, + "group_id": 1, + "parent_id": 5, + "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", + "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", + "author": { + "id": 10, + "name": "Lu Mayer", + "username": "kam", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", + "web_url": "http://localhost:3001/kam" + }, + "start_date": null, + "start_date_is_fixed": false, + "start_date_fixed": null, + "start_date_from_milestones": null, + "end_date": "2018-07-31", + "due_date": "2018-07-31", + "due_date_is_fixed": false, + "due_date_fixed": null, + "due_date_from_milestones": "2018-07-31", + "created_at": "2018-07-17T13:36:22.770Z", + "updated_at": "2018-07-18T12:22:05.239Z", + "labels": [] + } +] +``` + +## Assign a child epic + +Creates an association between two epics, designating one as the parent epic and the other as the child epic. A parent epic can have multiple child epics. If the new child epic already belonged to another epic, it is unassigned from that previous parent. + +``` +POST /groups/:id/epics/:epic_iid/epics +``` + +| 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 | +| `epic_iid` | integer | yes | The internal ID of the epic. | +| `child_epic_id` | integer | yes | The global ID of the child epic. Internal ID can't be used because they can conflict with epics from other groups. | + +```bash +curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/epics/6 +``` + +Example response: + +```json +{ + "id": 6, + "iid": 38, + "group_id": 1, + "parent_id": 5 + "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", + "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", + "author": { + "id": 10, + "name": "Lu Mayer", + "username": "kam", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", + "web_url": "http://localhost:3001/kam" + }, + "start_date": null, + "start_date_is_fixed": false, + "start_date_fixed": null, + "start_date_from_milestones": null, + "end_date": "2018-07-31", + "due_date": "2018-07-31", + "due_date_is_fixed": false, + "due_date_fixed": null, + "due_date_from_milestones": "2018-07-31", + "created_at": "2018-07-17T13:36:22.770Z", + "updated_at": "2018-07-18T12:22:05.239Z", + "labels": [] +} +``` + +## Create and assign a child epic + +Creates a a new epic and associates it with provided parent epic. The response is LinkedEpic object. + +``` +POST /groups/:id/epics/:epic_iid/epics +``` + +| 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 | +| `epic_iid` | integer | yes | The internal ID of the (future parent) epic. | +| `title` | integer | yes | The global ID of the child epic. Internal ID can't be used because they can conflict with epics from other groups. | + +```bash +curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/epics?title=Newpic +``` + +Example response: + +```json +{ + "id": 24, + "iid": 2, + "title": "child epic", + "group_id": 49, + "parent_id": 23, + "has_children": false, + "reference": "&2", + "url": "http://localhost/groups/group16/-/epics/2", + "relation_url": "http://localhost/groups/group16/-/epics/1/links/24" +} +``` + +## Re-order a child epic + +``` +PUT /groups/:id/epics/:epic_iid/epics/:child_epic_id +``` + +| 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. | +| `epic_iid` | integer | yes | The internal ID of the epic. | +| `child_epic_id` | integer | yes | The global ID of the child epic. Internal ID can't be used because they can conflict with epics from other groups. | +| `move_before_id` | integer | no | The global ID of a sibling epic that should be placed before the child epic. | +| `move_after_id` | integer | no | The global ID of a sibling epic that should be placed after the child epic. | + +```bash +curl --header PUT "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/4/epics/5 +``` + +Example response: + +```json +[ + { + "id": 29, + "iid": 6, + "group_id": 1, + "parent_id": 5, + "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", + "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", + "author": { + "id": 10, + "name": "Lu Mayer", + "username": "kam", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", + "web_url": "http://localhost:3001/kam" + }, + "start_date": null, + "start_date_is_fixed": false, + "start_date_fixed": null, + "start_date_from_milestones": null, + "end_date": "2018-07-31", + "due_date": "2018-07-31", + "due_date_is_fixed": false, + "due_date_fixed": null, + "due_date_from_milestones": "2018-07-31", + "created_at": "2018-07-17T13:36:22.770Z", + "updated_at": "2018-07-18T12:22:05.239Z", + "labels": [] + } +] +``` + +## Unassign a child epic + +Unassigns a child epic from a parent epic. + +``` +DELETE /groups/:id/epics/:epic_iid/epics/:child_epic_id +``` + +| 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. | +| `epic_iid` | integer | yes | The internal ID of the epic. | +| `child_epic_id` | integer | yes | The global ID of the child epic. Internal ID can't be used because they can conflict with epics from other groups. | + +```bash +curl --header DELETE "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/4/epics/5 +``` + +Example response: + +```json +{ + "id": 5, + "iid": 38, + "group_id": 1, + "parent_id": null, + "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", + "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", + "author": { + "id": 10, + "name": "Lu Mayer", + "username": "kam", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", + "web_url": "http://localhost:3001/kam" + }, + "start_date": null, + "start_date_is_fixed": false, + "start_date_fixed": null, + "start_date_from_milestones": null, + "end_date": "2018-07-31", + "due_date": "2018-07-31", + "due_date_is_fixed": false, + "due_date_fixed": null, + "due_date_from_milestones": "2018-07-31", + "created_at": "2018-07-17T13:36:22.770Z", + "updated_at": "2018-07-18T12:22:05.239Z", + "labels": [] +} +``` diff --git a/doc/api/epics.md b/doc/api/epics.md new file mode 100644 index 00000000000..0541cfaa715 --- /dev/null +++ b/doc/api/epics.md @@ -0,0 +1,360 @@ +# Epics API **[ULTIMATE]** + +Every API call to epic must be authenticated. + +If a user is not a member of a group and the group is private, a `GET` request on that group will result to a `404` status code. + +If epics feature is not available a `403` status code will be returned. + +## Epic issues API + +The [epic issues API](epic_issues.md) allows you to interact with issues associated with an epic. + +# Milestone dates integration + +> [Introduced][ee-6448] in GitLab 11.3. + +Since start date and due date can be dynamically sourced from related issue milestones, when user has edit permission, additional fields will be shown. These include two boolean fields `start_date_is_fixed` and `due_date_is_fixed`, and four date fields `start_date_fixed`, `start_date_from_milestones`, `due_date_fixed` and `due_date_from_milestones`. + +`end_date` has been deprecated in favor of `due_date`. + +## Epics pagination + +By default, `GET` requests return 20 results at a time because the API results +are paginated. + +Read more on [pagination](README.md#pagination). + +## List epics for a group + +Gets all epics of the requested group and its subgroups. + +``` +GET /groups/:id/epics +GET /groups/:id/epics?author_id=5 +GET /groups/:id/epics?labels=bug,reproduced +GET /groups/:id/epics?state=opened +``` + +| 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 | +| `author_id` | integer | no | Return epics created by the given user `id` | +| `labels` | string | no | Return epics matching a comma separated list of labels names. Label names from the epic group or a parent group can be used | +| `order_by` | string | no | Return epics ordered by `created_at` or `updated_at` fields. Default is `created_at` | +| `sort` | string | no | Return epics sorted in `asc` or `desc` order. Default is `desc` | +| `search` | string | no | Search epics against their `title` and `description` | +| `state` | string | no | Search epics against their `state`, possible filters: `opened`, `closed` and `all`, default: `all` | +| `created_after` | datetime | no | Return epics created on or after the given time | +| `created_before` | datetime | no | Return epics created on or before the given time | +| `updated_after` | datetime | no | Return epics updated on or after the given time | +| `updated_before` | datetime | no | Return epics updated on or before the given time | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics +``` + +Example response: + +```json +[ + { + "id": 29, + "iid": 4, + "group_id": 7, + "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", + "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", + "state": "opened", + "author": { + "id": 10, + "name": "Lu Mayer", + "username": "kam", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", + "web_url": "http://localhost:3001/kam" + }, + "start_date": null, + "start_date_is_fixed": false, + "start_date_fixed": null, + "start_date_from_milestones": null, + "end_date": "2018-07-31", + "due_date": "2018-07-31", + "due_date_is_fixed": false, + "due_date_fixed": null, + "due_date_from_milestones": "2018-07-31", + "created_at": "2018-07-17T13:36:22.770Z", + "updated_at": "2018-07-18T12:22:05.239Z", + "labels": [], + "upvotes": 4, + "downvotes": 0 + } +] +``` + +## Single epic + +Gets a single epic + +``` +GET /groups/:id/epics/:epic_iid +``` + +| 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 | +| `epic_iid` | integer/string | yes | The internal ID of the epic. | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5 +``` + +Example response: + +```json +{ + "id": 30, + "iid": 5, + "group_id": 7, + "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", + "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", + "state": "opened", + "author":{ + "id": 7, + "name": "Pamella Huel", + "username": "arnita", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", + "web_url": "http://localhost:3001/arnita" + }, + "start_date": null, + "start_date_is_fixed": false, + "start_date_fixed": null, + "start_date_from_milestones": null, + "end_date": "2018-07-31", + "due_date": "2018-07-31", + "due_date_is_fixed": false, + "due_date_fixed": null, + "due_date_from_milestones": "2018-07-31", + "created_at": "2018-07-17T13:36:22.770Z", + "updated_at": "2018-07-18T12:22:05.239Z", + "labels": [], + "upvotes": 4, + "downvotes": 0 +} +``` + +## New epic + +Creates a new epic. + +NOTE: **Note:** +Starting with GitLab [11.3][ee-6448], `start_date` and `end_date` should no longer be assigned +directly, as they now represent composite values. You can configure it via the `*_is_fixed` and +`*_fixed` fields instead. + +``` +POST /groups/:id/epics +``` + +| 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 | +| `title` | string | yes | The title of the epic | +| `labels` | string | no | The comma separated list of labels | +| `description` | string | no | The description of the epic | +| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) | +| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) | +| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (since 11.3) | +| `due_date_fixed` | string | no | The fixed due date of an epic (since 11.3) | +| `parent_id` | integer/string | no | The id of a parent epic (since 11.11) | + +```bash +curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics?title=Epic&description=Epic%20description +``` + +Example response: + +```json +{ + "id": 33, + "iid": 6, + "group_id": 7, + "title": "Epic", + "description": "Epic description", + "state": "opened", + "author": { + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "state" : "active", + "web_url" : "https://gitlab.example.com/eileen.lowe", + "id" : 18, + "username" : "eileen.lowe" + }, + "start_date": null, + "start_date_is_fixed": false, + "start_date_fixed": null, + "start_date_from_milestones": null, + "end_date": "2018-07-31", + "due_date": "2018-07-31", + "due_date_is_fixed": false, + "due_date_fixed": null, + "due_date_from_milestones": "2018-07-31", + "created_at": "2018-07-17T13:36:22.770Z", + "updated_at": "2018-07-18T12:22:05.239Z", + "labels": [], + "upvotes": 4, + "downvotes": 0 +} +``` + +## Update epic + +Updates an epic. + +NOTE: **Note:** +Starting with GitLab [11.3][ee-6448], `start_date` and `end_date` should no longer be assigned +directly, as they now represent composite values. You can configure it via the `*_is_fixed` and +`*_fixed` fields instead. + +``` +PUT /groups/:id/epics/:epic_iid +``` + +| 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 | +| `epic_iid` | integer/string | yes | The internal ID of the epic | +| `title` | string | no | The title of an epic | +| `description` | string | no | The description of an epic | +| `labels` | string | no | The comma separated list of labels | +| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) | +| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) | +| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (since 11.3) | +| `due_date_fixed` | string | no | The fixed due date of an epic (since 11.3) | +| `state_event` | string | no | State event for an epic. Set `close` to close the epic and `reopen` to reopen it (since 11.4) | + +```bash +curl --header PUT "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5?title=New%20Title +``` + +Example response: + +```json +{ + "id": 33, + "iid": 6, + "group_id": 7, + "title": "New Title", + "description": "Epic description", + "state": "opened", + "author": { + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "state" : "active", + "web_url" : "https://gitlab.example.com/eileen.lowe", + "id" : 18, + "username" : "eileen.lowe" + }, + "start_date": null, + "start_date_is_fixed": false, + "start_date_fixed": null, + "start_date_from_milestones": null, + "end_date": "2018-07-31", + "due_date": "2018-07-31", + "due_date_is_fixed": false, + "due_date_fixed": null, + "due_date_from_milestones": "2018-07-31", + "created_at": "2018-07-17T13:36:22.770Z", + "updated_at": "2018-07-18T12:22:05.239Z", + "labels": [], + "upvotes": 4, + "downvotes": 0 +} +``` + +## Delete epic + +Deletes an epic + +``` +DELETE /groups/:id/epics/:epic_iid +``` + +| 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 | +| `epic_iid` | integer/string | yes | The internal ID of the epic. | + +```bash +curl --header DELETE "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5 +``` + +## Create a todo + +Manually creates a todo for the current user on an epic. If +there already exists a todo for the user on that epic, status code `304` is +returned. + +``` +POST /groups/:id/epics/:epic_iid/todo +``` + +| 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 | +| `epic_iid ` | integer | yes | The internal ID of a group's epic | + +```bash +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/todo +``` + +Example response: + +```json +{ + "id": 112, + "group": { + "id": 1, + "name": "Gitlab", + "path": "gitlab", + "kind": "group", + "full_path": "base/gitlab", + "parent_id": null + }, + "author": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/root" + }, + "action_name": "marked", + "target_type": "epic", + "target": { + "id": 30, + "iid": 5, + "group_id": 1, + "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", + "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", + "author":{ + "id": 7, + "name": "Pamella Huel", + "username": "arnita", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", + "web_url": "http://localhost:3001/arnita" + }, + "start_date": null, + "end_date": null, + "created_at": "2018-01-21T06:21:13.165Z", + "updated_at": "2018-01-22T12:41:41.166Z" + }, + "target_url": "https://gitlab.example.com/groups/epics/5", + "body": "Vel voluptas atque dicta mollitia adipisci qui at.", + "state": "pending", + "created_at": "2016-07-01T11:09:13.992Z" +} +``` + +[ee-6448]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6448 diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md new file mode 100644 index 00000000000..a1cb524499f --- /dev/null +++ b/doc/api/geo_nodes.md @@ -0,0 +1,408 @@ +# Geo Nodes API **[PREMIUM ONLY]** + +In order to interact with Geo node endpoints, you need to authenticate yourself +as an admin. + +## Retrieve configuration about all Geo nodes + +``` +GET /geo_nodes +``` + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes +``` + +Example response: + +```json +[ + { + "id": 1, + "name": "us-node", + "url": "https://primary.example.com/", + "internal_url": "https://internal.example.com/", + "primary": true, + "enabled": true, + "current": true, + "files_max_capacity": 10, + "repos_max_capacity": 25, + "verification_max_capacity": 100, + "clone_protocol": "http" + }, + { + "id": 2, + "name": "cn-node", + "url": "https://secondary.example.com/", + "internal_url": "https://secondary.example.com/", + "primary": false, + "enabled": true, + "current": false, + "files_max_capacity": 10, + "repos_max_capacity": 25, + "verification_max_capacity": 100, + "clone_protocol": "http" + } +] +``` + +## Retrieve configuration about a specific Geo node + +``` +GET /geo_nodes/:id +``` + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes/1 +``` + +Example response: + +```json +{ + "id": 1, + "name": "us-node", + "url": "https://primary.example.com/", + "internal_url": "https://primary.example.com/", + "primary": true, + "enabled": true, + "current": true, + "files_max_capacity": 10, + "repos_max_capacity": 25, + "verification_max_capacity": 100, + "clone_protocol": "http" +} +``` + +## Edit a Geo node + +Updates settings of an existing Geo node. + +_This can only be run against a primary Geo node._ + +``` +PUT /geo_nodes/:id +``` + +| Attribute | Type | Required | Description | +|----------------------|---------|-----------|---------------------------------------------------------------------------| +| `id` | integer | yes | The ID of the Geo node. | +| `enabled` | boolean | no | Flag indicating if the Geo node is enabled. | +| `name` | string | yes | The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`. | +| `url` | string | yes | The user-facing URL of the Geo node. | +| `internal_url` | string | no | The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set.| +| `files_max_capacity` | integer | no | Control the maximum concurrency of LFS/attachment backfill for this secondary node. | +| `repos_max_capacity` | integer | no | Control the maximum concurrency of repository backfill for this secondary node. | +| `verification_max_capacity` | integer | no | Control the maximum concurrency of verification for this node. | + +Example response: + +```json +{ + "id": 1, + "name": "cn-node", + "url": "https://secondary.example.com/", + "internal_url": "https://secondary.example.com/", + "primary": false, + "enabled": true, + "current": true, + "files_max_capacity": 10, + "repos_max_capacity": 25, + "verification_max_capacity": 100, + "clone_protocol": "http" +} +``` + +## Delete a Geo node + +Removes the Geo node. + +NOTE: **Note:** +Only a Geo primary node will accept this request. + +``` +DELETE /geo_nodes/:id +``` + +| Attribute | Type | Required | Description | +|-----------|---------|----------|-------------------------| +| `id` | integer | yes | The ID of the Geo node. | + +## Repair a Geo node + +To repair the OAuth authentication of a Geo node. + +_This can only be run against a primary Geo node._ + +``` +POST /geo_nodes/:id/repair +``` + +Example response: + +```json +{ + "id": 1, + "name": "us-node", + "url": "https://primary.example.com/", + "internal_url": "https://primary.example.com/", + "primary": true, + "enabled": true, + "current": true, + "files_max_capacity": 10, + "repos_max_capacity": 25, + "verification_max_capacity": 100, + "clone_protocol": "http" +} +``` + +## Retrieve status about all Geo nodes + +``` +GET /geo_nodes/status +``` + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes/status +``` + +Example response: + +```json +[ + { + "geo_node_id": 1, + "healthy": true, + "health": "Healthy", + "health_status": "Healthy", + "missing_oauth_application": false, + "attachments_count": 1, + "attachments_synced_count": nil, + "attachments_failed_count": nil, + "attachments_synced_missing_on_primary_count": 0, + "attachments_synced_in_percentage": "0.00%", + "db_replication_lag_seconds": nil, + "lfs_objects_count": 0, + "lfs_objects_synced_count": nil, + "lfs_objects_failed_count": nil, + "lfs_objects_synced_missing_on_primary_count": 0, + "lfs_objects_synced_in_percentage": "0.00%", + "job_artifacts_count": 2, + "job_artifacts_synced_count": nil, + "job_artifacts_failed_count": nil, + "job_artifacts_synced_missing_on_primary_count": 0, + "job_artifacts_synced_in_percentage": "0.00%", + "repositories_count": 41, + "projects_count": 41, + "repositories_failed_count": nil, + "repositories_synced_count": nil, + "repositories_synced_in_percentage": "0.00%", + "wikis_count": 41, + "wikis_failed_count": nil, + "wikis_synced_count": nil, + "wikis_synced_in_percentage": "0.00%", + "replication_slots_count": 1, + "replication_slots_used_count": 1, + "replication_slots_used_in_percentage": "100.00%", + "replication_slots_max_retained_wal_bytes": 0, + "repositories_checked_count": 20, + "repositories_checked_failed_count": 20, + "repositories_checked_in_percentage": "100.00%", + "repositories_checksummed_count": 20, + "repositories_checksum_failed_count": 5, + "repositories_checksummed_in_percentage": "48.78%", + "wikis_checksummed_count": 10, + "wikis_checksum_failed_count": 3, + "wikis_checksummed_in_percentage": "24.39%", + "repositories_verified_count": 20, + "repositories_verification_failed_count": 5, + "repositories_verified_in_percentage": "48.78%", + "repositories_checksum_mismatch_count": 3, + "wikis_verified_count": 10, + "wikis_verification_failed_count": 3, + "wikis_verified_in_percentage": "24.39%", + "wikis_checksum_mismatch_count": 1, + "repositories_retrying_verification_count": 1, + "wikis_retrying_verification_count": 3, + "repositories_checked_count": 7, + "repositories_checked_failed_count": 2, + "repositories_checked_in_percentage": "17.07%", + "last_event_id": 23, + "last_event_timestamp": 1509681166, + "cursor_last_event_id": nil, + "cursor_last_event_timestamp": 0, + "last_successful_status_check_timestamp": 1510125024, + "version": "10.3.0", + "revision": "33d33a096a", + }, + { + "geo_node_id": 2, + "healthy": true, + "health": "Healthy", + "health_status": "Healthy", + "missing_oauth_application": false, + "attachments_count": 1, + "attachments_synced_count": 1, + "attachments_failed_count": 0, + "attachments_synced_missing_on_primary_count": 0, + "attachments_synced_in_percentage": "100.00%", + "db_replication_lag_seconds": 0, + "lfs_objects_count": 0, + "lfs_objects_synced_count": 0, + "lfs_objects_failed_count": 0, + "lfs_objects_synced_missing_on_primary_count": 0, + "lfs_objects_synced_in_percentage": "0.00%", + "job_artifacts_count": 2, + "job_artifacts_synced_count": 1, + "job_artifacts_failed_count": 1, + "job_artifacts_synced_missing_on_primary_count": 0, + "job_artifacts_synced_in_percentage": "50.00%", + "repositories_count": 41, + "projects_count": 41, + "repositories_failed_count": 1, + "repositories_synced_count": 40, + "repositories_synced_in_percentage": "97.56%", + "wikis_count": 41, + "wikis_failed_count": 0, + "wikis_synced_count": 41, + "wikis_synced_in_percentage": "100.00%", + "replication_slots_count": nil, + "replication_slots_used_count": nil, + "replication_slots_used_in_percentage": "0.00%", + "replication_slots_max_retained_wal_bytes": nil, + "repositories_checksummed_count": 20, + "repositories_checksum_failed_count": 5, + "repositories_checksummed_in_percentage": "48.78%", + "wikis_checksummed_count": 10, + "wikis_checksum_failed_count": 3, + "wikis_checksummed_in_percentage": "24.39%", + "repositories_verified_count": 20, + "repositories_verification_failed_count": 5, + "repositories_verified_in_percentage": "48.78%", + "repositories_checksum_mismatch_count": 3, + "wikis_verified_count": 10, + "wikis_verification_failed_count": 3, + "wikis_verified_in_percentage": "24.39%", + "wikis_checksum_mismatch_count": 1, + "repositories_retrying_verification_count": 4, + "wikis_retrying_verification_count": 2, + "repositories_checked_count": 5, + "repositories_checked_failed_count": 1, + "repositories_checked_in_percentage": "12.20%", + "last_event_id": 23, + "last_event_timestamp": 1509681166, + "cursor_last_event_id": 23, + "cursor_last_event_timestamp": 1509681166, + "last_successful_status_check_timestamp": 1510125024, + "version": "10.3.0", + "revision": "33d33a096a" + } +] +``` + +Note: fields `wikis_count` and `repositories_count` are deprecated and will be deleted soon. Please use `projects_count` instead. + +## Retrieve status about a specific Geo node + +``` +GET /geo_nodes/:id/status +``` + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes/2/status +``` + +Example response: + +```json +{ + "geo_node_id": 2, + "healthy": true, + "health": "Healthy", + "health_status": "Healthy", + "missing_oauth_application": false, + "attachments_count": 1, + "attachments_synced_count": 1, + "attachments_failed_count": 0, + "attachments_synced_missing_on_primary_count": 0, + "attachments_synced_in_percentage": "100.00%", + "db_replication_lag_seconds": 0, + "lfs_objects_count": 0, + "lfs_objects_synced_count": 0, + "lfs_objects_failed_count": 0, + "lfs_objects_synced_missing_on_primary_count": 0, + "lfs_objects_synced_in_percentage": "0.00%", + "job_artifacts_count": 2, + "job_artifacts_synced_count": 1, + "job_artifacts_failed_count": 1, + "job_artifacts_synced_missing_on_primary_count": 0, + "job_artifacts_synced_in_percentage": "50.00%", + "repositories_count": 41, + "projects_count": 41, + "repositories_failed_count": 1, + "repositories_synced_count": 40, + "repositories_synced_in_percentage": "97.56%", + "wikis_count": 41, + "wikis_failed_count": 0, + "wikis_synced_count": 41, + "wikis_synced_in_percentage": "100.00%", + "replication_slots_count": nil, + "replication_slots_used_count": nil, + "replication_slots_used_in_percentage": "0.00%", + "replication_slots_max_retained_wal_bytes": nil, + "last_event_id": 23, + "last_event_timestamp": 1509681166, + "cursor_last_event_id": 23, + "cursor_last_event_timestamp": 1509681166, + "last_successful_status_check_timestamp": 1510125268, + "version": "10.3.0", + "revision": "33d33a096a" +} +``` + +Note: The `health_status` parameter can only be in an "Healthy" or "Unhealthy" state, while the `health` parameter can be empty, "Healthy", or contain the actual error message. + +Note: Fields `wikis_count` and `repositories_count` are deprecated and will be deleted soon. Please use `projects_count` instead. + +## Retrieve project sync or verification failures that occurred on the current node + +This only works on a secondary node. + +``` +GET /geo_nodes/current/failures +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `type` | string | no | Type of failed objects (`repository`/`wiki`) | +| `failure_type` | string | no | Type of failures (`sync`/`checksum_mismatch`/`verification`) | + +This endpoint uses [Pagination](README.md#pagination). + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes/current/failures +``` + +Example response: + +```json +[ + { + "project_id": 3, + "last_repository_synced_at": "2017-10-31 14:25:55 UTC", + "last_repository_successful_sync_at": "2017-10-31 14:26:04 UTC", + "last_wiki_synced_at": "2017-10-31 14:26:04 UTC", + "last_wiki_successful_sync_at": "2017-10-31 14:26:11 UTC", + "repository_retry_count": null, + "wiki_retry_count": 1, + "last_repository_sync_failure": null, + "last_wiki_sync_failure": "Error syncing Wiki repository", + "last_repository_verification_failure": "", + "last_wiki_verification_failure": "", + "repository_verification_checksum_sha": "da39a3ee5e6b4b0d32e5bfef9a601890afd80709", + "wiki_verification_checksum_sha": "da39a3ee5e6b4b0d3255bfef9ef0189aafd80709", + "repository_checksum_mismatch": false, + "wiki_checksum_mismatch": false + } +] +``` diff --git a/doc/api/issue_links.md b/doc/api/issue_links.md new file mode 100644 index 00000000000..1c7db6a8e4c --- /dev/null +++ b/doc/api/issue_links.md @@ -0,0 +1,215 @@ +# Issue links API **[STARTER]** + +## List issue relations + +Get a list of related issues of a given issue, sorted by the relationship creation datetime (ascending). +Issues will be filtered according to the user authorizations. + +``` +GET /projects/:id/issues/:issue_iid/links +``` + +Parameters: + +| 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 | +| `issue_iid` | integer | yes | The internal ID of a project's issue | + +```json +[ + { + "id" : 84, + "iid" : 14, + "issue_link_id": 1 + "project_id" : 4, + "created_at" : "2016-01-07T12:44:33.959Z", + "title" : "Issues with auth", + "state" : "opened", + "assignees" : [], + "assignee" : null, + "labels" : [ + "bug" + ], + "author" : { + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "state" : "active", + "web_url" : "https://gitlab.example.com/eileen.lowe", + "id" : 18, + "username" : "eileen.lowe" + }, + "description" : null, + "updated_at" : "2016-01-07T12:44:33.959Z", + "milestone" : null, + "subscribed" : true, + "user_notes_count": 0, + "due_date": null, + "web_url": "http://example.com/example/example/issues/14", + "confidential": false, + "weight": null, + } +] +``` + +## Create an issue link + +Creates a two-way relation between two issues. User must be allowed to update both issues in order to succeed. + +``` +POST /projects/:id/issues/:issue_iid/links +``` + +| 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 | +| `issue_iid` | integer | yes | The internal ID of a project's issue | +| `target_project_id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) of a target project | +| `target_issue_iid` | integer/string | yes | The internal ID of a target project's issue | + + +```json +{ + "source_issue" : { + "id" : 83, + "iid" : 11, + "project_id" : 4, + "created_at" : "2016-01-07T12:44:33.959Z", + "title" : "Issues with auth", + "state" : "opened", + "assignees" : [], + "assignee" : null, + "labels" : [ + "bug" + ], + "author" : { + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "state" : "active", + "web_url" : "https://gitlab.example.com/eileen.lowe", + "id" : 18, + "username" : "eileen.lowe" + }, + "description" : null, + "updated_at" : "2016-01-07T12:44:33.959Z", + "milestone" : null, + "subscribed" : true, + "user_notes_count": 0, + "due_date": null, + "web_url": "http://example.com/example/example/issues/11", + "confidential": false, + "weight": null, + }, + "target_issue" : { + "id" : 84, + "iid" : 14, + "project_id" : 4, + "created_at" : "2016-01-07T12:44:33.959Z", + "title" : "Issues with auth", + "state" : "opened", + "assignees" : [], + "assignee" : null, + "labels" : [ + "bug" + ], + "author" : { + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "state" : "active", + "web_url" : "https://gitlab.example.com/eileen.lowe", + "id" : 18, + "username" : "eileen.lowe" + }, + "description" : null, + "updated_at" : "2016-01-07T12:44:33.959Z", + "milestone" : null, + "subscribed" : true, + "user_notes_count": 0, + "due_date": null, + "web_url": "http://example.com/example/example/issues/14", + "confidential": false, + "weight": null, + } +} +``` + +## Delete an issue link + +Deletes an issue link, thus removes the two-way relationship. + +``` +DELETE /projects/:id/issues/:issue_iid/links/:issue_link_id +``` + + +| 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 | +| `issue_iid` | integer | yes | The internal ID of a project's issue | +| `issue_link_id` | integer/string | yes | The ID of an issue relationship | + + +```json +{ + "source_issue" : { + "id" : 83, + "iid" : 11, + "project_id" : 4, + "created_at" : "2016-01-07T12:44:33.959Z", + "title" : "Issues with auth", + "state" : "opened", + "assignees" : [], + "assignee" : null, + "labels" : [ + "bug" + ], + "author" : { + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "state" : "active", + "web_url" : "https://gitlab.example.com/eileen.lowe", + "id" : 18, + "username" : "eileen.lowe" + }, + "description" : null, + "updated_at" : "2016-01-07T12:44:33.959Z", + "milestone" : null, + "subscribed" : true, + "user_notes_count": 0, + "due_date": null, + "web_url": "http://example.com/example/example/issues/11", + "confidential": false, + "weight": null, + }, + "target_issue" : { + "id" : 84, + "iid" : 14, + "project_id" : 4, + "created_at" : "2016-01-07T12:44:33.959Z", + "title" : "Issues with auth", + "state" : "opened", + "assignees" : [], + "assignee" : null, + "labels" : [ + "bug" + ], + "author" : { + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "state" : "active", + "web_url" : "https://gitlab.example.com/eileen.lowe", + "id" : 18, + "username" : "eileen.lowe" + }, + "description" : null, + "updated_at" : "2016-01-07T12:44:33.959Z", + "milestone" : null, + "subscribed" : true, + "user_notes_count": 0, + "due_date": null, + "web_url": "http://example.com/example/example/issues/14", + "confidential": false, + "weight": null, + } +} +``` diff --git a/doc/api/license.md b/doc/api/license.md new file mode 100644 index 00000000000..2a8de64bdbf --- /dev/null +++ b/doc/api/license.md @@ -0,0 +1,176 @@ +# License **[CORE ONLY]** + +In order to interact with license endpoints, you need to authenticate yourself +as an admin. + +## Retrieve information about the current license + +``` +GET /license +``` + +```json +{ + "id": 2, + "plan": "gold", + "created_at": "2018-02-27T23:21:58.674Z", + "starts_at": "2018-01-27", + "expires_at": "2022-01-27", + "historical_max": 300, + "expired": false, + "overage": 200, + "user_limit": 100, + "active_users": 300, + "licensee": { + "Name": "John Doe1" + }, + "add_ons": { + "GitLab_FileLocks": 1, + "GitLab_Auditor_User": 1 + } +} +``` + +## Retrieve information about all licenses + +``` +GET /licenses +``` + +```json +[ + { + "id": 1, + "plan": "silver", + "created_at": "2018-02-27T23:21:58.674Z", + "starts_at": "2018-01-27", + "expires_at": "2022-01-27", + "historical_max": 300, + "expired": false, + "overage": 200, + "user_limit": 100, + "licensee": { + "Name": "John Doe1" + }, + "add_ons": { + "GitLab_FileLocks": 1, + "GitLab_Auditor_User": 1 + } + }, + { + "id": 2, + "plan": "gold", + "created_at": "2018-02-27T23:21:58.674Z", + "starts_at": "2018-01-27", + "expires_at": "2022-01-27", + "historical_max": 300, + "expired": false, + "overage": 200, + "user_limit": 100, + "licensee": { + "Name": "Doe John" + }, + "add_ons": { + "GitLab_FileLocks": 1, + } + } +] +``` + +Overage is the difference between the number of active users and the licensed number of users. +This is calculated differently depending on whether the license has expired or not. + +- If the license has expired, it uses the historical maximum active user count (`historical_max`). +- If the license has not expired, it uses the current active users count. + +Returns: + +- `200 OK` with response containing the licenses in JSON format. This will be an empty JSON array if there are no licenses. +- `403 Forbidden` if the current user in not permitted to read the licenses. + +## Add a new license + +``` +POST /license +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `license` | string | yes | The license string | + +```bash +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license?license=eyJkYXRhIjoiMHM5Q...S01Udz09XG4ifQ==" +``` + +Example response: + +```json +{ + "id": 1, + "plan": "gold", + "created_at": "2018-02-27T23:21:58.674Z", + "starts_at": "2018-01-27", + "expires_at": "2022-01-27", + "historical_max": 300, + "expired": false, + "overage": 200, + "user_limit": 100, + "active_users": 300, + "licensee": { + "Name": "John Doe1" + }, + "add_ons": { + "GitLab_FileLocks": 1, + "GitLab_Auditor_User": 1 + } +} +``` + +Returns: + +- `201 Created` if the license is successfully added. +- `400 Bad Request` if the license couldn't be added, with an error message explaining the reason. + + +## Delete a license + +``` +DELETE /license/:id +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | ID of the GitLab license. | + +```bash +curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license/:id" +``` + +Example response: + +```json +{ + "id": 2, + "plan": "gold", + "created_at": "2018-02-27T23:21:58.674Z", + "starts_at": "2018-01-27", + "expires_at": "2022-01-27", + "historical_max": 300, + "expired": false, + "overage": 200, + "user_limit": 100, + "licensee": { + "Name": "John Doe" + }, + "add_ons": { + "GitLab_FileLocks": 1, + "GitLab_Auditor_User": 1 + } +} +``` + +Returns: + +- `204 No Content` if the license is successfully deleted. +- `403 Forbidden` if the current user in not permitted to delete the license. +- `404 Not Found` if the license to delete could not be found. diff --git a/doc/api/license_templates.md b/doc/api/license_templates.md new file mode 100644 index 00000000000..1b68af9ce31 --- /dev/null +++ b/doc/api/license_templates.md @@ -0,0 +1,5 @@ +--- +redirect_to: 'templates/licenses.md' +--- + +This document was moved to [another location](templates/licenses.md). diff --git a/doc/api/managed_licenses.md b/doc/api/managed_licenses.md new file mode 100644 index 00000000000..47b193111b6 --- /dev/null +++ b/doc/api/managed_licenses.md @@ -0,0 +1,136 @@ +# Managed Licenses API **[ULTIMATE]** + +## List managed licenses + +Get all managed licenses for a given project. + +``` +GET /projects/:id/managed_licenses +``` + +| Attribute | Type | Required | Description | +| --------- | ------- | -------- | --------------------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/managed_licenses +``` + +Example response: + +```json +[ + { + "id": 1, + "name": "MIT", + "approval_status": "approved" + }, + { + "id": 3, + "name": "ISC", + "approval_status": "blacklisted" + } +] +``` + +## Show an existing managed license + +Shows an existing managed license. + +``` +GET /projects/:id/managed_licenses/:managed_license_id +``` + +| 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 | +| `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" +``` + +Example response: + +```json +{ + "id": 1, + "name": "MIT", + "approval_status": "blacklisted" +} +``` + +## Create a new managed license + +Creates a new managed license for the given project with the given name and approval status. + +``` +POST /projects/:id/managed_licenses +``` + +| 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 | +| `name` | string | yes | The name of the managed license | +| `approval_status` | string | yes | The approval status. "approved" or "blacklisted" | + +```bash +curl --data "name=MIT&approval_status=blacklisted" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses" +``` + +Example response: + +```json +{ + "id": 1, + "name": "MIT", + "approval_status": "approved" +} +``` + +## Delete a managed license + +Deletes a managed license with a given id. + +``` +DELETE /projects/:id/managed_licenses/:managed_license_id +``` + +| 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 | +| `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project | + +```bash +curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/4" +``` + +When successful, it replies with an HTTP 204 response. + +## Edit an existing managed license + +Updates an existing managed license with a new approval status. + +``` +PATCH /projects/:id/managed_licenses/:managed_license_id +``` + +| 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 | +| `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project | +| `approval_status` | string | yes | The approval status. "approved" or "blacklisted" | + +```bash +curl --request PATCH --data "approval_status=blacklisted" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" +``` + +Example response: + +```json +{ + "id": 1, + "name": "MIT", + "approval_status": "blacklisted" +} +``` diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md new file mode 100644 index 00000000000..ddac81328b9 --- /dev/null +++ b/doc/api/merge_request_approvals.md @@ -0,0 +1,425 @@ +# Merge request approvals API **[STARTER]** + +Configuration for approvals on all Merge Requests (MR) in the project. Must be authenticated for all endpoints. + +## Project-level MR approvals + +### Get Configuration + +>**Note:** This API endpoint is only available on 10.6 Starter and above. + +You can request information about a project's approval configuration using the +following endpoint: + +``` +GET /projects/:id/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| --------- | ------- | -------- | ------------------- | +| `id` | integer | yes | The ID of a project | + +```json +{ + "approvers": [ + { + "user": { + "id": 5, + "name": "John Doe6", + "username": "user5", + "state":"active","avatar_url":"https://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80\u0026d=identicon","web_url":"http://localhost/user5" + } + } + ], + "approver_groups": [ + { + "group": { + "id": 1, + "name": "group1", + "path": "group1", + "description": "", + "visibility": "public", + "lfs_enabled": false, + "avatar_url": null, + "web_url": "http://localhost/groups/group1", + "request_access_enabled": false, + "full_name": "group1", + "full_path": "group1", + "parent_id": null, + "ldap_cn": null, + "ldap_access": null + } + } + ], + "approvals_before_merge": 2, + "reset_approvals_on_push": true, + "disable_overriding_approvers_per_merge_request": false +} +``` + +### Change configuration + +>**Note:** This API endpoint is only available on 10.6 Starter and above. + +If you are allowed to, you can change approval configuration using the following +endpoint: + +``` +POST /projects/:id/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +| ------------------------------------------------ | ------- | -------- | ---------------------------------------------------------- | +| `id` | integer | yes | The ID of a project | +| `approvals_before_merge` | integer | no | How many approvals are required before an MR can be merged | +| `reset_approvals_on_push` | boolean | no | Reset approvals on a new push | +| `disable_overriding_approvers_per_merge_request` | boolean | no | Allow/Disallow overriding approvers per MR | +| `merge_requests_author_approval` | boolean | no | Allow/Disallow authors be able to self approve merge requests | + +```json +{ + "approvers": [ + { + "user": { + "id": 5, + "name": "John Doe6", + "username": "user5", + "state":"active","avatar_url":"https://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80\u0026d=identicon","web_url":"http://localhost/user5" + } + } + ], + "approver_groups": [ + { + "group": { + "id": 1, + "name": "group1", + "path": "group1", + "description": "", + "visibility": "public", + "lfs_enabled": false, + "avatar_url": null, + "web_url": "http://localhost/groups/group1", + "request_access_enabled": false, + "full_name": "group1", + "full_path": "group1", + "parent_id": null, + "ldap_cn": null, + "ldap_access": null + } + } + ], + "approvals_before_merge": 2, + "reset_approvals_on_push": true, + "disable_overriding_approvers_per_merge_request": false, + "merge_requests_author_approval": false +} +``` + +### Change allowed approvers + +>**Note:** This API endpoint is only available on 10.6 Starter and above. + +If you are allowed to, you can change approvers and approver groups using +the following endpoint: + +``` +PUT /projects/:id/approvers +``` + +**Important:** Approvers and groups not in the request will be **removed** + +**Parameters:** + +| Attribute | Type | Required | Description | +| -------------------- | ------- | -------- | --------------------------------------------------- | +| `id` | integer | yes | The ID of a project | +| `approver_ids` | Array | yes | An array of User IDs that can approve MRs | +| `approver_group_ids` | Array | yes | An array of Group IDs whose members can approve MRs | + +```json +{ + "approvers": [ + { + "user": { + "id": 5, + "name": "John Doe6", + "username": "user5", + "state":"active","avatar_url":"https://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80\u0026d=identicon","web_url":"http://localhost/user5" + } + } + ], + "approver_groups": [ + { + "group": { + "id": 1, + "name": "group1", + "path": "group1", + "description": "", + "visibility": "public", + "lfs_enabled": false, + "avatar_url": null, + "web_url": "http://localhost/groups/group1", + "request_access_enabled": false, + "full_name": "group1", + "full_path": "group1", + "parent_id": null, + "ldap_cn": null, + "ldap_access": null + } + } + ], + "approvals_before_merge": 2, + "reset_approvals_on_push": true, + "disable_overriding_approvers_per_merge_request": false +} +``` + + +## Merge Request-level MR approvals + +Configuration for approvals on a specific Merge Request. Must be authenticated for all endpoints. + +### Get Configuration + +>**Note:** This API endpoint is only available on 8.9 Starter and above. + +You can request information about a merge request's approval status using the +following endpoint: + +``` +GET /projects/:id/merge_requests/:merge_request_iid/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +|---------------------|---------|----------|---------------------| +| `id` | integer | yes | The ID of a project | +| `merge_request_iid` | integer | yes | The IID 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": "cannot_be_merged", + "approvals_required": 2, + "approvals_left": 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" + } + } + ], + "approvers": [], + "approver_groups": [] +} +``` + +### Change approval configuration + +>**Note:** This API endpoint is only available on 10.6 Starter and above. + +If you are allowed to, you can change `approvals_required` using the following +endpoint: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/approvals +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +|----------------------|---------|----------|--------------------------------------------| +| `id` | integer | yes | The ID of a project | +| `merge_request_iid` | integer | yes | The IID of MR | +| `approvals_required` | integer | yes | Approvals required before MR can be merged | + + +```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": "cannot_be_merged", + "approvals_required": 2, + "approvals_left": 2, + "approved_by": [], + "approvers": [], + "approver_groups": [] +} +``` + +### Change allowed approvers for Merge Request + +>**Note:** This API endpoint is only available on 10.6 Starter and above. + +If you are allowed to, you can change approvers and approver groups using +the following endpoint: + +``` +PUT /projects/:id/merge_requests/:merge_request_iid/approvers +``` + +**Important:** Approvers and groups not in the request will be **removed** + +**Parameters:** + +| Attribute | Type | Required | Description | +|----------------------|---------|----------|-----------------------------------------------------------| +| `id` | integer | yes | The ID of a project | +| `merge_request_iid` | integer | yes | The IID of MR | +| `approver_ids` | Array | yes | An array of User IDs that can approve the MR | +| `approver_group_ids` | Array | yes | An array of Group IDs whose members can approve the 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": "cannot_be_merged", + "approvals_required": 2, + "approvals_left": 2, + "approved_by": [], + "approvers": [ + { + "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" + } + } + ], + "approver_groups": [ + { + "group": { + "id": 5, + "name": "group1", + "path": "group1", + "description": "", + "visibility": "public", + "lfs_enabled": false, + "avatar_url": null, + "web_url": "http://localhost/groups/group1", + "request_access_enabled": false, + "full_name": "group1", + "full_path": "group1", + "parent_id": null, + "ldap_cn": null, + "ldap_access": null + } + } + ] +} +``` + +## Approve Merge Request + +>**Note:** This API endpoint is only available on 8.9 Starter and above. + +If you are allowed to, you can approve a merge request using the following +endpoint: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/approve +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +|---------------------|---------|----------|-------------------------| +| `id` | integer | yes | The ID of a project | +| `merge_request_iid` | integer | yes | The IID of MR | +| `sha` | string | no | The HEAD of the MR | +| `approval_password` **[STARTER]** | string | no | Current user's password. Required if [**Require user password to approve**](../user/project/merge_requests/merge_request_approvals.md#require-authentication-when-approving-a-merge-request-starter) is enabled in the project settings. | + +The `sha` parameter works in the same way as +when [accepting a merge request](merge_requests.md#accept-mr): if it is passed, then it must +match the current HEAD of the merge request for the approval to be added. If it +does not match, the response code will be `409`. + +```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_left": 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" + } + } + ], + "approvers": [], + "approver_groups": [] +} +``` + +## Unapprove Merge Request + +>**Note:** This API endpoint is only available on 9.0 Starter and above. + +If you did approve a merge request, you can unapprove it using the following +endpoint: + +``` +POST /projects/:id/merge_requests/:merge_request_iid/unapprove +``` + +**Parameters:** + +| Attribute | Type | Required | Description | +|---------------------|---------|----------|---------------------| +| `id` | integer | yes | The ID of a project | +| `merge_request_iid` | integer | yes | The IID of MR | diff --git a/doc/api/packages.md b/doc/api/packages.md new file mode 100644 index 00000000000..618e5c3056a --- /dev/null +++ b/doc/api/packages.md @@ -0,0 +1,152 @@ +# Packages API **[PREMIUM]** + +This is the API docs of [GitLab Packages](../administration/packages.md). + +## List project packages + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9259) in GitLab 11.8. + +Get a list of project packages. Both Maven and NPM packages are included in results. +When accessed without authentication, only packages of public projects are returned. + +``` +GET /projects/:id/packages +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/packages +``` + +Example response: + +```json +[ + { + "id": 1, + "name": "com/mycompany/my-app", + "version": "1.0-SNAPSHOT", + "package_type": "maven" + }, + { + "id": 2, + "name": "@foo/bar", + "version": "1.0.3", + "package_type": "npm" + } +] +``` + +By default, the `GET` request will return 20 results, since the API is [paginated](README.md#pagination). + +## Get a project package + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9667) in GitLab 11.9. + +Get a single project package. + +``` +GET /projects/:id/packages/:package_id +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | +| `package_id` | integer | yes | ID of a package. | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/packages/:package_id +``` + +Example response: + +```json +{ + "id": 1, + "name": "com/mycompany/my-app", + "version": "1.0-SNAPSHOT", + "package_type": "maven" +} +``` + +## List package files + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9305) in GitLab 11.8. + +Get a list of package files of a single package. + +``` +GET /projects/:id/packages/:package_id/package_files +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | +| `package_id` | integer | yes | ID of a package. | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/packages/4/package_files +``` + +Example response: + +```json +[ + { + "id": 25, + "package_id": 4, + "created_at": "2018-11-07T15:25:52.199Z", + "file_name": "my-app-1.5-20181107.152550-1.jar", + "size": 2421, + "file_md5": "58e6a45a629910c6ff99145a688971ac", + "file_sha1": "ebd193463d3915d7e22219f52740056dfd26cbfe" + }, + { + "id": 26, + "package_id": 4, + "created_at": "2018-11-07T15:25:56.776Z", + "file_name": "my-app-1.5-20181107.152550-1.pom", + "size": 1122, + "file_md5": "d90f11d851e17c5513586b4a7e98f1b2", + "file_sha1": "9608d068fe88aff85781811a42f32d97feb440b5" + }, + { + "id": 27, + "package_id": 4, + "created_at": "2018-11-07T15:26:00.556Z", + "file_name": "maven-metadata.xml", + "size": 767, + "file_md5": "6dfd0cce1203145a927fef5e3a1c650c", + "file_sha1": "d25932de56052d320a8ac156f745ece73f6a8cd2" + } +] +``` + +By default, the `GET` request will return 20 results, since the API is [paginated](README.md#pagination). + +## Delete a project package + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9623) in GitLab 11.9. + +Deletes a project package. + +``` +DELETE /projects/:id/packages/:package_id +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | +| `package_id` | integer | yes | ID of a package. | + +```bash +curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/packages/:package_id +``` + +Can return the following status codes: + +- `204 No Content`, if the package was deleted successfully. +- `404 Not Found`, if the package was not found. diff --git a/doc/api/scim.md b/doc/api/scim.md new file mode 100644 index 00000000000..4595c6f2ed3 --- /dev/null +++ b/doc/api/scim.md @@ -0,0 +1,235 @@ +# SCIM API + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9388) in [GitLab Silver](https://about.gitlab.com/pricing/) 11.10. + +The SCIM API implements the [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644). + +NOTE: **Note:** +[Group SSO](../user/group/saml_sso/index.md) and the feature +flag `:group_scim` must be enabled for the group. For more information, see [SCIM setup documentation](../user/group/saml_sso/scim_setup.md#requirements). + +## Get a list of SAML users + +NOTE: **Note:** +This endpoint is used as part of the SCIM syncing mechanism and it only returns +a single user based on a unique ID which should match the `extern_uid` of the user. + +```text +GET /api/scim/v2/groups/:group_path/Users +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| +| `filter` | string | yes | A [filter](#available-filters) expression. | +| `group_path` | string | yes | Full path to the group. | + +Example request: + +```sh +curl 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20"0b1d561c-21ff-4092-beab-8154b17f82f2"' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json" +``` + +Example response: + +```json +{ + "schemas": [ + "urn:ietf:params:scim:api:messages:2.0:ListResponse" + ], + "totalResults": 1, + "itemsPerPage": 20, + "startIndex": 1, + "Resources": [ + { + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:User" + ], + "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", + "active": true, + "name.formatted": "Test User", + "userName": "username", + "meta": { "resourceType":"User" }, + "emails": [ + { + "type": "work", + "value": "name@example.com", + "primary": true + } + ] + } + ] +} +``` + +## Get a single SAML user + +```text +GET /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| +| `id` | string | yes | External UID of the user. | +| `group_path` | string | yes | Full path to the group. | + +Example request: + +```sh +curl 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json" +``` + +Example response: + +```json +{ + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:User" + ], + "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", + "active": true, + "name.formatted": "Test User", + "userName": "username", + "meta": { "resourceType":"User" }, + "emails": [ + { + "type": "work", + "value": "name@example.com", + "primary": true + } + ] +} +``` + +## Create a SAML user + +```text +POST /api/scim/v2/groups/:group_path/Users/ +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:---------------|:----------|:----|:--------------------------| +| `externalId` | string | yes | External UID of the user. | +| `userName` | string | yes | Username of the user. | +| `emails` | JSON string | yes | Work email. | +| `name` | JSON string | yes | Name of the user. | +| `meta` | string | no | Resource type (`User'). | + +Example request: + +```sh +curl --verbose --request POST 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users' --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json" +``` + +Example response: + +```json +{ + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:User" + ], + "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", + "active": true, + "name.formatted": "Test User", + "userName": "username", + "meta": { "resourceType":"User" }, + "emails": [ + { + "type": "work", + "value": "name@example.com", + "primary": true + } + ] +} +``` + +Returns a `201` status code if successful. + +## Update a single SAML user + +Fields that can be updated are: + +| SCIM/IdP field | GitLab field | +|:----------|:--------| +| id/externalId | extern_uid | +| name.formatted | name | +| emails\[type eq "work"\].value | email | +| active | Identity removal if `active = false` | +| userName | username | + +```text +PATCH /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| +| `id` | string | yes | External UID of the user. | +| `group_path` | string | yes | Full path to the group. | +| `Operations` | JSON string | yes | An [operations](#available-operations) expression. | + +Example request: + +```sh +curl --verbose --request PATCH 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2' --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json" +``` + +Returns an empty response with a `204` status code if successful. + +## Remove a single SAML user + +Removes the user's SSO identity and group membership. + +```text +DELETE /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| +| `id` | string | yes | External UID of the user. | +| `group_path` | string | yes | Full path to the group. | + +Example request: + +```sh +curl --verbose --request DELETE 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json" +``` + +Returns an empty response with a `204` status code if successful. + +## Available filters + +They match an expression as specified in [the RFC7644 filtering section](https://tools.ietf.org/html/rfc7644#section-3.4.2.2). + +| Filter | Description | +| ----- | ----------- | +| `eq` | The attribute matches exactly the specified value. | + +Example: + +``` +id eq a-b-c-d +``` + +## Available operations + +They perform an operation as specified in [the RFC7644 update section](https://tools.ietf.org/html/rfc7644#section-3.5.2). + +| Operator | Description | +| ----- | ----------- | +| `Replace` | The attribute's value is updated. | +| `Add` | The attribute has a new value. | + +Example: + +```json +{ "op": "Add", "path": "name.formatted", "value": "New Name" } +``` diff --git a/doc/api/vulnerabilities.md b/doc/api/vulnerabilities.md new file mode 100644 index 00000000000..87f77613ad3 --- /dev/null +++ b/doc/api/vulnerabilities.md @@ -0,0 +1,113 @@ +# Vulnerabilities API + +Every API call to vulnerabilities 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 in a `404` status code. + +CAUTION: **Caution:** +This API is in an alpha stage and considered unstable. +The response payload may be subject to change or breakage +across GitLab releases. + +## Vulnerabilities pagination + +By default, `GET` requests return 20 results at a time because the API results +are paginated. + +Read more on [pagination](README.md#pagination). + +## List project vulnerabilities + +List all of a project's vulnerabilities. + +``` +GET /projects/:id/vulnerabilities +GET /projects/:id/vulnerabilities?report_type=sast +GET /projects/:id/vulnerabilities?report_type=container_scanning +GET /projects/:id/vulnerabilities?report_type=sast,dast +GET /projects/:id/vulnerabilities?scope=all +GET /projects/:id/vulnerabilities?scope=dismissed +GET /projects/:id/vulnerabilities?severity=high +GET /projects/:id/vulnerabilities?confidence=unknown,experimental +``` + +| 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. | +| `report_type` | Array[string] | no | Returns vulnerabilities belonging to specified report type. Valid values: `sast`, `dast`, `dependency_scanning`, or `container_scanning`. | +| `scope` | string | no | Returns vulnerabilities for the given scope: `all` or `dismissed`. Defaults to `dismissed` | +| `severity` | Array[string] | no | Returns vulnerabilities belonging to specified severity level: `undefined`, `info`, `unknown`, `low`, `medium`, `high`, or `critical`. Defaults to all' | +| `confidence` | Array[string] | no | Returns vulnerabilities belonging to specified confidence level: `undefined`, `ignore`, `unknown`, `experimental`, `low`, `medium`, `high`, or `confirmed`. Defaults to all | + +```bash +curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/vulnerabilities +``` + +Example response: + +```json +[ + { + "id": null, + "report_type": "dependency_scanning", + "name": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js", + "severity": "unknown", + "confidence": "undefined", + "scanner": { + "external_id": "gemnasium", + "name": "Gemnasium" + }, + "identifiers": [ + { + "external_type": "gemnasium", + "external_id": "9952e574-7b5b-46fa-a270-aeb694198a98", + "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98", + "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories" + }, + { + "external_type": "cve", + "external_id": "CVE-2017-11429", + "name": "CVE-2017-11429", + "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429" + } + ], + "project_fingerprint": "fa6f5b6c5d240b834ac5e901dc69f9484cef89ec", + "create_vulnerability_feedback_issue_path": "/tests/yarn-remediation-test/vulnerability_feedback", + "create_vulnerability_feedback_merge_request_path": "/tests/yarn-remediation-test/vulnerability_feedback", + "create_vulnerability_feedback_dismissal_path": "/tests/yarn-remediation-test/vulnerability_feedback", + "project": { + "id": 31, + "name": "yarn-remediation-test", + "full_path": "/tests/yarn-remediation-test", + "full_name": "tests / yarn-remediation-test" + }, + "dismissal_feedback": null, + "issue_feedback": null, + "merge_request_feedback": null, + "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.", + "links": [ + { + "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279" + }, + { + "url": "https://www.kb.cert.org/vuls/id/475445" + }, + { + "url": "https://github.com/Clever/saml2/issues/127" + } + ], + "location": { + "file": "yarn.lock", + "dependency": { + "package": { + "name": "saml2-js" + }, + "version": "1.5.0" + } + }, + "solution": "Upgrade to fixed version.\r\n", + "blob_path": "/tests/yarn-remediation-test/blob/cc6c4a0778460455ae5d16ca7025ca9ca1ca75ac/yarn.lock" + } +] +``` |