more refactoring and added some auth checks
This commit is contained in:
parent
9c995725ea
commit
d5b673da79
14 changed files with 674 additions and 817 deletions
|
@ -50,7 +50,7 @@ module Projects
|
|||
end
|
||||
|
||||
def options
|
||||
@options ||= { from: start_date(events_params) }
|
||||
@options ||= { from: start_date(events_params), current_user: current_user }
|
||||
end
|
||||
|
||||
def events_params
|
||||
|
|
1194
db/schema.rb
1194
db/schema.rb
File diff suppressed because it is too large
Load diff
|
@ -1,26 +1,36 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class BaseEvent
|
||||
extend MetricsTables
|
||||
include MetricsTables
|
||||
|
||||
class << self
|
||||
attr_reader :stage, :start_time_attrs, :end_time_attrs, :projections
|
||||
attr_reader :stage, :start_time_attrs, :end_time_attrs, :projections, :query
|
||||
|
||||
def order
|
||||
@order || @start_time_attrs
|
||||
def initialize(project:, options:)
|
||||
@query = EventsQuery.new(project: project, options: options)
|
||||
@project = project
|
||||
@options = options
|
||||
end
|
||||
|
||||
def fetch
|
||||
@query.execute(self).map do |event|
|
||||
serialize(event) if has_permission?(event['id'])
|
||||
end
|
||||
end
|
||||
|
||||
def query(_base_query); end
|
||||
def custom_query(_base_query); end
|
||||
|
||||
def fetch(query)
|
||||
query.execute(self).map { |event| serialize(event, query) }
|
||||
end
|
||||
def order
|
||||
@order || @start_time_attrs
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def serialize(_event, _query)
|
||||
raise NotImplementedError.new("Expected #{self.name} to implement serialize(event, query)")
|
||||
end
|
||||
def serialize(_event)
|
||||
raise NotImplementedError.new("Expected #{self.name} to implement serialize(event)")
|
||||
end
|
||||
|
||||
def has_permission?(_id)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,24 +1,31 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class CodeEvent < BaseEvent
|
||||
@stage = :code
|
||||
@start_time_attrs = issue_metrics_table[:first_mentioned_in_commit_at]
|
||||
def initialize(*args)
|
||||
@stage = :code
|
||||
@start_time_attrs = issue_metrics_table[:first_mentioned_in_commit_at]
|
||||
@end_time_attrs = mr_table[:created_at]
|
||||
@projections = [mr_table[:title],
|
||||
mr_table[:iid],
|
||||
mr_table[:id],
|
||||
mr_table[:created_at],
|
||||
mr_table[:state],
|
||||
mr_table[:author_id]]
|
||||
@order = mr_table[:created_at]
|
||||
|
||||
@end_time_attrs = mr_table[:created_at]
|
||||
super(*args)
|
||||
end
|
||||
|
||||
@projections = [mr_table[:title],
|
||||
mr_table[:iid],
|
||||
mr_table[:id],
|
||||
mr_table[:created_at],
|
||||
mr_table[:state],
|
||||
mr_table[:author_id]]
|
||||
private
|
||||
|
||||
@order = mr_table[:created_at]
|
||||
|
||||
def self.serialize(event, query)
|
||||
def serialize(event)
|
||||
event['author'] = User.find(event.delete('author_id'))
|
||||
|
||||
AnalyticsMergeRequestSerializer.new(project: query.project).represent(event).as_json
|
||||
AnalyticsMergeRequestSerializer.new(project: @project).represent(event).as_json
|
||||
end
|
||||
|
||||
def has_permission?(id)
|
||||
@options[:current_user].can?(:read_merge_request, MergeRequest.find(id))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class TestEvent < BaseEvent
|
||||
@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]]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,35 +3,35 @@ module Gitlab
|
|||
class Events
|
||||
def initialize(project:, options:)
|
||||
@project = project
|
||||
@query = EventsQuery.new(project: project, options: options)
|
||||
@options = options
|
||||
end
|
||||
|
||||
def issue_events
|
||||
IssueEvent.fetch(@query)
|
||||
IssueEvent.new(project: @project, options: @options).fetch
|
||||
end
|
||||
|
||||
def plan_events
|
||||
PlanEvent.fetch(@query)
|
||||
PlanEvent.new(project: @project, options: @options).fetch
|
||||
end
|
||||
|
||||
def code_events
|
||||
CodeEvent.fetch(@query)
|
||||
CodeEvent.new(project: @project, options: @options).fetch
|
||||
end
|
||||
|
||||
def test_events
|
||||
TestEvent.fetch(@query)
|
||||
TestEvent.new(project: @project, options: @options).fetch
|
||||
end
|
||||
|
||||
def review_events
|
||||
ReviewEvent.fetch(@query)
|
||||
ReviewEvent.new(project: @project, options: @options).fetch
|
||||
end
|
||||
|
||||
def staging_events
|
||||
StagingEvent.fetch(@query)
|
||||
StagingEvent.new(project: @project, options: @options).fetch
|
||||
end
|
||||
|
||||
def production_events
|
||||
ProductionEvent.fetch(@query)
|
||||
ProductionEvent.new(project: @project, options: @options).fetch
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ module Gitlab
|
|||
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)
|
||||
|
||||
@stage_class.query(base_query)
|
||||
@stage_class.custom_query(base_query)
|
||||
|
||||
base_query.project(extract_epoch(diff_fn).as('total_time'), *@stage_class.projections).order(@stage_class.order.desc)
|
||||
end
|
||||
|
|
|
@ -1,22 +1,30 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class IssueEvent < BaseEvent
|
||||
@stage = :issue
|
||||
@start_time_attrs = issue_table[:created_at]
|
||||
def initialize(*args)
|
||||
@stage = :issue
|
||||
@start_time_attrs = issue_table[:created_at]
|
||||
@end_time_attrs = [issue_metrics_table[:first_associated_with_milestone_at],
|
||||
issue_metrics_table[:first_added_to_board_at]]
|
||||
@projections = [issue_table[:title],
|
||||
issue_table[:iid],
|
||||
issue_table[:id],
|
||||
issue_table[:created_at],
|
||||
issue_table[:author_id]]
|
||||
|
||||
@end_time_attrs = [issue_metrics_table[:first_associated_with_milestone_at],
|
||||
issue_metrics_table[:first_added_to_board_at]]
|
||||
super(*args)
|
||||
end
|
||||
|
||||
@projections = [issue_table[:title],
|
||||
issue_table[:iid],
|
||||
issue_table[:id],
|
||||
issue_table[:created_at],
|
||||
issue_table[:author_id]]
|
||||
private
|
||||
|
||||
def self.serialize(event, query)
|
||||
def serialize(event)
|
||||
event['author'] = User.find(event.delete('author_id'))
|
||||
|
||||
AnalyticsIssueSerializer.new(project: query.project).represent(event).as_json
|
||||
AnalyticsIssueSerializer.new(project: @project).represent(event).as_json
|
||||
end
|
||||
|
||||
def has_permission?(id)
|
||||
@options[:current_user].can?(:read_issue, Issue.find(id))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class PlanEvent < BaseEvent
|
||||
@stage = :plan
|
||||
@start_time_attrs = issue_metrics_table[:first_associated_with_milestone_at]
|
||||
def initialize(*args)
|
||||
@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]]
|
||||
|
||||
@end_time_attrs = [issue_metrics_table[:first_added_to_board_at],
|
||||
issue_metrics_table[:first_mentioned_in_commit_at]]
|
||||
super(*args)
|
||||
end
|
||||
|
||||
@projections = [mr_diff_table[:st_commits].as('commits'),
|
||||
issue_metrics_table[:first_mentioned_in_commit_at]]
|
||||
def custom_query(base_query)
|
||||
base_query.join(mr_diff_table).on(mr_diff_table[:merge_request_id].eq(mr_table[:id]))
|
||||
end
|
||||
|
||||
class << self
|
||||
def query(base_query)
|
||||
base_query.join(mr_diff_table).on(mr_diff_table[:merge_request_id].eq(mr_table[:id]))
|
||||
private
|
||||
|
||||
def serialize(event)
|
||||
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
|
||||
|
||||
private
|
||||
def serialize_commit(event, st_commit, query)
|
||||
commit = Commit.new(Gitlab::Git::Commit.new(st_commit), @project)
|
||||
|
||||
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
|
||||
AnalyticsCommitSerializer.new(project: @project, total_time: event['total_time']).represent(commit).as_json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,21 +1,29 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class ProductionEvent < BaseEvent
|
||||
@stage = :production
|
||||
@start_time_attrs = issue_table[:created_at]
|
||||
def initialize(*args)
|
||||
@stage = :production
|
||||
@start_time_attrs = issue_table[:created_at]
|
||||
@end_time_attrs = mr_metrics_table[:first_deployed_to_production_at]
|
||||
@projections = [issue_table[:title],
|
||||
issue_table[:iid],
|
||||
issue_table[:id],
|
||||
issue_table[:created_at],
|
||||
issue_table[:author_id]]
|
||||
|
||||
@end_time_attrs = mr_metrics_table[:first_deployed_to_production_at]
|
||||
super(*args)
|
||||
end
|
||||
|
||||
@projections = [issue_table[:title],
|
||||
issue_table[:iid],
|
||||
issue_table[:id],
|
||||
issue_table[:created_at],
|
||||
issue_table[:author_id]]
|
||||
private
|
||||
|
||||
def self.serialize(event, query)
|
||||
def serialize(event)
|
||||
event['author'] = User.find(event.delete('author_id'))
|
||||
|
||||
AnalyticsIssueSerializer.new(project: query.project).represent(event).as_json
|
||||
AnalyticsIssueSerializer.new(project: @project).represent(event).as_json
|
||||
end
|
||||
|
||||
def has_permission?(id)
|
||||
@options[:current_user].can?(:read_issue, Issue.find(id))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,20 +1,28 @@
|
|||
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 initialize(*args)
|
||||
@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)
|
||||
super(*args)
|
||||
end
|
||||
|
||||
def serialize(event)
|
||||
event['author'] = User.find(event.delete('author_id'))
|
||||
|
||||
AnalyticsMergeRequestSerializer.new(project: query.project).represent(event).as_json
|
||||
AnalyticsMergeRequestSerializer.new(project: @project).represent(event).as_json
|
||||
end
|
||||
|
||||
def has_permission?(id)
|
||||
@options[:current_user].can?(:read_merge_request, MergeRequest.find(id))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
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]]
|
||||
@order = build_table[:created_at]
|
||||
def initialize(*args)
|
||||
@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]]
|
||||
@order = build_table[:created_at]
|
||||
|
||||
def self.query(base_query)
|
||||
super(*args)
|
||||
end
|
||||
|
||||
def custom_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)
|
||||
private
|
||||
|
||||
def serialize(event)
|
||||
build = ::Ci::Build.find(event['id'])
|
||||
|
||||
AnalyticsBuildSerializer.new.represent(build).as_json
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
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]]
|
||||
@order = build_table[:created_at]
|
||||
def initialize(*args)
|
||||
@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]]
|
||||
@order = build_table[:created_at]
|
||||
|
||||
def self.query(base_query)
|
||||
super(*args)
|
||||
end
|
||||
|
||||
def custom_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)
|
||||
private
|
||||
|
||||
def serialize(event)
|
||||
build = ::Ci::Build.find(event['id'])
|
||||
|
||||
AnalyticsBuildSerializer.new.represent(build).as_json
|
||||
|
|
|
@ -6,7 +6,7 @@ describe Gitlab::CycleAnalytics::Events do
|
|||
let(:user) { create(:user, :admin) }
|
||||
let!(:context) { create(:issue, project: project, created_at: 2.days.ago) }
|
||||
|
||||
subject { described_class.new(project: project, options: { from: from_date }) }
|
||||
subject { described_class.new(project: project, options: { from: from_date, current_user: user }) }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([context])
|
||||
|
|
Loading…
Reference in a new issue