summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMałgorzata Ksionek <mksionek@gitlab.com>2019-06-25 12:01:06 +0200
committerMałgorzata Ksionek <mksionek@gitlab.com>2019-07-03 16:45:52 +0200
commitbc6f4804aeba3abf190a4c4d7b23bc290938f396 (patch)
tree61223facdcabaa86aadca5e2320d4701c8fdc356
parent946080b5e97da0a94901ed4dcc95c2664c47c476 (diff)
downloadgitlab-ce-bc6f4804aeba3abf190a4c4d7b23bc290938f396.tar.gz
Add group level specs
-rw-r--r--app/models/cycle_analytics/group_level.rb10
-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.rb10
-rw-r--r--lib/gitlab/cycle_analytics/base_stage.rb16
-rw-r--r--spec/models/cycle_analytics/group_level_spec.rb35
6 files changed, 84 insertions, 8 deletions
diff --git a/app/models/cycle_analytics/group_level.rb b/app/models/cycle_analytics/group_level.rb
index a7853aadbb2..2e54346b01c 100644
--- a/app/models/cycle_analytics/group_level.rb
+++ b/app/models/cycle_analytics/group_level.rb
@@ -13,10 +13,18 @@ module CycleAnalytics
current_user: @options[:current_user]).data
end
- def permissions(user:)
+ def permissions(user: nil)
STAGES.each_with_object({}) do |stage, obj|
obj[stage] = true
end
end
+
+ private
+
+ def stats_per_stage
+ STAGES.map do |stage_name|
+ self[stage_name].as_json(serializer: GroupAnalyticsStageSerializer)
+ end
+ end
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..019a3086f68
--- /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|
+ # 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 44bf8775f42..f2a0a9c4b7b 100644
--- a/lib/gitlab/cycle_analytics/base_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/base_event_fetcher.rb
@@ -9,7 +9,7 @@ module Gitlab
MAX_EVENTS = 50
- def initialize(project:, stage:, options:)
+ def initialize(project: nil, stage:, options:)
@project = project
@stage = stage
@options = options
@@ -72,12 +72,16 @@ module Gitlab
end
def serialization_context
- namespace = @group ? @group.name : @project.namespace
+ namespace = group ? group.name : @project.namespace
{ namespace: namespace }
end
def projects
- [@project]
+ group ? group.projects : [@project]
+ end
+
+ def group
+ @group ||= @options.fetch(:group, nil)
end
end
end
diff --git a/lib/gitlab/cycle_analytics/base_stage.rb b/lib/gitlab/cycle_analytics/base_stage.rb
index 9be96780247..6e807b96906 100644
--- a/lib/gitlab/cycle_analytics/base_stage.rb
+++ b/lib/gitlab/cycle_analytics/base_stage.rb
@@ -5,7 +5,7 @@ module Gitlab
class BaseStage
include BaseQuery
- def initialize(project:, options:)
+ def initialize(project: nil, options:)
@project = project
@options = options
end
@@ -14,8 +14,8 @@ module Gitlab
event_fetcher.fetch
end
- def as_json
- AnalyticsStageSerializer.new.represent(self)
+ def as_json(serializer: AnalyticsStageSerializer)
+ serializer.new.represent(self)
end
def title
@@ -38,6 +38,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).
@@ -73,7 +77,11 @@ module Gitlab
end
def projects
- [@project]
+ group ? group.projects : [@project]
+ end
+
+ def group
+ @group ||= @options.fetch(:group, 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..4f0502970df
--- /dev/null
+++ b/spec/models/cycle_analytics/group_level_spec.rb
@@ -0,0 +1,35 @@
+# 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(project: nil, options: { from: from_date, group: group }) }
+
+ describe '#permissions' do
+ it 'returns permissions' 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
+end