more refactoring and added some auth checks

This commit is contained in:
James Lopez 2016-11-17 18:00:37 +01:00
parent 9c995725ea
commit d5b673da79
14 changed files with 674 additions and 817 deletions

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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])