API: Ability to subscribe and unsubscribe from a merge request
This commit is contained in:
parent
bd0be13f5b
commit
f875189b39
5 changed files with 216 additions and 3 deletions
|
@ -11,7 +11,7 @@ v 8.7.0 (unreleased)
|
||||||
- Fix `signed_in_ip` being set to 127.0.0.1 when using a reverse proxy !3524
|
- Fix `signed_in_ip` being set to 127.0.0.1 when using a reverse proxy !3524
|
||||||
- Improved Markdown rendering performance !3389 (Yorick Peterse)
|
- Improved Markdown rendering performance !3389 (Yorick Peterse)
|
||||||
- Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu)
|
- Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu)
|
||||||
- API: Ability to subscribe and unsubscribe from an issue (Robert Schilling)
|
- API: Ability to subscribe and unsubscribe from issues and merge requests (Robert Schilling)
|
||||||
- Expose project badges in project settings
|
- Expose project badges in project settings
|
||||||
- Preserve time notes/comments have been updated at when moving issue
|
- Preserve time notes/comments have been updated at when moving issue
|
||||||
- Make HTTP(s) label consistent on clone bar (Stan Hu)
|
- Make HTTP(s) label consistent on clone bar (Stan Hu)
|
||||||
|
|
|
@ -606,3 +606,150 @@ Example response:
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Subscribe to a merge request
|
||||||
|
|
||||||
|
Subscribes to a merge request to receive notification. If the operation is
|
||||||
|
successful, status code `201` together with the updated merge request is
|
||||||
|
returned. If the user is already subscribed to the merge request, the status
|
||||||
|
code `304` is returned. If the project or merge request is not found, status
|
||||||
|
code `404` is returned.
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /projects/:id/merge_requests/:merge_request_id/subscribe
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Type | Required | Description |
|
||||||
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `id` | integer | yes | The ID of a project |
|
||||||
|
| `merge_request_id` | integer | yes | The ID of the merge request |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/17/subscribe
|
||||||
|
```
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 17,
|
||||||
|
"iid": 1,
|
||||||
|
"project_id": 5,
|
||||||
|
"title": "Et et sequi est impedit nulla ut rem et voluptatem.",
|
||||||
|
"description": "Consequatur velit eos rerum optio autem. Quia id officia quaerat dolorum optio. Illo laudantium aut ipsum dolorem.",
|
||||||
|
"state": "opened",
|
||||||
|
"created_at": "2016-04-05T21:42:23.233Z",
|
||||||
|
"updated_at": "2016-04-05T22:11:52.900Z",
|
||||||
|
"target_branch": "ui-dev-kit",
|
||||||
|
"source_branch": "version-1-9",
|
||||||
|
"upvotes": 0,
|
||||||
|
"downvotes": 0,
|
||||||
|
"author": {
|
||||||
|
"name": "Eileen Skiles",
|
||||||
|
"username": "leila",
|
||||||
|
"id": 19,
|
||||||
|
"state": "active",
|
||||||
|
"avatar_url": "http://www.gravatar.com/avatar/39ce4a2822cc896933ffbd68c1470e55?s=80&d=identicon",
|
||||||
|
"web_url": "https://gitlab.example.com/u/leila"
|
||||||
|
},
|
||||||
|
"assignee": {
|
||||||
|
"name": "Celine Wehner",
|
||||||
|
"username": "carli",
|
||||||
|
"id": 16,
|
||||||
|
"state": "active",
|
||||||
|
"avatar_url": "http://www.gravatar.com/avatar/f4cd5605b769dd2ce405a27c6e6f2684?s=80&d=identicon",
|
||||||
|
"web_url": "https://gitlab.example.com/u/carli"
|
||||||
|
},
|
||||||
|
"source_project_id": 5,
|
||||||
|
"target_project_id": 5,
|
||||||
|
"labels": [],
|
||||||
|
"work_in_progress": false,
|
||||||
|
"milestone": {
|
||||||
|
"id": 7,
|
||||||
|
"iid": 1,
|
||||||
|
"project_id": 5,
|
||||||
|
"title": "v2.0",
|
||||||
|
"description": "Corrupti eveniet et velit occaecati dolorem est rerum aut.",
|
||||||
|
"state": "closed",
|
||||||
|
"created_at": "2016-04-05T21:41:40.905Z",
|
||||||
|
"updated_at": "2016-04-05T21:41:40.905Z",
|
||||||
|
"due_date": null
|
||||||
|
},
|
||||||
|
"merge_when_build_succeeds": false,
|
||||||
|
"merge_status": "cannot_be_merged",
|
||||||
|
"subscribed": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Unsubscribe from a merge request
|
||||||
|
|
||||||
|
Unsubscribes from a merge request to not receive notifications from that merge
|
||||||
|
request. If the operation is successful, status code `201` together with the
|
||||||
|
updated merge request is returned. If the user is not subscribed to the merge
|
||||||
|
request, the status code `304` is returned. If the project or merge request is
|
||||||
|
not found, status code `404` is returned.
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /projects/:id/merge_requests/:merge_request_id/unsubscribe
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Type | Required | Description |
|
||||||
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `id` | integer | yes | The ID of a project |
|
||||||
|
| `merge_request_id` | integer | yes | The ID of the merge request |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/17/subscribe
|
||||||
|
```
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 17,
|
||||||
|
"iid": 1,
|
||||||
|
"project_id": 5,
|
||||||
|
"title": "Et et sequi est impedit nulla ut rem et voluptatem.",
|
||||||
|
"description": "Consequatur velit eos rerum optio autem. Quia id officia quaerat dolorum optio. Illo laudantium aut ipsum dolorem.",
|
||||||
|
"state": "opened",
|
||||||
|
"created_at": "2016-04-05T21:42:23.233Z",
|
||||||
|
"updated_at": "2016-04-05T22:11:52.900Z",
|
||||||
|
"target_branch": "ui-dev-kit",
|
||||||
|
"source_branch": "version-1-9",
|
||||||
|
"upvotes": 0,
|
||||||
|
"downvotes": 0,
|
||||||
|
"author": {
|
||||||
|
"name": "Eileen Skiles",
|
||||||
|
"username": "leila",
|
||||||
|
"id": 19,
|
||||||
|
"state": "active",
|
||||||
|
"avatar_url": "http://www.gravatar.com/avatar/39ce4a2822cc896933ffbd68c1470e55?s=80&d=identicon",
|
||||||
|
"web_url": "https://gitlab.example.com/u/leila"
|
||||||
|
},
|
||||||
|
"assignee": {
|
||||||
|
"name": "Celine Wehner",
|
||||||
|
"username": "carli",
|
||||||
|
"id": 16,
|
||||||
|
"state": "active",
|
||||||
|
"avatar_url": "http://www.gravatar.com/avatar/f4cd5605b769dd2ce405a27c6e6f2684?s=80&d=identicon",
|
||||||
|
"web_url": "https://gitlab.example.com/u/carli"
|
||||||
|
},
|
||||||
|
"source_project_id": 5,
|
||||||
|
"target_project_id": 5,
|
||||||
|
"labels": [],
|
||||||
|
"work_in_progress": false,
|
||||||
|
"milestone": {
|
||||||
|
"id": 7,
|
||||||
|
"iid": 1,
|
||||||
|
"project_id": 5,
|
||||||
|
"title": "v2.0",
|
||||||
|
"description": "Corrupti eveniet et velit occaecati dolorem est rerum aut.",
|
||||||
|
"state": "closed",
|
||||||
|
"created_at": "2016-04-05T21:41:40.905Z",
|
||||||
|
"updated_at": "2016-04-05T21:41:40.905Z",
|
||||||
|
"due_date": null
|
||||||
|
},
|
||||||
|
"merge_when_build_succeeds": false,
|
||||||
|
"merge_status": "cannot_be_merged",
|
||||||
|
"subscribed": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -235,7 +235,7 @@ module API
|
||||||
# Subscribes to a project issue
|
# Subscribes to a project issue
|
||||||
#
|
#
|
||||||
# Parameters:
|
# Parameters:
|
||||||
# id (required) - The ID of a project
|
# id (required) - The ID of a project
|
||||||
# issue_id (required) - The ID of a project issue
|
# issue_id (required) - The ID of a project issue
|
||||||
# Example Request:
|
# Example Request:
|
||||||
# POST /projects/:id/issues/:issue_id
|
# POST /projects/:id/issues/:issue_id
|
||||||
|
@ -270,7 +270,7 @@ module API
|
||||||
# Unsubscribes from a project issue
|
# Unsubscribes from a project issue
|
||||||
#
|
#
|
||||||
# Parameters:
|
# Parameters:
|
||||||
# id (required) - The ID of a project
|
# id (required) - The ID of a project
|
||||||
# issue_id (required) - The ID of a project issue
|
# issue_id (required) - The ID of a project issue
|
||||||
# Example Request:
|
# Example Request:
|
||||||
# POST /projects/:id/issues/:issue_id/unsubscribe
|
# POST /projects/:id/issues/:issue_id/unsubscribe
|
||||||
|
|
|
@ -327,6 +327,42 @@ module API
|
||||||
issues = ::Kaminari.paginate_array(merge_request.closes_issues(current_user))
|
issues = ::Kaminari.paginate_array(merge_request.closes_issues(current_user))
|
||||||
present paginate(issues), with: Entities::Issue, current_user: current_user
|
present paginate(issues), with: Entities::Issue, current_user: current_user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Subscribes to a merge request
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# id (required) - The ID of a project
|
||||||
|
# merge_request_id (required) - The ID of a merge request
|
||||||
|
# Example Request:
|
||||||
|
# POST /projects/:id/issues/:merge_request_id/subscribe
|
||||||
|
post "#{path}/subscribe" do
|
||||||
|
merge_request = user_project.merge_requests.find(params[:merge_request_id])
|
||||||
|
|
||||||
|
if !merge_request.subscribed?(current_user)
|
||||||
|
merge_request.toggle_subscription(current_user)
|
||||||
|
present merge_request, with: Entities::MergeRequest, current_user: current_user
|
||||||
|
else
|
||||||
|
not_modified!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Unsubscribes from a merge request
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# id (required) - The ID of a project
|
||||||
|
# merge_request_id (required) - The ID of a merge request
|
||||||
|
# Example Request:
|
||||||
|
# POST /projects/:id/merge_requests/:merge_request_id/unsubscribe
|
||||||
|
post "#{path}/unsubscribe" do
|
||||||
|
merge_request = user_project.merge_requests.find(params[:merge_request_id])
|
||||||
|
|
||||||
|
if merge_request.subscribed?(current_user)
|
||||||
|
merge_request.unsubscribe(current_user)
|
||||||
|
present merge_request, with: Entities::MergeRequest, current_user: current_user
|
||||||
|
else
|
||||||
|
not_modified!
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -516,6 +516,36 @@ describe API::API, api: true do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'POST :id/merge_requests/:merge_request_id/subscribe' do
|
||||||
|
it 'subscribes to a merge request' do
|
||||||
|
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscribe", admin)
|
||||||
|
|
||||||
|
expect(response.status).to eq(201)
|
||||||
|
expect(json_response['subscribed']).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns 304 if already subscribed' do
|
||||||
|
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscribe", user)
|
||||||
|
|
||||||
|
expect(response.status).to eq(304)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST :id/merge_requests/:merge_request_id/unsubscribe' do
|
||||||
|
it 'unsubscribes from a merge request' do
|
||||||
|
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/unsubscribe", user)
|
||||||
|
|
||||||
|
expect(response.status).to eq(201)
|
||||||
|
expect(json_response['subscribed']).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns 304 if not subscribed' do
|
||||||
|
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/unsubscribe", admin)
|
||||||
|
|
||||||
|
expect(response.status).to eq(304)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def mr_with_later_created_and_updated_at_time
|
def mr_with_later_created_and_updated_at_time
|
||||||
merge_request
|
merge_request
|
||||||
merge_request.created_at += 1.hour
|
merge_request.created_at += 1.hour
|
||||||
|
|
Loading…
Reference in a new issue