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