summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean McGivern <sean@gitlab.com>2019-07-18 09:23:54 +0000
committerSean McGivern <sean@gitlab.com>2019-07-18 09:23:54 +0000
commit0d1adc9f7f990254fd88ba03011908cc4f83461d (patch)
tree9ae9ca3abd0e8db7dcf3fe21b424070d0b3c7f39
parentf4ce99c54225b846a1d176d819d9db94de68ac52 (diff)
parent196dfd1243d5b5cf9786ff5019049104f7c22c7a (diff)
downloadgitlab-ce-0d1adc9f7f990254fd88ba03011908cc4f83461d.tar.gz
Merge branch 'adjust-cycle-analytics-to-group-level' into 'master'
Adjust cycle analytics to group level See merge request gitlab-org/gitlab-ce!30391
-rw-r--r--app/models/cycle_analytics/group_level.rb31
-rw-r--r--app/models/cycle_analytics/level_base.rb (renamed from app/models/cycle_analytics/base.rb)6
-rw-r--r--app/models/cycle_analytics/project_level.rb5
-rw-r--r--app/serializers/analytics_issue_entity.rb6
-rw-r--r--app/serializers/analytics_merge_request_entity.rb2
-rw-r--r--app/serializers/analytics_stage_entity.rb4
-rw-r--r--app/serializers/group_analytics_stage_entity.rb16
-rw-r--r--app/serializers/group_analytics_stage_serializer.rb5
-rw-r--r--lib/gitlab/cycle_analytics/base_event_fetcher.rb21
-rw-r--r--lib/gitlab/cycle_analytics/base_query.rb14
-rw-r--r--lib/gitlab/cycle_analytics/base_stage.rb24
-rw-r--r--lib/gitlab/cycle_analytics/code_event_fetcher.rb6
-rw-r--r--lib/gitlab/cycle_analytics/group_stage_summary.rb24
-rw-r--r--lib/gitlab/cycle_analytics/issue_event_fetcher.rb6
-rw-r--r--lib/gitlab/cycle_analytics/issue_helper.rb3
-rw-r--r--lib/gitlab/cycle_analytics/metrics_tables.rb8
-rw-r--r--lib/gitlab/cycle_analytics/permissions.rb2
-rw-r--r--lib/gitlab/cycle_analytics/plan_event_fetcher.rb6
-rw-r--r--lib/gitlab/cycle_analytics/plan_helper.rb13
-rw-r--r--lib/gitlab/cycle_analytics/production_event_fetcher.rb6
-rw-r--r--lib/gitlab/cycle_analytics/review_event_fetcher.rb6
-rw-r--r--lib/gitlab/cycle_analytics/summary/group/base.rb24
-rw-r--r--lib/gitlab/cycle_analytics/summary/group/deploy.rb29
-rw-r--r--lib/gitlab/cycle_analytics/summary/group/issue.rb25
-rw-r--r--spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb6
-rw-r--r--spec/lib/gitlab/cycle_analytics/code_stage_spec.rb98
-rw-r--r--spec/lib/gitlab/cycle_analytics/group_stage_summary_spec.rb88
-rw-r--r--spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb73
-rw-r--r--spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb78
-rw-r--r--spec/lib/gitlab/cycle_analytics/review_stage_spec.rb68
-rw-r--r--spec/lib/gitlab/cycle_analytics/shared_event_spec.rb2
-rw-r--r--spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb4
-rw-r--r--spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb70
-rw-r--r--spec/lib/gitlab/cycle_analytics/test_stage_spec.rb4
-rw-r--r--spec/lib/gitlab/cycle_analytics/usage_data_spec.rb2
-rw-r--r--spec/models/cycle_analytics/code_spec.rb4
-rw-r--r--spec/models/cycle_analytics/group_level_spec.rb46
-rw-r--r--spec/models/cycle_analytics/issue_spec.rb2
-rw-r--r--spec/models/cycle_analytics/plan_spec.rb2
-rw-r--r--spec/models/cycle_analytics/production_spec.rb4
-rw-r--r--spec/models/cycle_analytics/project_level_spec.rb2
-rw-r--r--spec/models/cycle_analytics/review_spec.rb2
-rw-r--r--spec/models/cycle_analytics/staging_spec.rb4
-rw-r--r--spec/models/cycle_analytics/test_spec.rb8
-rw-r--r--spec/serializers/analytics_issue_entity_spec.rb6
-rw-r--r--spec/serializers/analytics_issue_serializer_spec.rb6
-rw-r--r--spec/serializers/analytics_merge_request_serializer_spec.rb6
-rw-r--r--spec/serializers/analytics_stage_serializer_spec.rb10
-rw-r--r--spec/support/cycle_analytics_helpers/test_generation.rb12
49 files changed, 772 insertions, 127 deletions
diff --git a/app/models/cycle_analytics/group_level.rb b/app/models/cycle_analytics/group_level.rb
new file mode 100644
index 00000000000..508cde0ca00
--- /dev/null
+++ b/app/models/cycle_analytics/group_level.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module CycleAnalytics
+ class GroupLevel
+ include LevelBase
+ attr_reader :options, :group
+
+ def initialize(group:, options:)
+ @group = group
+ @options = options.merge(group: group)
+ end
+
+ def summary
+ @summary ||= ::Gitlab::CycleAnalytics::GroupStageSummary.new(group,
+ from: options[:from],
+ current_user: options[:current_user]).data
+ end
+
+ def permissions(*)
+ STAGES.each_with_object({}) do |stage, obj|
+ obj[stage] = true
+ end
+ end
+
+ def stats
+ @stats ||= STAGES.map do |stage_name|
+ self[stage_name].as_json(serializer: GroupAnalyticsStageSerializer)
+ end
+ end
+ end
+end
diff --git a/app/models/cycle_analytics/base.rb b/app/models/cycle_analytics/level_base.rb
index d7b28cd1b67..543349ebf8f 100644
--- a/app/models/cycle_analytics/base.rb
+++ b/app/models/cycle_analytics/level_base.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
module CycleAnalytics
- class Base
+ module LevelBase
STAGES = %i[issue plan code test review staging production].freeze
def all_medians_by_stage
STAGES.each_with_object({}) do |stage_name, medians_per_stage|
- medians_per_stage[stage_name] = self[stage_name].median
+ medians_per_stage[stage_name] = self[stage_name].project_median
end
end
@@ -21,7 +21,7 @@ module CycleAnalytics
end
def [](stage_name)
- Gitlab::CycleAnalytics::Stage[stage_name].new(project: @project, options: @options)
+ Gitlab::CycleAnalytics::Stage[stage_name].new(options: options)
end
end
end
diff --git a/app/models/cycle_analytics/project_level.rb b/app/models/cycle_analytics/project_level.rb
index 22631cc7d41..4aa426c58a1 100644
--- a/app/models/cycle_analytics/project_level.rb
+++ b/app/models/cycle_analytics/project_level.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
module CycleAnalytics
- class ProjectLevel < Base
+ class ProjectLevel
+ include LevelBase
attr_reader :project, :options
def initialize(project, options:)
@project = project
- @options = options
+ @options = options.merge(project: project)
end
def summary
diff --git a/app/serializers/analytics_issue_entity.rb b/app/serializers/analytics_issue_entity.rb
index ab15bd0ac7a..29d4a6ae1d0 100644
--- a/app/serializers/analytics_issue_entity.rb
+++ b/app/serializers/analytics_issue_entity.rb
@@ -20,12 +20,12 @@ class AnalyticsIssueEntity < Grape::Entity
end
expose :url do |object|
- url_to(:namespace_project_issue, id: object[:iid].to_s)
+ url_to(:namespace_project_issue, object)
end
private
- def url_to(route, id)
- public_send("#{route}_url", request.project.namespace, request.project, id) # rubocop:disable GitlabSecurity/PublicSend
+ def url_to(route, object)
+ public_send("#{route}_url", object[:path], object[:name], object[:iid].to_s) # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/app/serializers/analytics_merge_request_entity.rb b/app/serializers/analytics_merge_request_entity.rb
index b7134da9461..21d7eeb81b0 100644
--- a/app/serializers/analytics_merge_request_entity.rb
+++ b/app/serializers/analytics_merge_request_entity.rb
@@ -4,6 +4,6 @@ class AnalyticsMergeRequestEntity < AnalyticsIssueEntity
expose :state
expose :url do |object|
- url_to(:namespace_project_merge_request, id: object[:iid].to_s)
+ url_to(:namespace_project_merge_request, object)
end
end
diff --git a/app/serializers/analytics_stage_entity.rb b/app/serializers/analytics_stage_entity.rb
index 8bc6da5aeeb..eb38b90fb18 100644
--- a/app/serializers/analytics_stage_entity.rb
+++ b/app/serializers/analytics_stage_entity.rb
@@ -8,9 +8,9 @@ class AnalyticsStageEntity < Grape::Entity
expose :legend
expose :description
- expose :median, as: :value do |stage|
+ expose :project_median, as: :value do |stage|
# median returns a BatchLoader instance which we first have to unwrap by using to_f
# we use to_f to make sure results below 1 are presented to the end-user
- stage.median.to_f.nonzero? ? distance_of_time_in_words(stage.median) : nil
+ stage.project_median.to_f.nonzero? ? distance_of_time_in_words(stage.project_median) : nil
end
end
diff --git a/app/serializers/group_analytics_stage_entity.rb b/app/serializers/group_analytics_stage_entity.rb
new file mode 100644
index 00000000000..81be20e7dd8
--- /dev/null
+++ b/app/serializers/group_analytics_stage_entity.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class GroupAnalyticsStageEntity < Grape::Entity
+ include EntityDateHelper
+
+ expose :title
+ expose :name
+ expose :legend
+ expose :description
+
+ expose :group_median, as: :value do |stage|
+ # group_median returns a BatchLoader instance which we first have to unwrap by using to_f
+ # we use to_f to make sure results below 1 are presented to the end-user
+ stage.group_median.to_f.nonzero? ? distance_of_time_in_words(stage.group_median) : nil
+ end
+end
diff --git a/app/serializers/group_analytics_stage_serializer.rb b/app/serializers/group_analytics_stage_serializer.rb
new file mode 100644
index 00000000000..ec448dea602
--- /dev/null
+++ b/app/serializers/group_analytics_stage_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class GroupAnalyticsStageSerializer < BaseSerializer
+ entity GroupAnalyticsStageEntity
+end
diff --git a/lib/gitlab/cycle_analytics/base_event_fetcher.rb b/lib/gitlab/cycle_analytics/base_event_fetcher.rb
index 0cacef5b278..96aa799e864 100644
--- a/lib/gitlab/cycle_analytics/base_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/base_event_fetcher.rb
@@ -5,12 +5,11 @@ module Gitlab
class BaseEventFetcher
include BaseQuery
- attr_reader :projections, :query, :stage, :order, :project, :options
+ attr_reader :projections, :query, :stage, :order, :options
MAX_EVENTS = 50
- def initialize(project: nil, stage:, options:)
- @project = project
+ def initialize(stage:, options:)
@stage = stage
@options = options
end
@@ -68,11 +67,23 @@ module Gitlab
end
def allowed_ids_source
- { project_id: project.id }
+ group ? { group_id: group.id, include_subgroups: true } : { project_id: project.id }
+ end
+
+ def serialization_context
+ {}
end
def projects
- [project]
+ group ? Project.inside_path(group.full_path) : [project]
+ end
+
+ def group
+ @group ||= options.fetch(:group, nil)
+ end
+
+ def project
+ @project ||= options.fetch(:project, nil)
end
end
end
diff --git a/lib/gitlab/cycle_analytics/base_query.rb b/lib/gitlab/cycle_analytics/base_query.rb
index 39fc1759cfc..9c98c0bfbf2 100644
--- a/lib/gitlab/cycle_analytics/base_query.rb
+++ b/lib/gitlab/cycle_analytics/base_query.rb
@@ -16,17 +16,25 @@ module Gitlab
def stage_query(project_ids)
query = mr_closing_issues_table.join(issue_table).on(issue_table[:id].eq(mr_closing_issues_table[:issue_id]))
.join(issue_metrics_table).on(issue_table[:id].eq(issue_metrics_table[:issue_id]))
+ .join(projects_table).on(issue_table[:project_id].eq(projects_table[:id]))
+ .join(routes_table).on(projects_table[:namespace_id].eq(routes_table[:source_id]))
.project(issue_table[:project_id].as("project_id"))
.where(issue_table[:project_id].in(project_ids))
+ .where(routes_table[:source_type].eq('Namespace'))
.where(issue_table[:created_at].gteq(options[:from]))
# Load merge_requests
- query = query.join(mr_table, Arel::Nodes::OuterJoin)
+
+ query = load_merge_requests(query)
+
+ query
+ end
+
+ def load_merge_requests(query)
+ query.join(mr_table, Arel::Nodes::OuterJoin)
.on(mr_table[:id].eq(mr_closing_issues_table[:merge_request_id]))
.join(mr_metrics_table)
.on(mr_table[:id].eq(mr_metrics_table[:merge_request_id]))
-
- query
end
end
end
diff --git a/lib/gitlab/cycle_analytics/base_stage.rb b/lib/gitlab/cycle_analytics/base_stage.rb
index 98b86e54340..678a891e941 100644
--- a/lib/gitlab/cycle_analytics/base_stage.rb
+++ b/lib/gitlab/cycle_analytics/base_stage.rb
@@ -5,10 +5,9 @@ module Gitlab
class BaseStage
include BaseQuery
- attr_reader :project, :options
+ attr_reader :options
- def initialize(project: nil, options:)
- @project = project
+ def initialize(options:)
@options = options
end
@@ -24,7 +23,7 @@ module Gitlab
raise NotImplementedError.new("Expected #{self.name} to implement title")
end
- def median
+ def project_median
return if project.nil?
BatchLoader.for(project.id).batch(key: name) do |project_ids, loader|
@@ -42,6 +41,10 @@ module Gitlab
end
end
+ def group_median
+ median_query(projects.map(&:id))
+ end
+
def median_query(project_ids)
# Build a `SELECT` query. We find the first of the `end_time_attrs` that isn't `NULL` (call this end_time).
# Next, we find the first of the start_time_attrs that isn't `NULL` (call this start_time).
@@ -67,8 +70,7 @@ module Gitlab
private
def event_fetcher
- @event_fetcher ||= Gitlab::CycleAnalytics::EventFetcher[name].new(project: project,
- stage: name,
+ @event_fetcher ||= Gitlab::CycleAnalytics::EventFetcher[name].new(stage: name,
options: event_options)
end
@@ -77,7 +79,15 @@ module Gitlab
end
def projects
- [project]
+ group ? Project.inside_path(group.full_path) : [project]
+ end
+
+ def group
+ @group ||= options.fetch(:group, nil)
+ end
+
+ def project
+ @project ||= options.fetch(:project, nil)
end
end
end
diff --git a/lib/gitlab/cycle_analytics/code_event_fetcher.rb b/lib/gitlab/cycle_analytics/code_event_fetcher.rb
index 9e7ca529579..1e4e9b9e02c 100644
--- a/lib/gitlab/cycle_analytics/code_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/code_event_fetcher.rb
@@ -11,7 +11,9 @@ module Gitlab
mr_table[:id],
mr_table[:created_at],
mr_table[:state],
- mr_table[:author_id]]
+ mr_table[:author_id],
+ projects_table[:name],
+ routes_table[:path]]
@order = mr_table[:created_at]
super(*args)
@@ -20,7 +22,7 @@ module Gitlab
private
def serialize(event)
- AnalyticsMergeRequestSerializer.new(project: project).represent(event)
+ AnalyticsMergeRequestSerializer.new(serialization_context).represent(event)
end
def allowed_ids_finder_class
diff --git a/lib/gitlab/cycle_analytics/group_stage_summary.rb b/lib/gitlab/cycle_analytics/group_stage_summary.rb
new file mode 100644
index 00000000000..7b5c74e1a1b
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/group_stage_summary.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module CycleAnalytics
+ class GroupStageSummary
+ def initialize(group, from:, current_user:)
+ @group = group
+ @from = from
+ @current_user = current_user
+ end
+
+ def data
+ [serialize(Summary::Group::Issue.new(group: @group, from: @from, current_user: @current_user)),
+ serialize(Summary::Group::Deploy.new(group: @group, from: @from))]
+ end
+
+ private
+
+ def serialize(summary_object)
+ AnalyticsSummarySerializer.new.represent(summary_object)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb b/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
index bb3520ae920..2d03e425a6a 100644
--- a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
@@ -10,7 +10,9 @@ module Gitlab
issue_table[:iid],
issue_table[:id],
issue_table[:created_at],
- issue_table[:author_id]]
+ issue_table[:author_id],
+ projects_table[:name],
+ routes_table[:path]]
super(*args)
end
@@ -18,7 +20,7 @@ module Gitlab
private
def serialize(event)
- AnalyticsIssueSerializer.new(project: project).represent(event)
+ AnalyticsIssueSerializer.new(serialization_context).represent(event)
end
def allowed_ids_finder_class
diff --git a/lib/gitlab/cycle_analytics/issue_helper.rb b/lib/gitlab/cycle_analytics/issue_helper.rb
index ac836b8bf0f..0fc4f1dd41a 100644
--- a/lib/gitlab/cycle_analytics/issue_helper.rb
+++ b/lib/gitlab/cycle_analytics/issue_helper.rb
@@ -5,8 +5,11 @@ module Gitlab
module IssueHelper
def stage_query(project_ids)
query = issue_table.join(issue_metrics_table).on(issue_table[:id].eq(issue_metrics_table[:issue_id]))
+ .join(projects_table).on(issue_table[:project_id].eq(projects_table[:id]))
+ .join(routes_table).on(projects_table[:namespace_id].eq(routes_table[:source_id]))
.project(issue_table[:project_id].as("project_id"))
.where(issue_table[:project_id].in(project_ids))
+ .where(routes_table[:source_type].eq('Namespace'))
.where(issue_table[:created_at].gteq(options[:from]))
.where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
diff --git a/lib/gitlab/cycle_analytics/metrics_tables.rb b/lib/gitlab/cycle_analytics/metrics_tables.rb
index 3e0302d308d..015f7bfde24 100644
--- a/lib/gitlab/cycle_analytics/metrics_tables.rb
+++ b/lib/gitlab/cycle_analytics/metrics_tables.rb
@@ -35,6 +35,14 @@ module Gitlab
User.arel_table
end
+ def projects_table
+ Project.arel_table
+ end
+
+ def routes_table
+ Route.arel_table
+ end
+
def build_table
::CommitStatus.arel_table
end
diff --git a/lib/gitlab/cycle_analytics/permissions.rb b/lib/gitlab/cycle_analytics/permissions.rb
index 03ba98b4dfb..55214e6b896 100644
--- a/lib/gitlab/cycle_analytics/permissions.rb
+++ b/lib/gitlab/cycle_analytics/permissions.rb
@@ -23,7 +23,7 @@ module Gitlab
end
def get
- ::CycleAnalytics::Base::STAGES.each do |stage|
+ ::CycleAnalytics::LevelBase::STAGES.each do |stage|
@stage_permission_hash[stage] = authorized_stage?(stage)
end
diff --git a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
index 49a6b099f34..77cc358daa9 100644
--- a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
@@ -10,7 +10,9 @@ module Gitlab
issue_table[:iid],
issue_table[:id],
issue_table[:created_at],
- issue_table[:author_id]]
+ issue_table[:author_id],
+ projects_table[:name],
+ routes_table[:path]]
super(*args)
end
@@ -18,7 +20,7 @@ module Gitlab
private
def serialize(event)
- AnalyticsIssueSerializer.new(project: project).represent(event)
+ AnalyticsIssueSerializer.new(serialization_context).represent(event)
end
def allowed_ids_finder_class
diff --git a/lib/gitlab/cycle_analytics/plan_helper.rb b/lib/gitlab/cycle_analytics/plan_helper.rb
index ae578d45ad5..c3f742503a9 100644
--- a/lib/gitlab/cycle_analytics/plan_helper.rb
+++ b/lib/gitlab/cycle_analytics/plan_helper.rb
@@ -5,14 +5,21 @@ module Gitlab
module PlanHelper
def stage_query(project_ids)
query = issue_table.join(issue_metrics_table).on(issue_table[:id].eq(issue_metrics_table[:issue_id]))
+ .join(projects_table).on(issue_table[:project_id].eq(projects_table[:id]))
+ .join(routes_table).on(projects_table[:namespace_id].eq(routes_table[:source_id]))
.project(issue_table[:project_id].as("project_id"))
.where(issue_table[:project_id].in(project_ids))
- .where(issue_table[:created_at].gteq(options[:from]))
- .where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
- .where(issue_metrics_table[:first_mentioned_in_commit_at].not_eq(nil))
+ .where(routes_table[:source_type].eq('Namespace'))
+ query = add_conditions_to_query(query)
query
end
+
+ def add_conditions_to_query(query)
+ query.where(issue_table[:created_at].gteq(options[:from]))
+ .where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
+ .where(issue_metrics_table[:first_mentioned_in_commit_at].not_eq(nil))
+ end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/production_event_fetcher.rb b/lib/gitlab/cycle_analytics/production_event_fetcher.rb
index 949119d69a0..404b2460814 100644
--- a/lib/gitlab/cycle_analytics/production_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/production_event_fetcher.rb
@@ -10,7 +10,9 @@ module Gitlab
issue_table[:iid],
issue_table[:id],
issue_table[:created_at],
- issue_table[:author_id]]
+ issue_table[:author_id],
+ projects_table[:name],
+ routes_table[:path]]
super(*args)
end
@@ -18,7 +20,7 @@ module Gitlab
private
def serialize(event)
- AnalyticsIssueSerializer.new(project: project).represent(event)
+ AnalyticsIssueSerializer.new(serialization_context).represent(event)
end
def allowed_ids_finder_class
diff --git a/lib/gitlab/cycle_analytics/review_event_fetcher.rb b/lib/gitlab/cycle_analytics/review_event_fetcher.rb
index d31736e755d..6acd12517fa 100644
--- a/lib/gitlab/cycle_analytics/review_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/review_event_fetcher.rb
@@ -11,7 +11,9 @@ module Gitlab
mr_table[:id],
mr_table[:created_at],
mr_table[:state],
- mr_table[:author_id]]
+ mr_table[:author_id],
+ projects_table[:name],
+ routes_table[:path]]
super(*args)
end
@@ -19,7 +21,7 @@ module Gitlab
private
def serialize(event)
- AnalyticsMergeRequestSerializer.new(project: project).represent(event)
+ AnalyticsMergeRequestSerializer.new(serialization_context).represent(event)
end
def allowed_ids_finder_class
diff --git a/lib/gitlab/cycle_analytics/summary/group/base.rb b/lib/gitlab/cycle_analytics/summary/group/base.rb
new file mode 100644
index 00000000000..7f18b61d309
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/summary/group/base.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module CycleAnalytics
+ module Summary
+ module Group
+ class Base
+ def initialize(group:, from:)
+ @group = group
+ @from = from
+ end
+
+ def title
+ raise NotImplementedError.new("Expected #{self.name} to implement title")
+ end
+
+ def value
+ raise NotImplementedError.new("Expected #{self.name} to implement value")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cycle_analytics/summary/group/deploy.rb b/lib/gitlab/cycle_analytics/summary/group/deploy.rb
new file mode 100644
index 00000000000..d8fcd8f2ce4
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/summary/group/deploy.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module CycleAnalytics
+ module Summary
+ module Group
+ class Deploy < Group::Base
+ def title
+ n_('Deploy', 'Deploys', value)
+ end
+
+ def value
+ @value ||= Deployment.joins(:project)
+ .where(projects: { id: projects })
+ .where("deployments.created_at > ?", @from)
+ .success
+ .count
+ end
+
+ private
+
+ def projects
+ Project.inside_path(@group.full_path).ids
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cycle_analytics/summary/group/issue.rb b/lib/gitlab/cycle_analytics/summary/group/issue.rb
new file mode 100644
index 00000000000..70073e6d843
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/summary/group/issue.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module CycleAnalytics
+ module Summary
+ module Group
+ class Issue < Group::Base
+ def initialize(group:, from:, current_user:)
+ @group = group
+ @from = from
+ @current_user = current_user
+ end
+
+ def title
+ n_('New Issue', 'New Issues', value)
+ end
+
+ def value
+ @value ||= IssuesFinder.new(@current_user, group_id: @group.id, include_subgroups: true, created_after: @from).execute.count
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
index 8b07da11c5d..b7a64adc2ff 100644
--- a/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
@@ -9,12 +9,12 @@ describe Gitlab::CycleAnalytics::BaseEventFetcher do
let(:options) do
{ start_time_attrs: start_time_attrs,
end_time_attrs: end_time_attrs,
- from: 30.days.ago }
+ from: 30.days.ago,
+ project: project }
end
subject do
- described_class.new(project: project,
- stage: :issue,
+ described_class.new(stage: :issue,
options: options).fetch
end
diff --git a/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
index c738cc49c1f..933f3c7896e 100644
--- a/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
@@ -5,40 +5,114 @@ describe Gitlab::CycleAnalytics::CodeStage do
let(:stage_name) { :code }
let(:project) { create(:project) }
- let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
- let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let!(:mr_1) { create(:merge_request, source_project: project, created_at: 15.minutes.ago) }
- let!(:mr_2) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'A') }
- let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
- let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+ let(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
+ let(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let(:mr_1) { create(:merge_request, source_project: project, created_at: 15.minutes.ago) }
+ let(:mr_2) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'A') }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
before do
issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 45.minutes.ago)
issue_2.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
issue_3.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
+ create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B')
create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1)
create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2)
end
it_behaves_like 'base stage'
- describe '#median' do
+ describe '#project_median' do
around do |example|
Timecop.freeze { example.run }
end
it 'counts median from issues with metrics' do
- expect(stage.median).to eq(ISSUES_MEDIAN)
+ expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
end
describe '#events' do
+ subject { stage.events }
+
it 'exposes merge requests that closes issues' do
- result = stage.events
+ expect(subject.count).to eq(2)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(mr_1.title, mr_2.title)
+ end
+ end
+
+ context 'when group is given' do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project_2) { create(:project, group: group) }
+ let(:project_3) { create(:project, group: group) }
+ let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
+ let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
+ let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
+ let(:mr_2_1) { create(:merge_request, source_project: project_2, created_at: 15.minutes.ago) }
+ let(:mr_2_2) { create(:merge_request, source_project: project_3, created_at: 10.minutes.ago, source_branch: 'A') }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
+
+ before do
+ group.add_owner(user)
+ issue_2_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 45.minutes.ago)
+ issue_2_2.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
+ issue_2_3.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
+ create(:merge_requests_closing_issues, merge_request: mr_2_1, issue: issue_2_1)
+ create(:merge_requests_closing_issues, merge_request: mr_2_2, issue: issue_2_2)
+ end
+
+ describe '#group_median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.group_median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ subject { stage.events }
+
+ it 'exposes merge requests that close issues' do
+ expect(subject.count).to eq(2)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(mr_2_1.title, mr_2_2.title)
+ end
+ end
+
+ context 'when subgroup is given' do
+ let(:subgroup) { create(:group, parent: group) }
+ let(:project_4) { create(:project, group: subgroup) }
+ let(:project_5) { create(:project, group: subgroup) }
+ let(:issue_3_1) { create(:issue, project: project_4, created_at: 90.minutes.ago) }
+ let(:issue_3_2) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
+ let(:issue_3_3) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
+ let(:mr_3_1) { create(:merge_request, source_project: project_4, created_at: 15.minutes.ago) }
+ let(:mr_3_2) { create(:merge_request, source_project: project_5, created_at: 10.minutes.ago, source_branch: 'A') }
+
+ before do
+ issue_3_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 45.minutes.ago)
+ issue_3_2.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
+ issue_3_3.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
+ create(:merge_requests_closing_issues, merge_request: mr_3_1, issue: issue_3_1)
+ create(:merge_requests_closing_issues, merge_request: mr_3_2, issue: issue_3_2)
+ end
+
+ describe '#events' do
+ subject { stage.events }
+
+ it 'exposes merge requests that close issues' do
+ expect(subject.count).to eq(4)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(mr_2_1.title, mr_2_2.title, mr_3_1.title, mr_3_2.title)
+ end
- expect(result.count).to eq(2)
- expect(result.map { |event| event[:title] }).to contain_exactly(mr_1.title, mr_2.title)
+ it 'exposes merge requests that close issues with full path for subgroup' do
+ expect(subject.count).to eq(4)
+ expect(subject.find { |event| event[:title] == mr_3_1.title }[:url]).to include("#{subgroup.full_path}")
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/cycle_analytics/group_stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/group_stage_summary_spec.rb
new file mode 100644
index 00000000000..eea4f33ccb8
--- /dev/null
+++ b/spec/lib/gitlab/cycle_analytics/group_stage_summary_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::CycleAnalytics::GroupStageSummary do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :repository, namespace: group) }
+ let(:project_2) { create(:project, :repository, namespace: group) }
+ let(:from) { 1.day.ago }
+ let(:user) { create(:user, :admin) }
+
+ subject { described_class.new(group, from: Time.now, current_user: user).data }
+
+ describe "#new_issues" do
+ context 'with from date' do
+ before do
+ Timecop.freeze(5.days.ago) { create(:issue, project: project) }
+ Timecop.freeze(5.days.ago) { create(:issue, project: project_2) }
+ Timecop.freeze(5.days.from_now) { create(:issue, project: project) }
+ Timecop.freeze(5.days.from_now) { create(:issue, project: project_2) }
+ end
+
+ it "finds the number of issues created after it" do
+ expect(subject.first[:value]).to eq(2)
+ end
+
+ context 'with subgroups' do
+ before do
+ Timecop.freeze(5.days.from_now) { create(:issue, project: create(:project, namespace: create(:group, parent: group))) }
+ end
+
+ it "finds issues from them" do
+ expect(subject.first[:value]).to eq(3)
+ end
+ end
+ end
+
+ context 'with other projects' do
+ before do
+ Timecop.freeze(5.days.from_now) { create(:issue, project: create(:project, namespace: create(:group))) }
+ Timecop.freeze(5.days.from_now) { create(:issue, project: project) }
+ Timecop.freeze(5.days.from_now) { create(:issue, project: project_2) }
+ end
+
+ it "doesn't find issues from them" do
+ expect(subject.first[:value]).to eq(2)
+ end
+ end
+ end
+
+ describe "#deploys" do
+ context 'with from date' do
+ before do
+ Timecop.freeze(5.days.ago) { create(:deployment, :success, project: project) }
+ Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project) }
+ Timecop.freeze(5.days.ago) { create(:deployment, :success, project: project_2) }
+ Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project_2) }
+ end
+
+ it "finds the number of deploys made created after it" do
+ expect(subject.second[:value]).to eq(2)
+ end
+
+ context 'with subgroups' do
+ before do
+ Timecop.freeze(5.days.from_now) do
+ create(:deployment, :success, project: create(:project, :repository, namespace: create(:group, parent: group)))
+ end
+ end
+
+ it "finds deploys from them" do
+ expect(subject.second[:value]).to eq(3)
+ end
+ end
+ end
+
+ context 'with other projects' do
+ before do
+ Timecop.freeze(5.days.from_now) do
+ create(:deployment, :success, project: create(:project, :repository, namespace: create(:group)))
+ end
+ end
+
+ it "doesn't find deploys from them" do
+ expect(subject.second[:value]).to eq(0)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
index 3b6af9cbaed..ffd0b84cb57 100644
--- a/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
@@ -4,11 +4,11 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec'
describe Gitlab::CycleAnalytics::IssueStage do
let(:stage_name) { :issue }
let(:project) { create(:project) }
- let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
- let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let!(:issue_3) { create(:issue, project: project, created_at: 30.minutes.ago) }
+ let(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
+ let(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let(:issue_3) { create(:issue, project: project, created_at: 30.minutes.ago) }
let!(:issue_without_milestone) { create(:issue, project: project, created_at: 1.minute.ago) }
- let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
before do
issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago )
@@ -24,7 +24,7 @@ describe Gitlab::CycleAnalytics::IssueStage do
end
it 'counts median from issues with metrics' do
- expect(stage.median).to eq(ISSUES_MEDIAN)
+ expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
end
@@ -36,4 +36,67 @@ describe Gitlab::CycleAnalytics::IssueStage do
expect(result.map { |event| event[:title] }).to contain_exactly(issue_1.title, issue_2.title, issue_3.title)
end
end
+ context 'when group is given' do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project_2) { create(:project, group: group) }
+ let(:project_3) { create(:project, group: group) }
+ let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
+ let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
+ let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
+
+ before do
+ group.add_owner(user)
+ issue_2_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago)
+ issue_2_2.metrics.update!(first_added_to_board_at: 30.minutes.ago)
+ end
+
+ describe '#group_median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.group_median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ subject { stage.events }
+
+ it 'exposes merge requests that close issues' do
+ expect(subject.count).to eq(2)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(issue_2_1.title, issue_2_2.title)
+ end
+ end
+
+ context 'when subgroup is given' do
+ let(:subgroup) { create(:group, parent: group) }
+ let(:project_4) { create(:project, group: subgroup) }
+ let(:project_5) { create(:project, group: subgroup) }
+ let(:issue_3_1) { create(:issue, project: project_4, created_at: 90.minutes.ago) }
+ let(:issue_3_2) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
+ let(:issue_3_3) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
+
+ before do
+ issue_3_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago)
+ issue_3_2.metrics.update!(first_added_to_board_at: 30.minutes.ago)
+ end
+
+ describe '#events' do
+ subject { stage.events }
+
+ it 'exposes merge requests that close issues' do
+ expect(subject.count).to eq(4)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(issue_2_1.title, issue_2_2.title, issue_3_1.title, issue_3_2.title)
+ end
+
+ it 'exposes merge requests that close issues with full path for subgroup' do
+ expect(subject.count).to eq(4)
+ expect(subject.find { |event| event[:title] == issue_3_1.title }[:url]).to include("#{subgroup.full_path}")
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
index 506a8160412..3cd1320ca9c 100644
--- a/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
@@ -8,7 +8,7 @@ describe Gitlab::CycleAnalytics::PlanStage do
let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
let!(:issue_3) { create(:issue, project: project, created_at: 30.minutes.ago) }
let!(:issue_without_milestone) { create(:issue, project: project, created_at: 1.minute.ago) }
- let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
before do
issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 10.minutes.ago)
@@ -18,22 +18,88 @@ describe Gitlab::CycleAnalytics::PlanStage do
it_behaves_like 'base stage'
- describe '#median' do
+ describe '#project_median' do
around do |example|
Timecop.freeze { example.run }
end
it 'counts median from issues with metrics' do
- expect(stage.median).to eq(ISSUES_MEDIAN)
+ expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
end
describe '#events' do
+ subject { stage.events }
+
it 'exposes issues with metrics' do
- result = stage.events
+ expect(subject.count).to eq(2)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(issue_1.title, issue_2.title)
+ end
+ end
+
+ context 'when group is given' do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project_2) { create(:project, group: group) }
+ let(:project_3) { create(:project, group: group) }
+ let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
+ let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
+ let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
+
+ before do
+ group.add_owner(user)
+ issue_2_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 10.minutes.ago)
+ issue_2_2.metrics.update!(first_added_to_board_at: 30.minutes.ago, first_mentioned_in_commit_at: 20.minutes.ago)
+ issue_2_3.metrics.update!(first_added_to_board_at: 15.minutes.ago)
+ end
+
+ describe '#group_median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.group_median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ subject { stage.events }
+
+ it 'exposes merge requests that close issues' do
+ expect(subject.count).to eq(2)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(issue_2_1.title, issue_2_2.title)
+ end
+ end
+
+ context 'when subgroup is given' do
+ let(:subgroup) { create(:group, parent: group) }
+ let(:project_4) { create(:project, group: subgroup) }
+ let(:project_5) { create(:project, group: subgroup) }
+ let(:issue_3_1) { create(:issue, project: project_4, created_at: 90.minutes.ago) }
+ let(:issue_3_2) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
+ let(:issue_3_3) { create(:issue, project: project_5, created_at: 60.minutes.ago) }
+
+ before do
+ issue_3_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 10.minutes.ago)
+ issue_3_2.metrics.update!(first_added_to_board_at: 30.minutes.ago, first_mentioned_in_commit_at: 20.minutes.ago)
+ issue_3_3.metrics.update!(first_added_to_board_at: 15.minutes.ago)
+ end
+
+ describe '#events' do
+ subject { stage.events }
+
+ it 'exposes merge requests that close issues' do
+ expect(subject.count).to eq(4)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(issue_2_1.title, issue_2_2.title, issue_3_1.title, issue_3_2.title)
+ end
- expect(result.count).to eq(2)
- expect(result.map { |event| event[:title] }).to contain_exactly(issue_1.title, issue_2.title)
+ it 'exposes merge requests that close issues with full path for subgroup' do
+ expect(subject.count).to eq(4)
+ expect(subject.find { |event| event[:title] == issue_3_1.title }[:url]).to include("#{subgroup.full_path}")
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
index f072a9644e8..6d14973c711 100644
--- a/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
@@ -4,14 +4,14 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec'
describe Gitlab::CycleAnalytics::ReviewStage do
let(:stage_name) { :review }
let(:project) { create(:project) }
- let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
- let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let!(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) }
- let!(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') }
- let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
+ let(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
+ let(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) }
+ let(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') }
+ let(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
let!(:mr_4) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'C') }
- let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
before do
mr_1.metrics.update!(merged_at: 30.minutes.ago)
@@ -24,22 +24,66 @@ describe Gitlab::CycleAnalytics::ReviewStage do
it_behaves_like 'base stage'
- describe '#median' do
+ describe '#project_median' do
around do |example|
Timecop.freeze { example.run }
end
it 'counts median from issues with metrics' do
- expect(stage.median).to eq(ISSUES_MEDIAN)
+ expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
end
describe '#events' do
+ subject { stage.events }
+
it 'exposes merge requests that close issues' do
- result = stage.events
+ expect(subject.count).to eq(2)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(mr_1.title, mr_2.title)
+ end
+ end
+
+ context 'when group is given' do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project_2) { create(:project, group: group) }
+ let(:project_3) { create(:project, group: group) }
+ let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
+ let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
+ let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
+ let(:mr_2_1) { create(:merge_request, :closed, source_project: project_2, created_at: 60.minutes.ago) }
+ let(:mr_2_2) { create(:merge_request, :closed, source_project: project_3, created_at: 40.minutes.ago, source_branch: 'A') }
+ let(:mr_2_3) { create(:merge_request, source_project: project_2, created_at: 10.minutes.ago, source_branch: 'B') }
+ let!(:mr_2_4) { create(:merge_request, source_project: project_3, created_at: 10.minutes.ago, source_branch: 'C') }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
+
+ before do
+ group.add_owner(user)
+ mr_2_1.metrics.update!(merged_at: 30.minutes.ago)
+ mr_2_2.metrics.update!(merged_at: 10.minutes.ago)
+
+ create(:merge_requests_closing_issues, merge_request: mr_2_1, issue: issue_2_1)
+ create(:merge_requests_closing_issues, merge_request: mr_2_2, issue: issue_2_2)
+ create(:merge_requests_closing_issues, merge_request: mr_2_3, issue: issue_2_3)
+ end
+
+ describe '#group_median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.group_median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ subject { stage.events }
- expect(result.count).to eq(2)
- expect(result.map { |event| event[:title] }).to contain_exactly(mr_1.title, mr_2.title)
+ it 'exposes merge requests that close issues' do
+ expect(subject.count).to eq(2)
+ expect(subject.map { |event| event[:title] }).to contain_exactly(mr_2_1.title, mr_2_2.title)
+ end
end
end
end
diff --git a/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb b/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb
index c22d27f60d6..b001a46001e 100644
--- a/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
shared_examples 'default query config' do
let(:project) { create(:project) }
- let(:event) { described_class.new(project: project, stage: stage_name, options: { from: 1.day.ago }) }
+ let(:event) { described_class.new(stage: stage_name, options: { from: 1.day.ago, project: project }) }
it 'has the stage attribute' do
expect(event.stage).not_to be_nil
diff --git a/spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
index 1a4b572cc11..c146146723f 100644
--- a/spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
@@ -3,10 +3,10 @@ require 'spec_helper'
shared_examples 'base stage' do
ISSUES_MEDIAN = 30.minutes.to_i
- let(:stage) { described_class.new(project: double, options: {}) }
+ let(:stage) { described_class.new(options: { project: double }) }
before do
- allow(stage).to receive(:median).and_return(1.12)
+ allow(stage).to receive(:project_median).and_return(1.12)
allow_any_instance_of(Gitlab::CycleAnalytics::BaseEventFetcher).to receive(:event_result).and_return({})
end
diff --git a/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
index 17d5fbb9733..9ca12cc448c 100644
--- a/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
@@ -5,16 +5,16 @@ describe Gitlab::CycleAnalytics::StagingStage do
let(:stage_name) { :staging }
let(:project) { create(:project) }
- let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
- let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
- let!(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) }
- let!(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') }
- let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
+ let(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
+ let(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) }
+ let(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') }
+ let(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
let(:build_1) { create(:ci_build, project: project) }
let(:build_2) { create(:ci_build, project: project) }
- let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
before do
mr_1.metrics.update!(merged_at: 80.minutes.ago, first_deployed_to_production_at: 50.minutes.ago, pipeline_id: build_1.commit_id)
@@ -28,22 +28,68 @@ describe Gitlab::CycleAnalytics::StagingStage do
it_behaves_like 'base stage'
- describe '#median' do
+ describe '#project_median' do
around do |example|
Timecop.freeze { example.run }
end
it 'counts median from issues with metrics' do
- expect(stage.median).to eq(ISSUES_MEDIAN)
+ expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
end
describe '#events' do
+ subject { stage.events }
+
it 'exposes builds connected to merge request' do
- result = stage.events
+ expect(subject.count).to eq(2)
+ expect(subject.map { |event| event[:name] }).to contain_exactly(build_1.name, build_2.name)
+ end
+ end
+
+ context 'when group is given' do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project_2) { create(:project, group: group) }
+ let(:project_3) { create(:project, group: group) }
+ let(:issue_2_1) { create(:issue, project: project_2, created_at: 90.minutes.ago) }
+ let(:issue_2_2) { create(:issue, project: project_3, created_at: 60.minutes.ago) }
+ let(:issue_2_3) { create(:issue, project: project_2, created_at: 60.minutes.ago) }
+ let(:mr_1) { create(:merge_request, :closed, source_project: project_2, created_at: 60.minutes.ago) }
+ let(:mr_2) { create(:merge_request, :closed, source_project: project_3, created_at: 40.minutes.ago, source_branch: 'A') }
+ let(:mr_3) { create(:merge_request, source_project: project_2, created_at: 10.minutes.ago, source_branch: 'B') }
+ let(:build_1) { create(:ci_build, project: project_2) }
+ let(:build_2) { create(:ci_build, project: project_3) }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: user, group: group }) }
+
+ before do
+ group.add_owner(user)
+ mr_1.metrics.update!(merged_at: 80.minutes.ago, first_deployed_to_production_at: 50.minutes.ago, pipeline_id: build_1.commit_id)
+ mr_2.metrics.update!(merged_at: 60.minutes.ago, first_deployed_to_production_at: 30.minutes.ago, pipeline_id: build_2.commit_id)
+ mr_3.metrics.update!(merged_at: 10.minutes.ago, first_deployed_to_production_at: 3.days.ago, pipeline_id: create(:ci_build, project: project_2).commit_id)
+
+ create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_2_1)
+ create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2_2)
+ create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_2_3)
+ end
+
+ describe '#group_median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.group_median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ subject { stage.events }
- expect(result.count).to eq(2)
- expect(result.map { |event| event[:name] }).to contain_exactly(build_1.name, build_2.name)
+ it 'exposes merge requests that close issues' do
+ expect(subject.count).to eq(2)
+ expect(subject.map { |event| event[:name] }).to contain_exactly(build_1.name, build_2.name)
+ end
end
end
end
diff --git a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
index 8633a63849f..41028c44a00 100644
--- a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
@@ -4,7 +4,7 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec'
describe Gitlab::CycleAnalytics::TestStage do
let(:stage_name) { :test }
let(:project) { create(:project) }
- let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+ let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
it_behaves_like 'base stage'
@@ -36,7 +36,7 @@ describe Gitlab::CycleAnalytics::TestStage do
end
it 'counts median from issues with metrics' do
- expect(stage.median).to eq(ISSUES_MEDIAN)
+ expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
end
end
diff --git a/spec/lib/gitlab/cycle_analytics/usage_data_spec.rb b/spec/lib/gitlab/cycle_analytics/usage_data_spec.rb
index 8122e85a981..ad61bdeace7 100644
--- a/spec/lib/gitlab/cycle_analytics/usage_data_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/usage_data_spec.rb
@@ -34,7 +34,7 @@ describe Gitlab::CycleAnalytics::UsageData do
expect(result).to have_key(:avg_cycle_analytics)
- CycleAnalytics::Base::STAGES.each do |stage|
+ CycleAnalytics::LevelBase::STAGES.each do |stage|
expect(result[:avg_cycle_analytics]).to have_key(stage)
stage_values = result[:avg_cycle_analytics][stage]
diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb
index db6e70973ae..808659552ff 100644
--- a/spec/models/cycle_analytics/code_spec.rb
+++ b/spec/models/cycle_analytics/code_spec.rb
@@ -38,7 +38,7 @@ describe 'CycleAnalytics#code' do
merge_merge_requests_closing_issue(user, project, issue)
deploy_master(user, project)
- expect(subject[:code].median).to be_nil
+ expect(subject[:code].project_median).to be_nil
end
end
end
@@ -68,7 +68,7 @@ describe 'CycleAnalytics#code' do
merge_merge_requests_closing_issue(user, project, issue)
- expect(subject[:code].median).to be_nil
+ expect(subject[:code].project_median).to be_nil
end
end
end
diff --git a/spec/models/cycle_analytics/group_level_spec.rb b/spec/models/cycle_analytics/group_level_spec.rb
new file mode 100644
index 00000000000..154c1b9c0f8
--- /dev/null
+++ b/spec/models/cycle_analytics/group_level_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe CycleAnalytics::GroupLevel do
+ let(:group) { create(:group)}
+ let(:project) { create(:project, :repository, namespace: group) }
+ let(:from_date) { 10.days.ago }
+ let(:user) { create(:user, :admin) }
+ let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
+ let(:milestone) { create(:milestone, project: project) }
+ let(:mr) { create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}") }
+ let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha, head_pipeline_of: mr) }
+
+ subject { described_class.new(group: group, options: { from: from_date, current_user: user }) }
+
+ describe '#permissions' do
+ it 'returns true for all stages' do
+ expect(subject.permissions.values.uniq).to eq([true])
+ end
+ end
+
+ describe '#stats' do
+ before do
+ allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue])
+
+ create_cycle(user, project, issue, mr, milestone, pipeline)
+ deploy_master(user, project)
+ end
+
+ it 'returns medians for each stage for a specific group' do
+ expect(subject.no_stats?).to eq(false)
+ end
+ end
+
+ describe '#summary' do
+ before do
+ create_cycle(user, project, issue, mr, milestone, pipeline)
+ deploy_master(user, project)
+ end
+
+ it 'returns medians for each stage for a specific group' do
+ expect(subject.summary.map { |summary| summary[:value] }).to contain_exactly(1, 1)
+ end
+ end
+end
diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb
index 4ccbdf29df6..8cdf83b1292 100644
--- a/spec/models/cycle_analytics/issue_spec.rb
+++ b/spec/models/cycle_analytics/issue_spec.rb
@@ -43,7 +43,7 @@ describe 'CycleAnalytics#issue' do
create_merge_request_closing_issue(user, project, issue)
merge_merge_requests_closing_issue(user, project, issue)
- expect(subject[:issue].median).to be_nil
+ expect(subject[:issue].project_median).to be_nil
end
end
end
diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb
index c99c38e9cf3..28ad9bd194d 100644
--- a/spec/models/cycle_analytics/plan_spec.rb
+++ b/spec/models/cycle_analytics/plan_spec.rb
@@ -47,7 +47,7 @@ describe 'CycleAnalytics#plan' do
create_merge_request_closing_issue(user, project, issue, source_branch: branch_name)
merge_merge_requests_closing_issue(user, project, issue)
- expect(subject[:issue].median).to be_nil
+ expect(subject[:issue].project_median).to be_nil
end
end
end
diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb
index ddd199362d1..613c1786540 100644
--- a/spec/models/cycle_analytics/production_spec.rb
+++ b/spec/models/cycle_analytics/production_spec.rb
@@ -41,7 +41,7 @@ describe 'CycleAnalytics#production' do
MergeRequests::MergeService.new(project, user).execute(merge_request)
deploy_master(user, project)
- expect(subject[:production].median).to be_nil
+ expect(subject[:production].project_median).to be_nil
end
end
@@ -52,7 +52,7 @@ describe 'CycleAnalytics#production' do
MergeRequests::MergeService.new(project, user).execute(merge_request)
deploy_master(user, project, environment: 'staging')
- expect(subject[:production].median).to be_nil
+ expect(subject[:production].project_median).to be_nil
end
end
end
diff --git a/spec/models/cycle_analytics/project_level_spec.rb b/spec/models/cycle_analytics/project_level_spec.rb
index 77bd0bfeb9c..4de01b1c679 100644
--- a/spec/models/cycle_analytics/project_level_spec.rb
+++ b/spec/models/cycle_analytics/project_level_spec.rb
@@ -23,7 +23,7 @@ describe CycleAnalytics::ProjectLevel do
it 'returns every median for each stage for a specific project' do
values = described_class::STAGES.each_with_object({}) do |stage_name, hsh|
- hsh[stage_name] = subject[stage_name].median.presence
+ hsh[stage_name] = subject[stage_name].project_median.presence
end
expect(subject.all_medians_by_stage).to eq(values)
diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb
index 63c481ed465..ef88fd86340 100644
--- a/spec/models/cycle_analytics/review_spec.rb
+++ b/spec/models/cycle_analytics/review_spec.rb
@@ -28,7 +28,7 @@ describe 'CycleAnalytics#review' do
it "returns nil" do
MergeRequests::MergeService.new(project, user).execute(create(:merge_request))
- expect(subject[:review].median).to be_nil
+ expect(subject[:review].project_median).to be_nil
end
end
end
diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb
index c134b97553f..571792559d8 100644
--- a/spec/models/cycle_analytics/staging_spec.rb
+++ b/spec/models/cycle_analytics/staging_spec.rb
@@ -45,7 +45,7 @@ describe 'CycleAnalytics#staging' do
MergeRequests::MergeService.new(project, user).execute(merge_request)
deploy_master(user, project)
- expect(subject[:staging].median).to be_nil
+ expect(subject[:staging].project_median).to be_nil
end
end
@@ -56,7 +56,7 @@ describe 'CycleAnalytics#staging' do
MergeRequests::MergeService.new(project, user).execute(merge_request)
deploy_master(user, project, environment: 'staging')
- expect(subject[:staging].median).to be_nil
+ expect(subject[:staging].project_median).to be_nil
end
end
end
diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb
index a6ea73b2699..7b3001d2bd8 100644
--- a/spec/models/cycle_analytics/test_spec.rb
+++ b/spec/models/cycle_analytics/test_spec.rb
@@ -36,7 +36,7 @@ describe 'CycleAnalytics#test' do
merge_merge_requests_closing_issue(user, project, issue)
- expect(subject[:test].median).to be_nil
+ expect(subject[:test].project_median).to be_nil
end
end
@@ -47,7 +47,7 @@ describe 'CycleAnalytics#test' do
pipeline.run!
pipeline.succeed!
- expect(subject[:test].median).to be_nil
+ expect(subject[:test].project_median).to be_nil
end
end
@@ -62,7 +62,7 @@ describe 'CycleAnalytics#test' do
merge_merge_requests_closing_issue(user, project, issue)
- expect(subject[:test].median).to be_nil
+ expect(subject[:test].project_median).to be_nil
end
end
@@ -77,7 +77,7 @@ describe 'CycleAnalytics#test' do
merge_merge_requests_closing_issue(user, project, issue)
- expect(subject[:test].median).to be_nil
+ expect(subject[:test].project_median).to be_nil
end
end
end
diff --git a/spec/serializers/analytics_issue_entity_spec.rb b/spec/serializers/analytics_issue_entity_spec.rb
index 89588b4df2b..dd5e43a4b62 100644
--- a/spec/serializers/analytics_issue_entity_spec.rb
+++ b/spec/serializers/analytics_issue_entity_spec.rb
@@ -9,12 +9,14 @@ describe AnalyticsIssueEntity do
iid: "1",
id: "1",
created_at: "2016-11-12 15:04:02.948604",
- author: user
+ author: user,
+ name: project.name,
+ path: project.namespace
}
end
let(:project) { create(:project) }
- let(:request) { EntityRequest.new(project: project, entity: :merge_request) }
+ let(:request) { EntityRequest.new(entity: :merge_request) }
let(:entity) do
described_class.new(entity_hash, request: request, project: project)
diff --git a/spec/serializers/analytics_issue_serializer_spec.rb b/spec/serializers/analytics_issue_serializer_spec.rb
index 5befc28f4fa..c9ffe1c5dad 100644
--- a/spec/serializers/analytics_issue_serializer_spec.rb
+++ b/spec/serializers/analytics_issue_serializer_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe AnalyticsIssueSerializer do
subject do
described_class
- .new(project: project, entity: :merge_request)
+ .new(entity: :merge_request)
.represent(resource)
end
@@ -16,7 +16,9 @@ describe AnalyticsIssueSerializer do
iid: "1",
id: "1",
created_at: "2016-11-12 15:04:02.948604",
- author: user
+ author: user,
+ name: project.name,
+ path: project.namespace
}
end
diff --git a/spec/serializers/analytics_merge_request_serializer_spec.rb b/spec/serializers/analytics_merge_request_serializer_spec.rb
index 62067cc0ef2..123d7d795ce 100644
--- a/spec/serializers/analytics_merge_request_serializer_spec.rb
+++ b/spec/serializers/analytics_merge_request_serializer_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe AnalyticsMergeRequestSerializer do
subject do
described_class
- .new(project: project, entity: :merge_request)
+ .new(entity: :merge_request)
.represent(resource)
end
@@ -17,7 +17,9 @@ describe AnalyticsMergeRequestSerializer do
id: "1",
state: 'open',
created_at: "2016-11-12 15:04:02.948604",
- author: user
+ author: user,
+ name: project.name,
+ path: project.namespace
}
end
diff --git a/spec/serializers/analytics_stage_serializer_spec.rb b/spec/serializers/analytics_stage_serializer_spec.rb
index 5b05c2f2ef3..86a796a2d94 100644
--- a/spec/serializers/analytics_stage_serializer_spec.rb
+++ b/spec/serializers/analytics_stage_serializer_spec.rb
@@ -6,11 +6,11 @@ describe AnalyticsStageSerializer do
end
let(:resource) do
- Gitlab::CycleAnalytics::CodeStage.new(project: double, options: {})
+ Gitlab::CycleAnalytics::CodeStage.new(options: { project: double })
end
before do
- allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:median).and_return(1.12)
+ allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:project_median).and_return(1.12)
allow_any_instance_of(Gitlab::CycleAnalytics::BaseEventFetcher).to receive(:event_result).and_return({})
end
@@ -24,7 +24,7 @@ describe AnalyticsStageSerializer do
context 'when median is equal 0' do
before do
- allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:median).and_return(0)
+ allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:project_median).and_return(0)
end
it 'sets the value to nil' do
@@ -34,7 +34,7 @@ describe AnalyticsStageSerializer do
context 'when median is below 1' do
before do
- allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:median).and_return(0.12)
+ allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:project_median).and_return(0.12)
end
it 'sets the value to equal to median' do
@@ -44,7 +44,7 @@ describe AnalyticsStageSerializer do
context 'when median is above 1' do
before do
- allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:median).and_return(60.12)
+ allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:project_median).and_return(60.12)
end
it 'sets the value to equal to median' do
diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb
index 19b32c84d81..be1c2bc3046 100644
--- a/spec/support/cycle_analytics_helpers/test_generation.rb
+++ b/spec/support/cycle_analytics_helpers/test_generation.rb
@@ -50,7 +50,7 @@ module CycleAnalyticsHelpers
end
median_time_difference = time_differences.sort[2]
- expect(subject[phase].median).to be_within(5).of(median_time_difference)
+ expect(subject[phase].project_median).to be_within(5).of(median_time_difference)
end
context "when the data belongs to another project" do
@@ -80,7 +80,7 @@ module CycleAnalyticsHelpers
# Turn off the stub before checking assertions
allow(self).to receive(:project).and_call_original
- expect(subject[phase].median).to be_nil
+ expect(subject[phase].project_median).to be_nil
end
end
@@ -103,7 +103,7 @@ module CycleAnalyticsHelpers
Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn
- expect(subject[phase].median).to be_nil
+ expect(subject[phase].project_median).to be_nil
end
end
end
@@ -121,7 +121,7 @@ module CycleAnalyticsHelpers
Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn
- expect(subject[phase].median).to be_nil
+ expect(subject[phase].project_median).to be_nil
end
end
end
@@ -138,7 +138,7 @@ module CycleAnalyticsHelpers
post_fn[self, data] if post_fn
- expect(subject[phase].median).to be_nil
+ expect(subject[phase].project_median).to be_nil
end
end
end
@@ -146,7 +146,7 @@ module CycleAnalyticsHelpers
context "when none of the start / end conditions are matched" do
it "returns nil" do
- expect(subject[phase].median).to be_nil
+ expect(subject[phase].project_median).to be_nil
end
end
end