Commit d48c5fe2 authored by Toon Claes's avatar Toon Claes

Merge branch '217383-rename-sprints' into 'master'

Rename Sprint to Iteration

See merge request gitlab-org/gitlab!31639
parents 22a8c7e4 17a5f712
...@@ -30,7 +30,7 @@ class Group < Namespace ...@@ -30,7 +30,7 @@ class Group < Namespace
has_many :members_and_requesters, as: :source, class_name: 'GroupMember' has_many :members_and_requesters, as: :source, class_name: 'GroupMember'
has_many :milestones has_many :milestones
has_many :sprints has_many :iterations
has_many :shared_group_links, foreign_key: :shared_with_group_id, class_name: 'GroupGroupLink' has_many :shared_group_links, foreign_key: :shared_with_group_id, class_name: 'GroupGroupLink'
has_many :shared_with_group_links, foreign_key: :shared_group_id, class_name: 'GroupGroupLink' has_many :shared_with_group_links, foreign_key: :shared_group_id, class_name: 'GroupGroupLink'
has_many :shared_groups, through: :shared_group_links, source: :shared_group has_many :shared_groups, through: :shared_group_links, source: :shared_group
......
...@@ -13,7 +13,7 @@ module InternalIdEnums ...@@ -13,7 +13,7 @@ module InternalIdEnums
operations_feature_flags: 6, operations_feature_flags: 6,
operations_user_lists: 7, operations_user_lists: 7,
alert_management_alerts: 8, alert_management_alerts: 8,
sprints: 9 sprints: 9 # iterations
} }
end end
end end
......
...@@ -32,7 +32,7 @@ class Issue < ApplicationRecord ...@@ -32,7 +32,7 @@ class Issue < ApplicationRecord
belongs_to :project belongs_to :project
belongs_to :duplicated_to, class_name: 'Issue' belongs_to :duplicated_to, class_name: 'Issue'
belongs_to :closed_by, class_name: 'User' belongs_to :closed_by, class_name: 'User'
belongs_to :sprint belongs_to :iteration, foreign_key: 'sprint_id'
belongs_to :moved_to, class_name: 'Issue' belongs_to :moved_to, class_name: 'Issue'
has_one :moved_from, class_name: 'Issue', foreign_key: :moved_to_id has_one :moved_from, class_name: 'Issue', foreign_key: :moved_to_id
......
# frozen_string_literal: true # frozen_string_literal: true
class Sprint < ApplicationRecord class Iteration < ApplicationRecord
include Timebox include Timebox
self.table_name = 'sprints'
STATE_ID_MAP = { STATE_ID_MAP = {
active: 1, active: 1,
closed: 2 closed: 2
...@@ -10,14 +12,14 @@ class Sprint < ApplicationRecord ...@@ -10,14 +12,14 @@ class Sprint < ApplicationRecord
include AtomicInternalId include AtomicInternalId
has_many :issues has_many :issues, foreign_key: 'sprint_id'
has_many :merge_requests has_many :merge_requests, foreign_key: 'sprint_id'
belongs_to :project belongs_to :project
belongs_to :group belongs_to :group
has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.sprints&.maximum(:iid) } has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.iterations&.maximum(:iid) }
has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.sprints&.maximum(:iid) } has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.iterations&.maximum(:iid) }
state_machine :state, initial: :active do state_machine :state, initial: :active do
event :close do event :close do
...@@ -28,7 +30,7 @@ class Sprint < ApplicationRecord ...@@ -28,7 +30,7 @@ class Sprint < ApplicationRecord
transition closed: :active transition closed: :active
end end
state :active, value: Sprint::STATE_ID_MAP[:active] state :active, value: Iteration::STATE_ID_MAP[:active]
state :closed, value: Sprint::STATE_ID_MAP[:closed] state :closed, value: Iteration::STATE_ID_MAP[:closed]
end end
end end
...@@ -33,7 +33,7 @@ class MergeRequest < ApplicationRecord ...@@ -33,7 +33,7 @@ class MergeRequest < ApplicationRecord
belongs_to :target_project, class_name: "Project" belongs_to :target_project, class_name: "Project"
belongs_to :source_project, class_name: "Project" belongs_to :source_project, class_name: "Project"
belongs_to :merge_user, class_name: "User" belongs_to :merge_user, class_name: "User"
belongs_to :sprint belongs_to :iteration, foreign_key: 'sprint_id'
has_internal_id :iid, scope: :target_project, track_if: -> { !importing? }, init: ->(s) { s&.target_project&.merge_requests&.maximum(:iid) } has_internal_id :iid, scope: :target_project, track_if: -> { !importing? }, init: ->(s) { s&.target_project&.merge_requests&.maximum(:iid) }
......
...@@ -208,7 +208,7 @@ class Project < ApplicationRecord ...@@ -208,7 +208,7 @@ class Project < ApplicationRecord
has_many :services has_many :services
has_many :events has_many :events
has_many :milestones has_many :milestones
has_many :sprints has_many :iterations
has_many :notes has_many :notes
has_many :snippets, class_name: 'ProjectSnippet' has_many :snippets, class_name: 'ProjectSnippet'
has_many :hooks, class_name: 'ProjectHook' has_many :hooks, class_name: 'ProjectHook'
......
# frozen_string_literal: true # frozen_string_literal: true
# Search for sprints # Search for iterations
# #
# params - Hash # params - Hash
# project_ids: Array of project ids or single project id or ActiveRecord relation. # project_ids: Array of project ids or single project id or ActiveRecord relation.
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
# title - Filter by title. # title - Filter by title.
# state - Filters by state. # state - Filters by state.
class SprintsFinder class IterationsFinder
include FinderMethods include FinderMethods
include TimeFrameFilter include TimeFrameFilter
...@@ -20,7 +20,7 @@ class SprintsFinder ...@@ -20,7 +20,7 @@ class SprintsFinder
end end
def execute def execute
items = Sprint.all items = Iteration.all
items = by_groups_and_projects(items) items = by_groups_and_projects(items)
items = by_title(items) items = by_title(items)
items = by_search_title(items) items = by_search_title(items)
...@@ -53,7 +53,7 @@ class SprintsFinder ...@@ -53,7 +53,7 @@ class SprintsFinder
end end
def by_state(items) def by_state(items)
Sprint.filter_by_state(items, params[:state]) Iteration.filter_by_state(items, params[:state])
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
......
...@@ -15,7 +15,7 @@ module Iterations ...@@ -15,7 +15,7 @@ module Iterations
return ::ServiceResponse.error(message: _('Operation not allowed'), http_status: 403) unless return ::ServiceResponse.error(message: _('Operation not allowed'), http_status: 403) unless
parent.feature_available?(:iterations) && can?(current_user, :create_iteration, parent) parent.feature_available?(:iterations) && can?(current_user, :create_iteration, parent)
iteration = parent.sprints.new(params) iteration = parent.iterations.new(params)
if iteration.save if iteration.save
::ServiceResponse.success(message: _('New iteration created'), payload: { iteration: iteration }) ::ServiceResponse.success(message: _('New iteration created'), payload: { iteration: iteration })
......
...@@ -2,48 +2,48 @@ ...@@ -2,48 +2,48 @@
require 'spec_helper' require 'spec_helper'
describe SprintsFinder do describe IterationsFinder do
let(:now) { Time.now } let(:now) { Time.now }
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:project_1) { create(:project, namespace: group) } let_it_be(:project_1) { create(:project, namespace: group) }
let_it_be(:project_2) { create(:project, namespace: group) } let_it_be(:project_2) { create(:project, namespace: group) }
let!(:started_group_sprint) { create(:sprint, group: group, title: 'one test', start_date: now - 1.day, due_date: now) } let!(:started_group_iteration) { create(:iteration, group: group, title: 'one test', start_date: now - 1.day, due_date: now) }
let!(:upcoming_group_sprint) { create(:sprint, group: group, start_date: now + 1.day, due_date: now + 2.days) } let!(:upcoming_group_iteration) { create(:iteration, group: group, start_date: now + 1.day, due_date: now + 2.days) }
let!(:sprint_from_project_1) { create(:sprint, project: project_1, state: ::Sprint::STATE_ID_MAP[:active], start_date: now + 2.days, due_date: now + 3.days) } let!(:iteration_from_project_1) { create(:iteration, project: project_1, state: ::Iteration::STATE_ID_MAP[:active], start_date: now + 2.days, due_date: now + 3.days) }
let!(:sprint_from_project_2) { create(:sprint, project: project_2, state: ::Sprint::STATE_ID_MAP[:active], start_date: now + 4.days, due_date: now + 5.days) } let!(:iteration_from_project_2) { create(:iteration, project: project_2, state: ::Iteration::STATE_ID_MAP[:active], start_date: now + 4.days, due_date: now + 5.days) }
let(:project_ids) { [project_1.id, project_2.id] } let(:project_ids) { [project_1.id, project_2.id] }
subject { described_class.new(params).execute } subject { described_class.new(params).execute }
context 'sprints for projects' do context 'iterations for projects' do
let(:params) { { project_ids: project_ids, state: 'all' } } let(:params) { { project_ids: project_ids, state: 'all' } }
it 'returns sprints for projects' do it 'returns iterations for projects' do
expect(subject).to contain_exactly(sprint_from_project_1, sprint_from_project_2) expect(subject).to contain_exactly(iteration_from_project_1, iteration_from_project_2)
end end
end end
context 'sprints for groups' do context 'iterations for groups' do
let(:params) { { group_ids: group.id, state: 'all' } } let(:params) { { group_ids: group.id, state: 'all' } }
it 'returns sprints for groups' do it 'returns iterations for groups' do
expect(subject).to contain_exactly(started_group_sprint, upcoming_group_sprint) expect(subject).to contain_exactly(started_group_iteration, upcoming_group_iteration)
end end
end end
context 'sprints for groups and project' do context 'iterations for groups and project' do
let(:params) { { project_ids: project_ids, group_ids: group.id, state: 'all' } } let(:params) { { project_ids: project_ids, group_ids: group.id, state: 'all' } }
it 'returns sprints for groups and projects' do it 'returns iterations for groups and projects' do
expect(subject).to contain_exactly(started_group_sprint, upcoming_group_sprint, sprint_from_project_1, sprint_from_project_2) expect(subject).to contain_exactly(started_group_iteration, upcoming_group_iteration, iteration_from_project_1, iteration_from_project_2)
end end
it 'orders sprints by due date' do it 'orders iterations by due date' do
sprint = create(:sprint, group: group, due_date: now - 2.days) iteration = create(:iteration, group: group, due_date: now - 2.days)
expect(subject.first).to eq(sprint) expect(subject.first).to eq(iteration)
expect(subject.second).to eq(started_group_sprint) expect(subject.second).to eq(started_group_iteration)
expect(subject.third).to eq(upcoming_group_sprint) expect(subject.third).to eq(upcoming_group_iteration)
end end
end end
...@@ -57,62 +57,62 @@ describe SprintsFinder do ...@@ -57,62 +57,62 @@ describe SprintsFinder do
end end
before do before do
started_group_sprint.close started_group_iteration.close
sprint_from_project_1.close iteration_from_project_1.close
end end
it 'filters by active state' do it 'filters by active state' do
params[:state] = 'active' params[:state] = 'active'
expect(subject).to contain_exactly(upcoming_group_sprint, sprint_from_project_2) expect(subject).to contain_exactly(upcoming_group_iteration, iteration_from_project_2)
end end
it 'filters by closed state' do it 'filters by closed state' do
params[:state] = 'closed' params[:state] = 'closed'
expect(subject).to contain_exactly(started_group_sprint, sprint_from_project_1) expect(subject).to contain_exactly(started_group_iteration, iteration_from_project_1)
end end
it 'filters by title' do it 'filters by title' do
params[:title] = 'one test' params[:title] = 'one test'
expect(subject.to_a).to contain_exactly(started_group_sprint) expect(subject.to_a).to contain_exactly(started_group_iteration)
end end
it 'filters by search_title' do it 'filters by search_title' do
params[:search_title] = 'one t' params[:search_title] = 'one t'
expect(subject.to_a).to contain_exactly(started_group_sprint) expect(subject.to_a).to contain_exactly(started_group_iteration)
end end
context 'by timeframe' do context 'by timeframe' do
it 'returns sprints with start_date and due_date between timeframe' do it 'returns iterations with start_date and due_date between timeframe' do
params.merge!(start_date: now - 1.day, end_date: now + 3.days) params.merge!(start_date: now - 1.day, end_date: now + 3.days)
expect(subject).to match_array([started_group_sprint, upcoming_group_sprint, sprint_from_project_1]) expect(subject).to match_array([started_group_iteration, upcoming_group_iteration, iteration_from_project_1])
end end
it 'returns sprints which start before the timeframe' do it 'returns iterations which start before the timeframe' do
sprint = create(:sprint, project: project_2, start_date: now - 5.days) iteration = create(:iteration, project: project_2, start_date: now - 5.days)
params.merge!(start_date: now - 3.days, end_date: now - 2.days) params.merge!(start_date: now - 3.days, end_date: now - 2.days)
expect(subject).to match_array([sprint]) expect(subject).to match_array([iteration])
end end
it 'returns sprints which end after the timeframe' do it 'returns iterations which end after the timeframe' do
sprint = create(:sprint, project: project_2, due_date: now + 6.days) iteration = create(:iteration, project: project_2, due_date: now + 6.days)
params.merge!(start_date: now + 6.days, end_date: now + 7.days) params.merge!(start_date: now + 6.days, end_date: now + 7.days)
expect(subject).to match_array([sprint]) expect(subject).to match_array([iteration])
end end
end end
end end
describe '#find_by' do describe '#find_by' do
it 'finds a single sprint' do it 'finds a single iteration' do
finder = described_class.new(project_ids: [project_1.id], state: 'all') finder = described_class.new(project_ids: [project_1.id], state: 'all')
expect(finder.find_by(iid: sprint_from_project_1.iid)).to eq(sprint_from_project_1) expect(finder.find_by(iid: iteration_from_project_1.iid)).to eq(iteration_from_project_1)
end end
end end
end end
# frozen_string_literal: true # frozen_string_literal: true
FactoryBot.define do FactoryBot.define do
factory :sprint do factory :iteration do
title title
transient do transient do
...@@ -13,11 +13,11 @@ FactoryBot.define do ...@@ -13,11 +13,11 @@ FactoryBot.define do
end end
trait :active do trait :active do
state { Sprint::STATE_ID_MAP[:active] } state { Iteration::STATE_ID_MAP[:active] }
end end
trait :closed do trait :closed do
state { Sprint::STATE_ID_MAP[:closed] } state { Iteration::STATE_ID_MAP[:closed] }
end end
trait :with_dates do trait :with_dates do
...@@ -25,24 +25,24 @@ FactoryBot.define do ...@@ -25,24 +25,24 @@ FactoryBot.define do
due_date { Date.new(2000, 1, 30) } due_date { Date.new(2000, 1, 30) }
end end
after(:build, :stub) do |sprint, evaluator| after(:build, :stub) do |iteration, evaluator|
if evaluator.group if evaluator.group
sprint.group = evaluator.group iteration.group = evaluator.group
elsif evaluator.group_id elsif evaluator.group_id
sprint.group_id = evaluator.group_id iteration.group_id = evaluator.group_id
elsif evaluator.project elsif evaluator.project
sprint.project = evaluator.project iteration.project = evaluator.project
elsif evaluator.project_id elsif evaluator.project_id
sprint.project_id = evaluator.project_id iteration.project_id = evaluator.project_id
elsif evaluator.resource_parent elsif evaluator.resource_parent
id = evaluator.resource_parent.id id = evaluator.resource_parent.id
evaluator.resource_parent.is_a?(Group) ? evaluator.group_id = id : evaluator.project_id = id evaluator.resource_parent.is_a?(Group) ? evaluator.group_id = id : evaluator.project_id = id
else else
sprint.project = create(:project) iteration.project = create(:project)
end end
end end
factory :active_sprint, traits: [:active] factory :active_iteration, traits: [:active]
factory :closed_sprint, traits: [:closed] factory :closed_iteration, traits: [:closed]
end end
end end
...@@ -6,7 +6,7 @@ issues: ...@@ -6,7 +6,7 @@ issues:
- assignees - assignees
- updated_by - updated_by
- milestone - milestone
- sprint - iteration
- notes - notes
- resource_label_events - resource_label_events
- resource_weight_events - resource_weight_events
...@@ -116,7 +116,7 @@ merge_requests: ...@@ -116,7 +116,7 @@ merge_requests:
- assignee - assignee
- updated_by - updated_by
- milestone - milestone
- sprint - iteration
- notes - notes
- resource_label_events - resource_label_events
- resource_milestone_events - resource_milestone_events
...@@ -350,7 +350,7 @@ project: ...@@ -350,7 +350,7 @@ project:
- labels - labels
- events - events
- milestones - milestones
- sprints - iterations
- notes - notes
- snippets - snippets
- hooks - hooks
......
...@@ -25,7 +25,7 @@ describe Group do ...@@ -25,7 +25,7 @@ describe Group do
it { is_expected.to have_many(:clusters).class_name('Clusters::Cluster') } it { is_expected.to have_many(:clusters).class_name('Clusters::Cluster') }
it { is_expected.to have_many(:container_repositories) } it { is_expected.to have_many(:container_repositories) }
it { is_expected.to have_many(:milestones) } it { is_expected.to have_many(:milestones) }
it { is_expected.to have_many(:sprints) } it { is_expected.to have_many(:iterations) }
describe '#members & #requesters' do describe '#members & #requesters' do
let(:requester) { create(:user) } let(:requester) { create(:user) }
......
...@@ -7,7 +7,7 @@ describe Issue do ...@@ -7,7 +7,7 @@ describe Issue do
describe "Associations" do describe "Associations" do
it { is_expected.to belong_to(:milestone) } it { is_expected.to belong_to(:milestone) }
it { is_expected.to belong_to(:sprint) } it { is_expected.to belong_to(:iteration) }
it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:moved_to).class_name('Issue') } it { is_expected.to belong_to(:moved_to).class_name('Issue') }
it { is_expected.to have_one(:moved_from).class_name('Issue') } it { is_expected.to have_one(:moved_from).class_name('Issue') }
......
# frozen_string_literal: true
require 'spec_helper'
describe Iteration do
it_behaves_like 'a timebox', :iteration do
let(:timebox_table_name) { described_class.table_name.to_sym }
end
describe "#iid" do
let!(:project) { create(:project) }
let!(:group) { create(:group) }
it "is properly scoped on project and group" do
iteration1 = create(:iteration, project: project)
iteration2 = create(:iteration, project: project)
iteration3 = create(:iteration, group: group)
iteration4 = create(:iteration, group: group)
iteration5 = create(:iteration, project: project)
want = {
iteration1: 1,
iteration2: 2,
iteration3: 1,
iteration4: 2,
iteration5: 3
}
got = {
iteration1: iteration1.iid,
iteration2: iteration2.iid,
iteration3: iteration3.iid,
iteration4: iteration4.iid,
iteration5: iteration5.iid
}
expect(got).to eq(want)
end
end
end
...@@ -19,7 +19,7 @@ describe MergeRequest do ...@@ -19,7 +19,7 @@ describe MergeRequest do
it { is_expected.to have_many(:merge_request_diffs) } it { is_expected.to have_many(:merge_request_diffs) }
it { is_expected.to have_many(:user_mentions).class_name("MergeRequestUserMention") } it { is_expected.to have_many(:user_mentions).class_name("MergeRequestUserMention") }
it { is_expected.to belong_to(:milestone) } it { is_expected.to belong_to(:milestone) }
it { is_expected.to belong_to(:sprint) } it { is_expected.to belong_to(:iteration) }
it { is_expected.to have_many(:resource_milestone_events) } it { is_expected.to have_many(:resource_milestone_events) }
it { is_expected.to have_many(:resource_state_events) } it { is_expected.to have_many(:resource_state_events) }
......
...@@ -21,7 +21,7 @@ describe Project do ...@@ -21,7 +21,7 @@ describe Project do
it { is_expected.to have_many(:merge_requests) } it { is_expected.to have_many(:merge_requests) }
it { is_expected.to have_many(:issues) } it { is_expected.to have_many(:issues) }
it { is_expected.to have_many(:milestones) } it { is_expected.to have_many(:milestones) }
it { is_expected.to have_many(:sprints) } it { is_expected.to have_many(:iterations) }
it { is_expected.to have_many(:project_members).dependent(:delete_all) } it { is_expected.to have_many(:project_members).dependent(:delete_all) }
it { is_expected.to have_many(:users).through(:project_members) } it { is_expected.to have_many(:users).through(:project_members) }
it { is_expected.to have_many(:requesters).dependent(:delete_all) } it { is_expected.to have_many(:requesters).dependent(:delete_all) }
......
# frozen_string_literal: true
require 'spec_helper'
describe Sprint do
it_behaves_like 'a timebox', :sprint
describe "#iid" do
let!(:project) { create(:project) }
let!(:group) { create(:group) }
it "is properly scoped on project and group" do
sprint1 = create(:sprint, project: project)
sprint2 = create(:sprint, project: project)
sprint3 = create(:sprint, group: group)
sprint4 = create(:sprint, group: group)
sprint5 = create(:sprint, project: project)
want = {
sprint1: 1,
sprint2: 2,
sprint3: 1,
sprint4: 2,
sprint5: 3
}
got = {
sprint1: sprint1.iid,
sprint2: sprint2.iid,
sprint3: sprint3.iid,
sprint4: sprint4.iid,
sprint5: sprint5.iid
}
expect(got).to eq(want)
end
end
end
...@@ -15,7 +15,7 @@ RSpec.shared_examples 'a timebox' do |timebox_type| ...@@ -15,7 +15,7 @@ RSpec.shared_examples 'a timebox' do |timebox_type|
let(:instance) { build(timebox_type, project: build(:project), group: nil) } let(:instance) { build(timebox_type, project: build(:project), group: nil) }
let(:scope) { :project } let(:scope) { :project }
let(:scope_attrs) { { project: instance.project } } let(:scope_attrs) { { project: instance.project } }
let(:usage) {timebox_table_name } let(:usage) { timebox_table_name }
end end
end end
...@@ -25,7 +25,7 @@ RSpec.shared_examples 'a timebox' do |timebox_type| ...@@ -25,7 +25,7 @@ RSpec.shared_examples 'a timebox' do |timebox_type|
let(:instance) { build(timebox_type, project: nil, group: build(:group)) } let(:instance) { build(timebox_type, project: nil, group: build(:group)) }
let(:scope) { :group } let(:scope) { :group }
let(:scope_attrs) { { namespace: instance.group } } let(:scope_attrs) { { namespace: instance.group } }
let(:usage) {timebox_table_name } let(:usage) { timebox_table_name }
end end
end end
end end
......
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