Merge branch '51636-task-list-api-pderichs' into 'master'
Add task count and completed count to responses of Issue and MR See merge request gitlab-org/gitlab-ce!28859
This commit is contained in:
commit
3ef0c54966
|
@ -75,4 +75,11 @@ module Taskable
|
|||
def task_status_short
|
||||
task_status(short: true)
|
||||
end
|
||||
|
||||
def task_completion_status
|
||||
@task_completion_status ||= {
|
||||
count: tasks.summary.item_count,
|
||||
completed_count: tasks.summary.complete_count
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add task count and completed count to responses of Issue and MR
|
||||
merge_request: 28859
|
||||
author:
|
||||
type: added
|
|
@ -135,7 +135,11 @@ Example response:
|
|||
"award_emoji":"http://example.com/api/v4/projects/1/issues/76/award_emoji",
|
||||
"project":"http://example.com/api/v4/projects/1"
|
||||
},
|
||||
"subscribed": false
|
||||
"subscribed": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -265,7 +269,11 @@ Example response:
|
|||
"award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji",
|
||||
"project":"http://example.com/api/v4/projects/4"
|
||||
},
|
||||
"subscribed": false
|
||||
"subscribed": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -403,7 +411,11 @@ Example response:
|
|||
"award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji",
|
||||
"project":"http://example.com/api/v4/projects/4"
|
||||
},
|
||||
"subscribed": false
|
||||
"subscribed": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -500,6 +512,10 @@ Example response:
|
|||
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
|
||||
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
|
||||
"project": "http://example.com/api/v4/projects/1"
|
||||
},
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -583,6 +599,10 @@ Example response:
|
|||
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
|
||||
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
|
||||
"project": "http://example.com/api/v4/projects/1"
|
||||
},
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -674,6 +694,10 @@ Example response:
|
|||
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
|
||||
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
|
||||
"project": "http://example.com/api/v4/projects/1"
|
||||
},
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -780,6 +804,10 @@ Example response:
|
|||
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
|
||||
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
|
||||
"project": "http://example.com/api/v4/projects/1"
|
||||
},
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -865,6 +893,10 @@ Example response:
|
|||
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
|
||||
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
|
||||
"project": "http://example.com/api/v4/projects/1"
|
||||
},
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -931,7 +963,11 @@ Example response:
|
|||
"due_date": null,
|
||||
"web_url": "http://example.com/example/example/issues/12",
|
||||
"confidential": false,
|
||||
"discussion_locked": false
|
||||
"discussion_locked": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1029,7 +1065,11 @@ Example response:
|
|||
"due_date": null,
|
||||
"web_url": "http://example.com/example/example/issues/110",
|
||||
"confidential": false,
|
||||
"discussion_locked": false
|
||||
"discussion_locked": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
},
|
||||
"target_url": "https://gitlab.example.com/gitlab-org/gitlab-ci/issues/10",
|
||||
"body": "Vel voluptas atque dicta mollitia adipisci qui at.",
|
||||
|
|
|
@ -138,7 +138,11 @@ Parameters:
|
|||
"human_time_estimate": null,
|
||||
"human_total_time_spent": null
|
||||
},
|
||||
"squash": false
|
||||
"squash": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -280,7 +284,11 @@ Parameters:
|
|||
"human_time_estimate": null,
|
||||
"human_total_time_spent": null
|
||||
},
|
||||
"squash": false
|
||||
"squash": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -410,7 +418,11 @@ Parameters:
|
|||
"human_time_estimate": null,
|
||||
"human_total_time_spent": null
|
||||
},
|
||||
"squash": false
|
||||
"squash": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -545,7 +557,11 @@ Parameters:
|
|||
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
|
||||
},
|
||||
"diverged_commits_count": 2,
|
||||
"rebase_in_progress": false
|
||||
"rebase_in_progress": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -579,7 +595,7 @@ Parameters:
|
|||
"state": "active",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/10fc7f102be8de7657fb4d80898bbfe3?s=80&d=identicon",
|
||||
"web_url": "http://localhost/user2"
|
||||
},
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
@ -702,7 +718,11 @@ Parameters:
|
|||
"total_time_spent": 0,
|
||||
"human_time_estimate": null,
|
||||
"human_total_time_spent": null
|
||||
}
|
||||
},
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
},
|
||||
"changes": [
|
||||
{
|
||||
"old_path": "VERSION",
|
||||
|
@ -865,7 +885,11 @@ POST /projects/:id/merge_requests
|
|||
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
|
||||
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
|
||||
},
|
||||
"diverged_commits_count": 2
|
||||
"diverged_commits_count": 2,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1002,7 +1026,11 @@ Must include at least one non-required attribute from above.
|
|||
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
|
||||
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
|
||||
},
|
||||
"diverged_commits_count": 2
|
||||
"diverged_commits_count": 2,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1155,13 +1183,17 @@ Parameters:
|
|||
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
|
||||
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
|
||||
},
|
||||
"diverged_commits_count": 2
|
||||
"diverged_commits_count": 2,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Returns the up to date merge-ref HEAD commit
|
||||
|
||||
Merge the changes between the merge request source and target branches into `refs/merge-requests/:iid/merge`
|
||||
Merge the changes between the merge request source and target branches into `refs/merge-requests/:iid/merge`
|
||||
ref, of the target project repository, if possible. This ref will have the state the target branch would have if
|
||||
a regular merge action was taken.
|
||||
|
||||
|
@ -1309,7 +1341,11 @@ Parameters:
|
|||
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
|
||||
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
|
||||
},
|
||||
"diverged_commits_count": 2
|
||||
"diverged_commits_count": 2,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1345,7 +1381,7 @@ If the rebase operation is ongoing, the response will include the following:
|
|||
|
||||
```json
|
||||
{
|
||||
"rebase_in_progress": true
|
||||
"rebase_in_progress": true,
|
||||
"merge_error": null
|
||||
}
|
||||
```
|
||||
|
@ -1356,7 +1392,7 @@ the following:
|
|||
```json
|
||||
{
|
||||
"rebase_in_progress": false,
|
||||
"merge_error": null,
|
||||
"merge_error": null
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1365,7 +1401,7 @@ If the rebase operation fails, the response will include the following:
|
|||
```json
|
||||
{
|
||||
"rebase_in_progress": false,
|
||||
"merge_error": "Rebase failed. Please rebase locally",
|
||||
"merge_error": "Rebase failed. Please rebase locally"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1572,7 +1608,11 @@ Example response:
|
|||
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
|
||||
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
|
||||
},
|
||||
"diverged_commits_count": 2
|
||||
"diverged_commits_count": 2,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1701,7 +1741,11 @@ Example response:
|
|||
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
|
||||
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
|
||||
},
|
||||
"diverged_commits_count": 2
|
||||
"diverged_commits_count": 2,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -576,6 +576,8 @@ module API
|
|||
expose :time_stats, using: 'API::Entities::IssuableTimeStats' do |issue|
|
||||
issue
|
||||
end
|
||||
|
||||
expose :task_completion_status
|
||||
end
|
||||
|
||||
class Issue < IssueBasic
|
||||
|
@ -724,6 +726,8 @@ module API
|
|||
end
|
||||
|
||||
expose :squash
|
||||
|
||||
expose :task_completion_status
|
||||
end
|
||||
|
||||
class MergeRequest < MergeRequestBasic
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'task completion status response' do
|
||||
set(:user) { create(:user) }
|
||||
set(:project) do
|
||||
create(:project, :public, creator_id: user.id, namespace: user.namespace)
|
||||
end
|
||||
|
||||
shared_examples 'taskable completion status provider' do |path|
|
||||
samples = [
|
||||
{
|
||||
description: '',
|
||||
expected_count: 0,
|
||||
expected_completed_count: 0
|
||||
},
|
||||
{
|
||||
description: 'Lorem ipsum',
|
||||
expected_count: 0,
|
||||
expected_completed_count: 0
|
||||
},
|
||||
{
|
||||
description: %{- [ ] task 1
|
||||
- [x] task 2 },
|
||||
expected_count: 2,
|
||||
expected_completed_count: 1
|
||||
},
|
||||
{
|
||||
description: %{- [ ] task 1
|
||||
- [ ] task 2 },
|
||||
expected_count: 2,
|
||||
expected_completed_count: 0
|
||||
},
|
||||
{
|
||||
description: %{- [x] task 1
|
||||
- [x] task 2 },
|
||||
expected_count: 2,
|
||||
expected_completed_count: 2
|
||||
},
|
||||
{
|
||||
description: %{- [ ] task 1},
|
||||
expected_count: 1,
|
||||
expected_completed_count: 0
|
||||
},
|
||||
{
|
||||
description: %{- [x] task 1},
|
||||
expected_count: 1,
|
||||
expected_completed_count: 1
|
||||
}
|
||||
]
|
||||
samples.each do |sample_data|
|
||||
context "with a description of #{sample_data[:description].inspect}" do
|
||||
before do
|
||||
taskable.update!(description: sample_data[:description])
|
||||
|
||||
get api("#{path}?iids[]=#{taskable.iid}", user)
|
||||
end
|
||||
|
||||
it { expect(response).to have_gitlab_http_status(200) }
|
||||
|
||||
it 'returns the expected results' do
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response).not_to be_empty
|
||||
|
||||
task_completion_status = json_response.first['task_completion_status']
|
||||
expect(task_completion_status['count']).to eq(sample_data[:expected_count])
|
||||
expect(task_completion_status['completed_count']).to eq(sample_data[:expected_completed_count])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'task list completion status for issues' do
|
||||
it_behaves_like 'taskable completion status provider', '/issues' do
|
||||
let(:taskable) { create(:issue, project: project, author: user) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'task list completion status for merge_requests' do
|
||||
it_behaves_like 'taskable completion status provider', '/merge_requests' do
|
||||
let(:taskable) { create(:merge_request, source_project: project, target_project: project, author: user) }
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue