refactor events facade so it uses separate classes and refactor query stuff
This commit is contained in:
parent
f9de157e70
commit
ed39d61d74
33 changed files with 930 additions and 677 deletions
|
@ -19,7 +19,7 @@ module Projects
|
|||
end
|
||||
|
||||
def test
|
||||
@options = { from: start_date(events_params), branch: events_params[:branch_name] }
|
||||
@options[:branch] = events_params[:branch_name]
|
||||
|
||||
render_events(events.test_events)
|
||||
end
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
class CycleAnalytics
|
||||
include Gitlab::CycleAnalytics::MetricsFetcher
|
||||
|
||||
def initialize(project, from:)
|
||||
@project = project
|
||||
@from = from
|
||||
@fetcher = Gitlab::CycleAnalytics::MetricsFetcher.new(project: project, from: from, branch: nil)
|
||||
end
|
||||
|
||||
def summary
|
||||
|
@ -11,45 +10,45 @@ class CycleAnalytics
|
|||
end
|
||||
|
||||
def issue
|
||||
calculate_metric(:issue,
|
||||
@fetcher.calculate_metric(:issue,
|
||||
Issue.arel_table[:created_at],
|
||||
[Issue::Metrics.arel_table[:first_associated_with_milestone_at],
|
||||
Issue::Metrics.arel_table[:first_added_to_board_at]])
|
||||
end
|
||||
|
||||
def plan
|
||||
calculate_metric(:plan,
|
||||
@fetcher.calculate_metric(:plan,
|
||||
[Issue::Metrics.arel_table[:first_associated_with_milestone_at],
|
||||
Issue::Metrics.arel_table[:first_added_to_board_at]],
|
||||
Issue::Metrics.arel_table[:first_mentioned_in_commit_at])
|
||||
end
|
||||
|
||||
def code
|
||||
calculate_metric(:code,
|
||||
@fetcher.calculate_metric(:code,
|
||||
Issue::Metrics.arel_table[:first_mentioned_in_commit_at],
|
||||
MergeRequest.arel_table[:created_at])
|
||||
end
|
||||
|
||||
def test
|
||||
calculate_metric(:test,
|
||||
@fetcher.calculate_metric(:test,
|
||||
MergeRequest::Metrics.arel_table[:latest_build_started_at],
|
||||
MergeRequest::Metrics.arel_table[:latest_build_finished_at])
|
||||
end
|
||||
|
||||
def review
|
||||
calculate_metric(:review,
|
||||
@fetcher.calculate_metric(:review,
|
||||
MergeRequest.arel_table[:created_at],
|
||||
MergeRequest::Metrics.arel_table[:merged_at])
|
||||
end
|
||||
|
||||
def staging
|
||||
calculate_metric(:staging,
|
||||
@fetcher.calculate_metric(:staging,
|
||||
MergeRequest::Metrics.arel_table[:merged_at],
|
||||
MergeRequest::Metrics.arel_table[:first_deployed_to_production_at])
|
||||
end
|
||||
|
||||
def production
|
||||
calculate_metric(:production,
|
||||
@fetcher.calculate_metric(:production,
|
||||
Issue.arel_table[:created_at],
|
||||
MergeRequest::Metrics.arel_table[:first_deployed_to_production_at])
|
||||
end
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class AnalyticsGenericSerializer < BaseSerializer
|
||||
entity AnalyticsGenericEntity
|
||||
|
||||
def represent(resource, opts = {})
|
||||
resource.symbolize_keys!
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
class AnalyticsGenericEntity < Grape::Entity
|
||||
class AnalyticsIssueEntity < Grape::Entity
|
||||
include RequestAwareEntity
|
||||
include EntityDateHelper
|
||||
|
||||
expose :title
|
||||
expose :state, if: ->(_instance, options) { options[:request].entity == :merge_request }
|
||||
expose :author, using: UserEntity
|
||||
|
||||
expose :iid do |object|
|
||||
|
@ -19,7 +18,7 @@ class AnalyticsGenericEntity < Grape::Entity
|
|||
end
|
||||
|
||||
expose :url do |object|
|
||||
url_to("namespace_project_#{request.entity}".to_sym, id: object[:iid].to_s)
|
||||
url_to(:namespace_project_issue, id: object[:iid].to_s)
|
||||
end
|
||||
|
||||
private
|
3
app/serializers/analytics_issue_serializer.rb
Normal file
3
app/serializers/analytics_issue_serializer.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class AnalyticsIssueSerializer < AnalyticsGenericSerializer
|
||||
entity AnalyticsIssueEntity
|
||||
end
|
7
app/serializers/analytics_merge_request_entity.rb
Normal file
7
app/serializers/analytics_merge_request_entity.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class AnalyticsMergeRequestEntity < AnalyticsIssueEntity
|
||||
expose :state
|
||||
|
||||
expose :url do |object|
|
||||
url_to(:namespace_project_merge_request, id: object[:iid].to_s)
|
||||
end
|
||||
end
|
3
app/serializers/analytics_merge_request_serializer.rb
Normal file
3
app/serializers/analytics_merge_request_serializer.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class AnalyticsMergeRequestSerializer < AnalyticsGenericSerializer
|
||||
entity AnalyticsMergeRequestEntity
|
||||
end
|
1202
db/schema.rb
1202
db/schema.rb
File diff suppressed because it is too large
Load diff
|
@ -1,17 +0,0 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class BaseConfig
|
||||
extend MetricsFetcher
|
||||
|
||||
class << self
|
||||
attr_reader :start_time_attrs, :end_time_attrs, :projections
|
||||
end
|
||||
|
||||
def self.order
|
||||
@order || @start_time_attrs
|
||||
end
|
||||
|
||||
def self.query(base_query); end
|
||||
end
|
||||
end
|
||||
end
|
27
lib/gitlab/cycle_analytics/base_event.rb
Normal file
27
lib/gitlab/cycle_analytics/base_event.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class BaseEvent
|
||||
extend MetricsTables
|
||||
|
||||
class << self
|
||||
attr_reader :stage, :start_time_attrs, :end_time_attrs, :projections
|
||||
|
||||
def order
|
||||
@order || @start_time_attrs
|
||||
end
|
||||
|
||||
def query(base_query); end
|
||||
|
||||
def fetch(query)
|
||||
query.execute(self).map { |event| serialize(event, query) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def serialize(event, query)
|
||||
raise NotImplementedError.new("Expected #{self.name} to implement serialize(event)")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class CodeConfig < BaseConfig
|
||||
class CodeEvent < BaseEvent
|
||||
@stage = :code
|
||||
@start_time_attrs = issue_metrics_table[:first_mentioned_in_commit_at]
|
||||
|
||||
@end_time_attrs = mr_table[:created_at]
|
||||
|
@ -13,6 +14,12 @@ module Gitlab
|
|||
mr_table[:author_id]]
|
||||
|
||||
@order = mr_table[:created_at]
|
||||
|
||||
def self.serialize(event, query)
|
||||
event['author'] = User.find(event.delete('author_id'))
|
||||
|
||||
AnalyticsMergeRequestSerializer.new(project: query.project).represent(event).as_json
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class ReviewConfig < BaseConfig
|
||||
class TestEvent < BaseEvent
|
||||
@start_time_attrs = mr_table[:created_at]
|
||||
|
||||
@end_time_attrs = mr_metrics_table[:merged_at]
|
|
@ -3,73 +3,35 @@ module Gitlab
|
|||
class Events
|
||||
def initialize(project:, options:)
|
||||
@project = project
|
||||
@fetcher = EventsFetcher.new(project: project, options: options)
|
||||
@query = EventsQuery.new(project: project, options: options)
|
||||
end
|
||||
|
||||
def issue_events
|
||||
@fetcher.fetch(stage: :issue).map { |event| serialize_event(event) }
|
||||
IssueEvent.fetch(@query)
|
||||
end
|
||||
|
||||
def plan_events
|
||||
@fetcher.fetch(stage: :plan).map do |event|
|
||||
st_commit = first_time_reference_commit(event.delete('commits'), event)
|
||||
|
||||
next unless st_commit
|
||||
|
||||
serialize_commit(event, st_commit)
|
||||
end
|
||||
PlanEvent.fetch(@query)
|
||||
end
|
||||
|
||||
def code_events
|
||||
@fetcher.fetch(stage: :code).map { |event| serialize_event(event, entity: :merge_request) }
|
||||
CodeEvent.fetch(@query)
|
||||
end
|
||||
|
||||
def test_events
|
||||
@fetcher.fetch(stage: :test).map { |event| serialize_build_event(event) }
|
||||
TestEvent.fetch(@query)
|
||||
end
|
||||
|
||||
def review_events
|
||||
@fetcher.fetch(stage: :review).map { |event| serialize_event(event, entity: :merge_request) }
|
||||
ReviewEvent.fetch(@query)
|
||||
end
|
||||
|
||||
def staging_events
|
||||
@fetcher.fetch(stage: :staging).map { |event| serialize_build_event(event) }
|
||||
StagingEvent.fetch(@query)
|
||||
end
|
||||
|
||||
def production_events
|
||||
@fetcher.fetch(stage: :production).map { |event| serialize_event(event) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def serialize_event(event, entity: :issue)
|
||||
event['author'] = User.find(event.delete('author_id'))
|
||||
|
||||
AnalyticsGenericSerializer.new(project: @project, entity: entity).represent(event).as_json
|
||||
end
|
||||
|
||||
def serialize_build_event(event)
|
||||
build = ::Ci::Build.find(event['id'])
|
||||
|
||||
AnalyticsBuildSerializer.new.represent(build).as_json
|
||||
end
|
||||
|
||||
def first_time_reference_commit(commits, event)
|
||||
YAML.load(commits).find do |commit|
|
||||
next unless commit[:committed_date] && event['first_mentioned_in_commit_at']
|
||||
|
||||
commit[:committed_date].to_i == DateTime.parse(event['first_mentioned_in_commit_at'].to_s).to_i
|
||||
end
|
||||
end
|
||||
|
||||
def serialize_commit(event, st_commit)
|
||||
commit = Commit.new(Gitlab::Git::Commit.new(st_commit), @project)
|
||||
|
||||
AnalyticsCommitSerializer.new(project: @project, total_time: event['total_time']).represent(commit).as_json
|
||||
end
|
||||
|
||||
def interval_in_words(diff)
|
||||
"#{distance_of_time_in_words(diff.to_f)} ago"
|
||||
ProductionEvent.fetch(@query)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,9 +6,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def fetch(stage:)
|
||||
@query.execute(stage) do |stage_class, base_query|
|
||||
stage_class.query(base_query)
|
||||
end
|
||||
@query.execute(stage)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class EventsQuery
|
||||
include MetricsFetcher
|
||||
attr_reader :project
|
||||
|
||||
def initialize(project:, options: {})
|
||||
@project = project
|
||||
@from = options[:from]
|
||||
@branch = options[:branch]
|
||||
@fetcher = Gitlab::CycleAnalytics::MetricsFetcher.new(project: project, from: @from, branch: @branch)
|
||||
end
|
||||
|
||||
def execute(stage, &block)
|
||||
@stage = stage
|
||||
query = build_query(&block)
|
||||
def execute(stage_class)
|
||||
@stage_class = stage_class
|
||||
|
||||
ActiveRecord::Base.connection.exec_query(query.to_sql)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_query
|
||||
base_query = base_query_for(@stage)
|
||||
diff_fn = subtract_datetimes_diff(base_query, stage_class.start_time_attrs, stage_class.end_time_attrs)
|
||||
def query
|
||||
base_query = @fetcher.base_query_for(@stage_class.stage)
|
||||
diff_fn = @fetcher.subtract_datetimes_diff(base_query, @stage_class.start_time_attrs, @stage_class.end_time_attrs)
|
||||
|
||||
yield(stage_class, base_query) if block_given?
|
||||
@stage_class.query(base_query)
|
||||
|
||||
base_query.project(extract_epoch(diff_fn).as('total_time'), *stage_class.projections).order(stage_class.order.desc)
|
||||
base_query.project(extract_epoch(diff_fn).as('total_time'), *@stage_class.projections).order(@stage_class.order.desc)
|
||||
end
|
||||
|
||||
def extract_epoch(arel_attribute)
|
||||
|
@ -32,10 +32,6 @@ module Gitlab
|
|||
|
||||
Arel.sql(%Q{EXTRACT(EPOCH FROM (#{arel_attribute.to_sql}))})
|
||||
end
|
||||
|
||||
def stage_class
|
||||
@stage_class ||= "Gitlab::CycleAnalytics::#{@stage.to_s.camelize}Config".constantize
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class IssueConfig < BaseConfig
|
||||
class IssueEvent < BaseEvent
|
||||
@stage = :issue
|
||||
@start_time_attrs = issue_table[:created_at]
|
||||
|
||||
@end_time_attrs = [issue_metrics_table[:first_associated_with_milestone_at],
|
||||
|
@ -11,6 +12,12 @@ module Gitlab
|
|||
issue_table[:id],
|
||||
issue_table[:created_at],
|
||||
issue_table[:author_id]]
|
||||
|
||||
def self.serialize(event, query)
|
||||
event['author'] = User.find(event.delete('author_id'))
|
||||
|
||||
AnalyticsIssueSerializer.new(project: query.project).represent(event).as_json
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,12 +1,18 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
module MetricsFetcher
|
||||
class MetricsFetcher
|
||||
include Gitlab::Database::Median
|
||||
include Gitlab::Database::DateTime
|
||||
include MetricsTables
|
||||
|
||||
DEPLOYMENT_METRIC_STAGES = %i[production staging]
|
||||
|
||||
private
|
||||
def initialize(project:, from:, branch:)
|
||||
@project = project
|
||||
@project = project
|
||||
@from = from
|
||||
@branch = branch
|
||||
end
|
||||
|
||||
def calculate_metric(name, start_time_attrs, end_time_attrs)
|
||||
cte_table = Arel::Table.new("cte_table_for_#{name}")
|
||||
|
@ -49,38 +55,6 @@ module Gitlab
|
|||
|
||||
query
|
||||
end
|
||||
|
||||
def mr_metrics_table
|
||||
MergeRequest::Metrics.arel_table
|
||||
end
|
||||
|
||||
def mr_table
|
||||
MergeRequest.arel_table
|
||||
end
|
||||
|
||||
def mr_diff_table
|
||||
MergeRequestDiff.arel_table
|
||||
end
|
||||
|
||||
def mr_closing_issues_table
|
||||
MergeRequestsClosingIssues.arel_table
|
||||
end
|
||||
|
||||
def issue_table
|
||||
Issue.arel_table
|
||||
end
|
||||
|
||||
def issue_metrics_table
|
||||
Issue::Metrics.arel_table
|
||||
end
|
||||
|
||||
def user_table
|
||||
User.arel_table
|
||||
end
|
||||
|
||||
def build_table
|
||||
::CommitStatus.arel_table
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
37
lib/gitlab/cycle_analytics/metrics_tables.rb
Normal file
37
lib/gitlab/cycle_analytics/metrics_tables.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
module MetricsTables
|
||||
def mr_metrics_table
|
||||
MergeRequest::Metrics.arel_table
|
||||
end
|
||||
|
||||
def mr_table
|
||||
MergeRequest.arel_table
|
||||
end
|
||||
|
||||
def mr_diff_table
|
||||
MergeRequestDiff.arel_table
|
||||
end
|
||||
|
||||
def mr_closing_issues_table
|
||||
MergeRequestsClosingIssues.arel_table
|
||||
end
|
||||
|
||||
def issue_table
|
||||
Issue.arel_table
|
||||
end
|
||||
|
||||
def issue_metrics_table
|
||||
Issue::Metrics.arel_table
|
||||
end
|
||||
|
||||
def user_table
|
||||
User.arel_table
|
||||
end
|
||||
|
||||
def build_table
|
||||
::CommitStatus.arel_table
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,17 +0,0 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class PlanConfig < BaseConfig
|
||||
@start_time_attrs = issue_metrics_table[:first_associated_with_milestone_at]
|
||||
|
||||
@end_time_attrs = [issue_metrics_table[:first_added_to_board_at],
|
||||
issue_metrics_table[:first_mentioned_in_commit_at]]
|
||||
|
||||
@projections = [mr_diff_table[:st_commits].as('commits'),
|
||||
issue_metrics_table[:first_mentioned_in_commit_at]]
|
||||
|
||||
def self.query(base_query)
|
||||
base_query.join(mr_diff_table).on(mr_diff_table[:merge_request_id].eq(mr_table[:id]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
44
lib/gitlab/cycle_analytics/plan_event.rb
Normal file
44
lib/gitlab/cycle_analytics/plan_event.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class PlanEvent < BaseEvent
|
||||
@stage = :plan
|
||||
@start_time_attrs = issue_metrics_table[:first_associated_with_milestone_at]
|
||||
|
||||
@end_time_attrs = [issue_metrics_table[:first_added_to_board_at],
|
||||
issue_metrics_table[:first_mentioned_in_commit_at]]
|
||||
|
||||
@projections = [mr_diff_table[:st_commits].as('commits'),
|
||||
issue_metrics_table[:first_mentioned_in_commit_at]]
|
||||
|
||||
class << self
|
||||
def query(base_query)
|
||||
base_query.join(mr_diff_table).on(mr_diff_table[:merge_request_id].eq(mr_table[:id]))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def serialize(event, query)
|
||||
st_commit = first_time_reference_commit(event.delete('commits'), event)
|
||||
|
||||
return unless st_commit
|
||||
|
||||
serialize_commit(event, st_commit, query)
|
||||
end
|
||||
|
||||
def first_time_reference_commit(commits, event)
|
||||
YAML.load(commits).find do |commit|
|
||||
next unless commit[:committed_date] && event['first_mentioned_in_commit_at']
|
||||
|
||||
commit[:committed_date].to_i == DateTime.parse(event['first_mentioned_in_commit_at'].to_s).to_i
|
||||
end
|
||||
end
|
||||
|
||||
def serialize_commit(event, st_commit, query)
|
||||
commit = Commit.new(Gitlab::Git::Commit.new(st_commit), @project)
|
||||
|
||||
AnalyticsCommitSerializer.new(project: query.project, total_time: event['total_time']).represent(commit).as_json
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class ProductionConfig < BaseConfig
|
||||
class ProductionEvent < BaseEvent
|
||||
@stage = :production
|
||||
@start_time_attrs = issue_table[:created_at]
|
||||
|
||||
@end_time_attrs = mr_metrics_table[:first_deployed_to_production_at]
|
||||
|
@ -10,6 +11,12 @@ module Gitlab
|
|||
issue_table[:id],
|
||||
issue_table[:created_at],
|
||||
issue_table[:author_id]]
|
||||
|
||||
def self.serialize(event, query)
|
||||
event['author'] = User.find(event.delete('author_id'))
|
||||
|
||||
AnalyticsIssueSerializer.new(project: query.project).represent(event).as_json
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
21
lib/gitlab/cycle_analytics/review_event.rb
Normal file
21
lib/gitlab/cycle_analytics/review_event.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class ReviewEvent < BaseEvent
|
||||
@stage = :review
|
||||
@start_time_attrs = mr_table[:created_at]
|
||||
@end_time_attrs = mr_metrics_table[:merged_at]
|
||||
@projections = [mr_table[:title],
|
||||
mr_table[:iid],
|
||||
mr_table[:id],
|
||||
mr_table[:created_at],
|
||||
mr_table[:state],
|
||||
mr_table[:author_id]]
|
||||
|
||||
def self.serialize(event, _query)
|
||||
event['author'] = User.find(event.delete('author_id'))
|
||||
|
||||
AnalyticsMergeRequestSerializer.new(project: query.project).represent(event).as_json
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class StagingConfig < BaseConfig
|
||||
class StagingEvent < BaseEvent
|
||||
@stage = :staging
|
||||
@start_time_attrs = mr_metrics_table[:merged_at]
|
||||
@end_time_attrs = mr_metrics_table[:first_deployed_to_production_at]
|
||||
@projections = [build_table[:id]]
|
||||
|
@ -9,6 +10,12 @@ module Gitlab
|
|||
def self.query(base_query)
|
||||
base_query.join(build_table).on(mr_metrics_table[:pipeline_id].eq(build_table[:commit_id]))
|
||||
end
|
||||
|
||||
def self.serialize(event, _query)
|
||||
build = ::Ci::Build.find(event['id'])
|
||||
|
||||
AnalyticsBuildSerializer.new.represent(build).as_json
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class TestConfig < BaseConfig
|
||||
class TestEvent < BaseEvent
|
||||
@stage = :test
|
||||
@start_time_attrs = mr_metrics_table[:latest_build_started_at]
|
||||
@end_time_attrs = mr_metrics_table[:latest_build_finished_at]
|
||||
@projections = [build_table[:id]]
|
||||
|
@ -9,6 +10,12 @@ module Gitlab
|
|||
def self.query(base_query)
|
||||
base_query.join(build_table).on(mr_metrics_table[:pipeline_id].eq(build_table[:commit_id]))
|
||||
end
|
||||
|
||||
def self.serialize(event, _query)
|
||||
build = ::Ci::Build.find(event['id'])
|
||||
|
||||
AnalyticsBuildSerializer.new.represent(build).as_json
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
require 'lib/gitlab/cycle_analytics/shared_config_spec'
|
||||
require 'lib/gitlab/cycle_analytics/shared_event_spec'
|
||||
|
||||
describe Gitlab::CycleAnalytics::CodeConfig do
|
||||
describe Gitlab::CycleAnalytics::CodeEvent do
|
||||
it_behaves_like 'default query config'
|
||||
|
||||
it 'has the default order' do
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
require 'lib/gitlab/cycle_analytics/shared_config_spec'
|
||||
require 'lib/gitlab/cycle_analytics/shared_event_spec'
|
||||
|
||||
describe Gitlab::CycleAnalytics::IssueConfig do
|
||||
describe Gitlab::CycleAnalytics::IssueEvent do
|
||||
it_behaves_like 'default query config'
|
||||
|
||||
it 'has the default order' do
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
require 'lib/gitlab/cycle_analytics/shared_config_spec'
|
||||
require 'lib/gitlab/cycle_analytics/shared_event_spec'
|
||||
|
||||
describe Gitlab::CycleAnalytics::PlanConfig do
|
||||
describe Gitlab::CycleAnalytics::PlanEvent do
|
||||
it_behaves_like 'default query config'
|
||||
|
||||
it 'has the default order' do
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
require 'lib/gitlab/cycle_analytics/shared_config_spec'
|
||||
require 'lib/gitlab/cycle_analytics/shared_event_spec'
|
||||
|
||||
describe Gitlab::CycleAnalytics::ProductionConfig do
|
||||
describe Gitlab::CycleAnalytics::ProductionEvent do
|
||||
it_behaves_like 'default query config'
|
||||
|
||||
it 'has the default order' do
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
require 'lib/gitlab/cycle_analytics/shared_config_spec'
|
||||
require 'lib/gitlab/cycle_analytics/shared_event_spec'
|
||||
|
||||
describe Gitlab::CycleAnalytics::ReviewConfig do
|
||||
describe Gitlab::CycleAnalytics::ReviewEvent do
|
||||
it_behaves_like 'default query config'
|
||||
|
||||
it 'has the default order' do
|
|
@ -12,4 +12,8 @@ shared_examples 'default query config' do
|
|||
it 'has the projection attributes' do
|
||||
expect(described_class.projections).not_to be_nil
|
||||
end
|
||||
|
||||
it 'implements the fetch method' do
|
||||
expect(described_class.fetch).not_to raise_error
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
require 'lib/gitlab/cycle_analytics/shared_config_spec'
|
||||
require 'lib/gitlab/cycle_analytics/shared_event_spec'
|
||||
|
||||
describe Gitlab::CycleAnalytics::StagingConfig do
|
||||
describe Gitlab::CycleAnalytics::StagingEvent do
|
||||
it_behaves_like 'default query config'
|
||||
|
||||
it 'has the default order' do
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
require 'lib/gitlab/cycle_analytics/shared_config_spec'
|
||||
require 'lib/gitlab/cycle_analytics/shared_event_spec'
|
||||
|
||||
describe Gitlab::CycleAnalytics::TestConfig do
|
||||
describe Gitlab::CycleAnalytics::TestEvent do
|
||||
it_behaves_like 'default query config'
|
||||
|
||||
it 'has the default order' do
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe AnalyticsGenericEntity do
|
||||
describe AnalyticsIssueEntity do
|
||||
let(:user) { create(:user) }
|
||||
let(:entity_hash) do
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue