Commit 0dcb3a95 authored by Adam Hegyi's avatar Adam Hegyi

Automatically set position VSA stages

This change sets the relative_position based on the order of the
incoming array when persisting stages together with the
value stream record.

Also fix the enum value for IssueDeployedToProduction.
parent 26b813ce
...@@ -67,8 +67,7 @@ export default { ...@@ -67,8 +67,7 @@ export default {
state.stages = []; state.stages = [];
}, },
[types.RECEIVE_GROUP_STAGES_SUCCESS](state, stages) { [types.RECEIVE_GROUP_STAGES_SUCCESS](state, stages) {
const transformedStages = transformRawStages(stages); state.stages = transformRawStages(stages);
state.stages = transformedStages.sort((a, b) => a?.id > b?.id);
}, },
[types.REQUEST_UPDATE_STAGE](state) { [types.REQUEST_UPDATE_STAGE](state) {
state.isLoading = true; state.isLoading = true;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
class Analytics::CycleAnalytics::GroupValueStream < ApplicationRecord class Analytics::CycleAnalytics::GroupValueStream < ApplicationRecord
belongs_to :group belongs_to :group
has_many :stages, class_name: 'Analytics::CycleAnalytics::GroupStage', index_errors: true has_many :stages, -> { ordered }, class_name: 'Analytics::CycleAnalytics::GroupStage', index_errors: true
validates :group, :name, presence: true validates :group, :name, presence: true
validates :name, length: { minimum: 3, maximum: 100, allow_nil: false }, uniqueness: { scope: :group_id } validates :name, length: { minimum: 3, maximum: 100, allow_nil: false }, uniqueness: { scope: :group_id }
......
...@@ -37,6 +37,8 @@ module Analytics ...@@ -37,6 +37,8 @@ module Analytics
raw_params[:stages_attributes] = raw_params.delete(:stages) || [] raw_params[:stages_attributes] = raw_params.delete(:stages) || []
raw_params[:stages_attributes].map! { |attrs| build_stage_attributes(attrs) } raw_params[:stages_attributes].map! { |attrs| build_stage_attributes(attrs) }
set_relative_positions!(raw_params[:stages_attributes])
raw_params raw_params
end end
...@@ -62,6 +64,13 @@ module Analytics ...@@ -62,6 +64,13 @@ module Analytics
ServiceResponse.error(message: 'Forbidden', http_status: :forbidden, payload: { errors: nil }) ServiceResponse.error(message: 'Forbidden', http_status: :forbidden, payload: { errors: nil })
end end
end end
def set_relative_positions!(stages_attributes)
increment = (Gitlab::RelativePositioning::MAX_POSITION - Gitlab::RelativePositioning::START_POSITION).fdiv(stages_attributes.size + 1).floor
stages_attributes.each_with_index do |stage_attribute, i|
stage_attribute[:relative_position] = increment * i
end
end
end end
end end
end end
......
...@@ -23,4 +23,26 @@ RSpec.describe Analytics::CycleAnalytics::GroupValueStream, type: :model do ...@@ -23,4 +23,26 @@ RSpec.describe Analytics::CycleAnalytics::GroupValueStream, type: :model do
expect(value_stream.errors.messages).to eq(name: [I18n.t('errors.messages.taken')]) expect(value_stream.errors.messages).to eq(name: [I18n.t('errors.messages.taken')])
end end
end end
describe 'ordering of stages' do
let(:group) { create(:group) }
let(:value_stream) do
create(:cycle_analytics_group_value_stream, group: group, stages: [
create(:cycle_analytics_group_stage, group: group, name: "stage 1", relative_position: 5),
create(:cycle_analytics_group_stage, group: group, name: "stage 2", relative_position: nil),
create(:cycle_analytics_group_stage, group: group, name: "stage 3", relative_position: 1)
])
end
before do
value_stream.reload
end
describe 'stages attribute' do
it 'sorts stages by relative position' do
names = value_stream.stages.map(&:name)
expect(names).to eq(['stage 3', 'stage 1', 'stage 2'])
end
end
end
end end
...@@ -49,6 +49,15 @@ RSpec.describe Analytics::CycleAnalytics::ValueStreams::CreateService do ...@@ -49,6 +49,15 @@ RSpec.describe Analytics::CycleAnalytics::ValueStreams::CreateService do
expect(value_stream.stages.size).to eq(2) expect(value_stream.stages.size).to eq(2)
end end
it 'calculates and sets relative_position for the stages based on the incoming stages array' do
incoming_stage_names = params[:stages].map { |stage| stage[:name] }
value_stream = subject.payload[:value_stream]
persisted_stages_sorted_by_relative_position = value_stream.stages.sort_by(&:relative_position).map(&:name)
expect(persisted_stages_sorted_by_relative_position).to eq(incoming_stage_names)
end
context 'when the stage is invalid' do context 'when the stage is invalid' do
it 'propagates validation errors' do it 'propagates validation errors' do
params[:stages].first[:name] = '' params[:stages].first[:name] = ''
......
...@@ -53,6 +53,21 @@ RSpec.describe Analytics::CycleAnalytics::ValueStreams::UpdateService do ...@@ -53,6 +53,21 @@ RSpec.describe Analytics::CycleAnalytics::ValueStreams::UpdateService do
expect(last_stage.reload.name).to eq('updated') expect(last_stage.reload.name).to eq('updated')
end end
context 'relative positioning' do
before do
params[:stages].reverse!
end
it 'calculates and sets relative_position for the stages based on the incoming stages array' do
incoming_stage_names = params[:stages].map { |stage| stage[:name] }
value_stream = subject.payload[:value_stream]
persisted_stages_sorted_by_relative_position = value_stream.stages.sort_by(&:relative_position).map(&:name)
expect(persisted_stages_sorted_by_relative_position).to eq(incoming_stage_names)
end
end
context 'when the params are invalid' do context 'when the params are invalid' do
before do before do
params[:stages].last[:name] = '' params[:stages].last[:name] = ''
......
...@@ -8,10 +8,12 @@ module Gitlab ...@@ -8,10 +8,12 @@ module Gitlab
# Issue: < 100 # Issue: < 100
# MergeRequest: >= 100 && < 1000 # MergeRequest: >= 100 && < 1000
# Custom events for default stages: >= 1000 (legacy) # Custom events for default stages: >= 1000 (legacy)
#
# To avoid duplications, verify that the value does not exist in ee/lib/ee/gitlab/analytics/cycle_analytics/stage_events.rb
ENUM_MAPPING = { ENUM_MAPPING = {
StageEvents::IssueCreated => 1, StageEvents::IssueCreated => 1,
StageEvents::IssueFirstMentionedInCommit => 2, StageEvents::IssueFirstMentionedInCommit => 2,
StageEvents::IssueDeployedToProduction => 3, StageEvents::IssueDeployedToProduction => 10,
StageEvents::MergeRequestCreated => 100, StageEvents::MergeRequestCreated => 100,
StageEvents::MergeRequestFirstDeployedToProduction => 101, StageEvents::MergeRequestFirstDeployedToProduction => 101,
StageEvents::MergeRequestLastBuildFinished => 102, StageEvents::MergeRequestLastBuildFinished => 102,
......
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