Commit bf064215 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Allow multiple todos behind a feature flag

This feature flag allows users to get multiple todos even if they have
an existing pending todo
parent 2503be2f
...@@ -216,7 +216,7 @@ class TodoService ...@@ -216,7 +216,7 @@ class TodoService
def create_todos(users, attributes) def create_todos(users, attributes)
Array(users).map do |user| Array(users).map do |user|
next if pending_todos(user, attributes).exists? next if pending_todos(user, attributes).exists? && Feature.disabled?(:multiple_todos, user)
issue_type = attributes.delete(:issue_type) issue_type = attributes.delete(:issue_type)
track_todo_creation(user, issue_type) track_todo_creation(user, issue_type)
...@@ -278,7 +278,7 @@ class TodoService ...@@ -278,7 +278,7 @@ class TodoService
create_todos(directly_addressed_users, attributes) create_todos(directly_addressed_users, attributes)
# Create Todos for mentioned users # Create Todos for mentioned users
mentioned_users = filter_mentioned_users(parent, note || target, author, skip_users) mentioned_users = filter_mentioned_users(parent, note || target, author, skip_users + directly_addressed_users)
attributes = attributes_for_todo(parent, target, author, Todo::MENTIONED, note) attributes = attributes_for_todo(parent, target, author, Todo::MENTIONED, note)
create_todos(mentioned_users, attributes) create_todos(mentioned_users, attributes)
end end
......
---
name: multiple_todos
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47629
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/28355
milestone: '13.8'
type: development
group: group::project management
default_enabled: false
...@@ -88,6 +88,8 @@ RSpec.describe API::Todos do ...@@ -88,6 +88,8 @@ RSpec.describe API::Todos do
end end
it 'returns 304 there already exist a todo on that epic' do it 'returns 304 there already exist a todo on that epic' do
stub_feature_flags(multiple_todos: false)
create(:todo, project: nil, group: group, user: user, target: epic) create(:todo, project: nil, group: group, user: user, target: epic)
subject subject
......
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe TodoService do RSpec.describe TodoService do
let(:author) { create(:user, username: 'author') } let_it_be(:author) { create(:user, username: 'author') }
let(:non_member) { create(:user, username: 'non_member') } let_it_be(:non_member) { create(:user, username: 'non_member') }
let(:member) { create(:user, username: 'member') } let_it_be(:member) { create(:user, username: 'member') }
let(:guest) { create(:user, username: 'guest') } let_it_be(:guest) { create(:user, username: 'guest') }
let(:admin) { create(:admin, username: 'administrator') } let_it_be(:admin) { create(:admin, username: 'administrator') }
let(:john_doe) { create(:user, username: 'john_doe') } let_it_be(:john_doe) { create(:user, username: 'john_doe') }
let(:skipped) { create(:user, username: 'skipped') } let_it_be(:skipped) { create(:user, username: 'skipped') }
let(:skip_users) { [skipped] } let(:skip_users) { [skipped] }
let(:service) { described_class.new } let(:service) { described_class.new }
...@@ -21,21 +21,23 @@ RSpec.describe TodoService do ...@@ -21,21 +21,23 @@ RSpec.describe TodoService do
let(:description_mentions) { "- [ ] Task 1\n- [ ] Task 2 FYI: #{mentions}" } let(:description_mentions) { "- [ ] Task 1\n- [ ] Task 2 FYI: #{mentions}" }
let(:description_directly_addressed) { "#{mentions}\n- [ ] Task 1\n- [ ] Task 2" } let(:description_directly_addressed) { "#{mentions}\n- [ ] Task 1\n- [ ] Task 2" }
let(:group) { create(:group) } let_it_be(:group, reload: true) { create(:group) }
let(:epic) { create(:epic, group: group, author: author, description: description_mentions) } let(:epic) { create(:epic, group: group, author: author, description: description_mentions) }
let(:todos_for) { [] } let(:todos_for) { [] }
let(:todos_not_for) { [] } let(:todos_not_for) { [] }
let(:target) { epic } let(:target) { epic }
before do before_all do
stub_licensed_features(epics: true)
group.add_guest(guest) group.add_guest(guest)
group.add_developer(author) group.add_developer(author)
group.add_developer(member) group.add_developer(member)
end end
before do
stub_licensed_features(epics: true)
end
shared_examples_for 'todos creation' do shared_examples_for 'todos creation' do
it 'creates todos for users mentioned' do it 'creates todos for users mentioned' do
if todos_for.count > 0 if todos_for.count > 0
...@@ -169,19 +171,19 @@ RSpec.describe TodoService do ...@@ -169,19 +171,19 @@ RSpec.describe TodoService do
end end
describe '#new_note' do describe '#new_note' do
let!(:first_todo) do
create(:todo, :assigned,
user: john_doe, project: nil, group: group, target: epic, author: author)
end
let!(:second_todo) do
create(:todo, :assigned,
user: john_doe, project: nil, group: group, target: epic, author: author)
end
let(:note) { create(:note, noteable: epic, project: nil, author: john_doe, note: mentions) } let(:note) { create(:note, noteable: epic, project: nil, author: john_doe, note: mentions) }
context 'when a note is created for an epic' do context 'when a note is created for an epic' do
let!(:first_todo) do
create(:todo, :assigned,
user: john_doe, project: nil, group: group, target: epic, author: author)
end
let!(:second_todo) do
create(:todo, :assigned,
user: john_doe, project: nil, group: group, target: epic, author: author)
end
it 'marks pending epic todos for the note author as done' do it 'marks pending epic todos for the note author as done' do
service.new_note(note, john_doe) service.new_note(note, john_doe)
...@@ -189,7 +191,7 @@ RSpec.describe TodoService do ...@@ -189,7 +191,7 @@ RSpec.describe TodoService do
expect(second_todo.reload).to be_done expect(second_todo.reload).to be_done
end end
it 'does not marka pending epic todos for the note author as done for system notes' do it 'does not mark pending epic todos for the note author as done for system notes' do
system_note = create(:system_note, noteable: epic) system_note = create(:system_note, noteable: epic)
service.new_note(system_note, john_doe) service.new_note(system_note, john_doe)
...@@ -208,8 +210,8 @@ RSpec.describe TodoService do ...@@ -208,8 +210,8 @@ RSpec.describe TodoService do
end end
let(:todo_params) { { action: Todo::MENTIONED } } let(:todo_params) { { action: Todo::MENTIONED } }
let(:todos_for) { [author, non_member, member, guest, admin, skipped] } let(:todos_for) { users }
let(:todos_not_for) { [john_doe] } let(:todos_not_for) { [] }
include_examples 'todos creation' include_examples 'todos creation'
end end
...@@ -220,8 +222,8 @@ RSpec.describe TodoService do ...@@ -220,8 +222,8 @@ RSpec.describe TodoService do
end end
let(:todo_params) { { action: Todo::DIRECTLY_ADDRESSED } } let(:todo_params) { { action: Todo::DIRECTLY_ADDRESSED } }
let(:todos_for) { [author, non_member, member, guest, admin, skipped] } let(:todos_for) { users }
let(:todos_not_for) { [john_doe] } let(:todos_not_for) { [] }
include_examples 'todos creation' include_examples 'todos creation'
end end
...@@ -290,7 +292,6 @@ RSpec.describe TodoService do ...@@ -290,7 +292,6 @@ RSpec.describe TodoService do
# for each valid mentioned user # for each valid mentioned user
should_create_todo(user: john_doe, target: merge_request, action: Todo::MENTIONED) should_create_todo(user: john_doe, target: merge_request, action: Todo::MENTIONED)
should_not_create_todo(user: approver_1, target: merge_request, action: Todo::MENTIONED)
# skip for code owner # skip for code owner
should_not_create_todo(user: code_owner, target: merge_request, action: Todo::APPROVAL_REQUIRED) should_not_create_todo(user: code_owner, target: merge_request, action: Todo::APPROVAL_REQUIRED)
......
...@@ -42,6 +42,8 @@ RSpec.describe 'Creating a todo for the alert' do ...@@ -42,6 +42,8 @@ RSpec.describe 'Creating a todo for the alert' do
context 'todo already exists' do context 'todo already exists' do
before do before do
stub_feature_flags(multiple_todos: false)
create(:todo, :pending, project: project, user: user, target: alert) create(:todo, :pending, project: project, user: user, target: alert)
end end
......
...@@ -302,6 +302,8 @@ RSpec.describe API::Todos do ...@@ -302,6 +302,8 @@ RSpec.describe API::Todos do
end end
it 'returns 304 there already exist a todo on that issuable' do it 'returns 304 there already exist a todo on that issuable' do
stub_feature_flags(multiple_todos: false)
create(:todo, project: project_1, author: author_1, user: john_doe, target: issuable) create(:todo, project: project_1, author: author_1, user: john_doe, target: issuable)
post api("/projects/#{project_1.id}/#{issuable_type}/#{issuable.iid}/todo", john_doe) post api("/projects/#{project_1.id}/#{issuable_type}/#{issuable.iid}/todo", john_doe)
......
...@@ -58,6 +58,10 @@ RSpec.describe AlertManagement::Alerts::Todo::CreateService do ...@@ -58,6 +58,10 @@ RSpec.describe AlertManagement::Alerts::Todo::CreateService do
create(:todo, :pending, **todo_params) create(:todo, :pending, **todo_params)
end end
before do
stub_feature_flags(multiple_todos: false)
end
it 'does not create a todo' do it 'does not create a todo' do
expect { result }.not_to change { Todo.count } expect { result }.not_to change { Todo.count }
end end
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment