Commit bef5540c authored by Pavel Shutsin's avatar Pavel Shutsin

Merge branch '344800-collect-project-stages' into 'master'

Collect projects Value Stream stages

See merge request gitlab-org/gitlab!75336
parents ec227a08 eb47cadf
...@@ -26,6 +26,12 @@ module Analytics ...@@ -26,6 +26,12 @@ module Analytics
:project_id :project_id
end end
def self.distinct_stages_within_hierarchy(group)
with_preloaded_labels
.where(project_id: group.all_projects.select(:id))
.select("DISTINCT ON(stage_event_hash_id) #{quoted_table_name}.*")
end
private private
# Project should belong to a group when the stage has Label based events since only GroupLabels are allowed. # Project should belong to a group when the stage has Label based events since only GroupLabels are allowed.
......
...@@ -29,6 +29,7 @@ module Gitlab ...@@ -29,6 +29,7 @@ module Gitlab
def stages def stages
[ [
*group_stages, *group_stages,
*project_stages,
add_stage_event_hash_id(in_memory_lead_time_stage), add_stage_event_hash_id(in_memory_lead_time_stage),
add_stage_event_hash_id(in_memory_cycle_time_stage) add_stage_event_hash_id(in_memory_cycle_time_stage)
].uniq(&:stage_event_hash_id) ].uniq(&:stage_event_hash_id)
...@@ -42,6 +43,10 @@ module Gitlab ...@@ -42,6 +43,10 @@ module Gitlab
@group_stages ||= ::Analytics::CycleAnalytics::GroupStage.distinct_stages_within_hierarchy(group) @group_stages ||= ::Analytics::CycleAnalytics::GroupStage.distinct_stages_within_hierarchy(group)
end end
def project_stages
@project_stages ||= ::Analytics::CycleAnalytics::ProjectStage.distinct_stages_within_hierarchy(group)
end
def in_memory_lead_time_stage def in_memory_lead_time_stage
::Analytics::CycleAnalytics::GroupStage.new( ::Analytics::CycleAnalytics::GroupStage.new(
name: 'lead time', # not visible to the user name: 'lead time', # not visible to the user
......
...@@ -5,9 +5,13 @@ require 'spec_helper' ...@@ -5,9 +5,13 @@ require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::DistinctStageLoader do RSpec.describe Gitlab::Analytics::CycleAnalytics::DistinctStageLoader do
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:stage_1) { create(:cycle_analytics_group_stage, group: group, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) } let_it_be(:stage_1) { create(:cycle_analytics_group_stage, group: group, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
let_it_be(:stage_2) { create(:cycle_analytics_group_stage, group: group, start_event_identifier: :issue_created, end_event_identifier: :issue_first_associated_with_milestone) } let_it_be(:common_stage_params) { { start_event_identifier: :issue_created, end_event_identifier: :issue_first_associated_with_milestone } }
let_it_be(:stage_duplicate) { create(:cycle_analytics_group_stage, group: group, start_event_identifier: :issue_created, end_event_identifier: :issue_first_associated_with_milestone) } let_it_be(:stage_2) { create(:cycle_analytics_group_stage, group: group, **common_stage_params) }
let_it_be(:stage_triplicate) { create(:cycle_analytics_group_stage, group: group, start_event_identifier: :issue_created, end_event_identifier: :issue_first_associated_with_milestone) } let_it_be(:stage_duplicate) { create(:cycle_analytics_group_stage, group: group, **common_stage_params) }
let_it_be(:stage_triplicate) { create(:cycle_analytics_group_stage, group: group, **common_stage_params) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:project_stage) { create(:cycle_analytics_project_stage, project: project, **common_stage_params) }
subject(:distinct_stages) { described_class.new(group: group).stages } subject(:distinct_stages) { described_class.new(group: group).stages }
......
...@@ -29,4 +29,29 @@ RSpec.describe Analytics::CycleAnalytics::ProjectStage do ...@@ -29,4 +29,29 @@ RSpec.describe Analytics::CycleAnalytics::ProjectStage do
let(:default_params) { { project: project } } let(:default_params) { { project: project } }
end end
end end
describe '.distinct_stages_within_hierarchy' do
let_it_be(:top_level_group) { create(:group) }
let_it_be(:sub_group_1) { create(:group, parent: top_level_group) }
let_it_be(:sub_group_2) { create(:group, parent: sub_group_1) }
let_it_be(:project_1) { create(:project, group: sub_group_1) }
let_it_be(:project_2) { create(:project, group: sub_group_2) }
let_it_be(:project_3) { create(:project, group: top_level_group) }
let_it_be(:stage1) { create(:cycle_analytics_project_stage, project: project_1, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production) }
let_it_be(:stage2) { create(:cycle_analytics_project_stage, project: project_3, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production) }
let_it_be(:stage3) { create(:cycle_analytics_project_stage, project: project_1, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
let_it_be(:stage4) { create(:cycle_analytics_project_stage, project: project_3, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
subject(:distinct_start_and_end_event_identifiers) { described_class.distinct_stages_within_hierarchy(top_level_group).to_a.pluck(:start_event_identifier, :end_event_identifier) }
it 'returns distinct stages by start and end events (using stage_event_hash_id)' do
expect(distinct_start_and_end_event_identifiers).to match_array([
%w[issue_created issue_deployed_to_production],
%w[merge_request_created merge_request_merged]
])
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