Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
745e0f87
Commit
745e0f87
authored
Nov 18, 2016
by
James Lopez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored 1 iteration of cycle analytics and stages in general
parent
f185d9e9
Changes
70
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
70 changed files
with
830 additions
and
451 deletions
+830
-451
app/controllers/concerns/cycle_analytics_params.rb
app/controllers/concerns/cycle_analytics_params.rb
+4
-0
app/controllers/projects/cycle_analytics/events_controller.rb
...controllers/projects/cycle_analytics/events_controller.rb
+14
-18
app/controllers/projects/cycle_analytics_controller.rb
app/controllers/projects/cycle_analytics_controller.rb
+8
-46
app/models/cycle_analytics.rb
app/models/cycle_analytics.rb
+18
-42
app/models/cycle_analytics/summary.rb
app/models/cycle_analytics/summary.rb
+0
-43
app/serializers/analytics_stage_entity.rb
app/serializers/analytics_stage_entity.rb
+10
-0
app/serializers/analytics_stage_serializer.rb
app/serializers/analytics_stage_serializer.rb
+3
-0
app/serializers/analytics_summary_entity.rb
app/serializers/analytics_summary_entity.rb
+7
-0
app/serializers/analytics_summary_serializer.rb
app/serializers/analytics_summary_serializer.rb
+3
-0
lib/gitlab/cycle_analytics/base_event_fetcher.rb
lib/gitlab/cycle_analytics/base_event_fetcher.rb
+17
-9
lib/gitlab/cycle_analytics/base_query.rb
lib/gitlab/cycle_analytics/base_query.rb
+31
-0
lib/gitlab/cycle_analytics/base_stage.rb
lib/gitlab/cycle_analytics/base_stage.rb
+54
-0
lib/gitlab/cycle_analytics/code_event_fetcher.rb
lib/gitlab/cycle_analytics/code_event_fetcher.rb
+4
-4
lib/gitlab/cycle_analytics/code_stage.rb
lib/gitlab/cycle_analytics/code_stage.rb
+21
-0
lib/gitlab/cycle_analytics/event_fetcher.rb
lib/gitlab/cycle_analytics/event_fetcher.rb
+9
-0
lib/gitlab/cycle_analytics/events.rb
lib/gitlab/cycle_analytics/events.rb
+0
-38
lib/gitlab/cycle_analytics/events_query.rb
lib/gitlab/cycle_analytics/events_query.rb
+0
-37
lib/gitlab/cycle_analytics/issue_event.rb
lib/gitlab/cycle_analytics/issue_event.rb
+0
-27
lib/gitlab/cycle_analytics/issue_event_fetcher.rb
lib/gitlab/cycle_analytics/issue_event_fetcher.rb
+1
-4
lib/gitlab/cycle_analytics/issue_stage.rb
lib/gitlab/cycle_analytics/issue_stage.rb
+22
-0
lib/gitlab/cycle_analytics/plan_event_fetcher.rb
lib/gitlab/cycle_analytics/plan_event_fetcher.rb
+4
-6
lib/gitlab/cycle_analytics/plan_stage.rb
lib/gitlab/cycle_analytics/plan_stage.rb
+22
-0
lib/gitlab/cycle_analytics/production_event_fetcher.rb
lib/gitlab/cycle_analytics/production_event_fetcher.rb
+6
-0
lib/gitlab/cycle_analytics/production_helper.rb
lib/gitlab/cycle_analytics/production_helper.rb
+9
-0
lib/gitlab/cycle_analytics/production_stage.rb
lib/gitlab/cycle_analytics/production_stage.rb
+28
-0
lib/gitlab/cycle_analytics/review_event_fetcher.rb
lib/gitlab/cycle_analytics/review_event_fetcher.rb
+1
-7
lib/gitlab/cycle_analytics/review_stage.rb
lib/gitlab/cycle_analytics/review_stage.rb
+21
-0
lib/gitlab/cycle_analytics/stage.rb
lib/gitlab/cycle_analytics/stage.rb
+9
-0
lib/gitlab/cycle_analytics/stage_summary.rb
lib/gitlab/cycle_analytics/stage_summary.rb
+23
-0
lib/gitlab/cycle_analytics/staging_event_fetcher.rb
lib/gitlab/cycle_analytics/staging_event_fetcher.rb
+4
-5
lib/gitlab/cycle_analytics/staging_stage.rb
lib/gitlab/cycle_analytics/staging_stage.rb
+22
-0
lib/gitlab/cycle_analytics/summary/base.rb
lib/gitlab/cycle_analytics/summary/base.rb
+20
-0
lib/gitlab/cycle_analytics/summary/commit.rb
lib/gitlab/cycle_analytics/summary/commit.rb
+39
-0
lib/gitlab/cycle_analytics/summary/deploy.rb
lib/gitlab/cycle_analytics/summary/deploy.rb
+11
-0
lib/gitlab/cycle_analytics/summary/issue.rb
lib/gitlab/cycle_analytics/summary/issue.rb
+21
-0
lib/gitlab/cycle_analytics/test_event.rb
lib/gitlab/cycle_analytics/test_event.rb
+0
-13
lib/gitlab/cycle_analytics/test_event_fetcher.rb
lib/gitlab/cycle_analytics/test_event_fetcher.rb
+6
-0
lib/gitlab/cycle_analytics/test_stage.rb
lib/gitlab/cycle_analytics/test_stage.rb
+29
-0
lib/gitlab/database/median.rb
lib/gitlab/database/median.rb
+5
-0
spec/lib/gitlab/cycle_analytics/code_event_fetcher_spec.rb
spec/lib/gitlab/cycle_analytics/code_event_fetcher_spec.rb
+12
-0
spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
+8
-0
spec/lib/gitlab/cycle_analytics/events_spec.rb
spec/lib/gitlab/cycle_analytics/events_spec.rb
+75
-62
spec/lib/gitlab/cycle_analytics/issue_event_fetcher_spec.rb
spec/lib/gitlab/cycle_analytics/issue_event_fetcher_spec.rb
+8
-0
spec/lib/gitlab/cycle_analytics/issue_event_spec.rb
spec/lib/gitlab/cycle_analytics/issue_event_spec.rb
+0
-10
spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
+8
-0
spec/lib/gitlab/cycle_analytics/plan_event_fetcher_spec.rb
spec/lib/gitlab/cycle_analytics/plan_event_fetcher_spec.rb
+4
-6
spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
+8
-0
spec/lib/gitlab/cycle_analytics/production_event_fetcher_spec.rb
...b/gitlab/cycle_analytics/production_event_fetcher_spec.rb
+8
-0
spec/lib/gitlab/cycle_analytics/production_stage_spec.rb
spec/lib/gitlab/cycle_analytics/production_stage_spec.rb
+8
-0
spec/lib/gitlab/cycle_analytics/review_event_fetcher_spec.rb
spec/lib/gitlab/cycle_analytics/review_event_fetcher_spec.rb
+8
-0
spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
+8
-0
spec/lib/gitlab/cycle_analytics/shared_event_spec.rb
spec/lib/gitlab/cycle_analytics/shared_event_spec.rb
+2
-9
spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
+30
-0
spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+10
-10
spec/lib/gitlab/cycle_analytics/staging_event_fetcher_spec.rb
.../lib/gitlab/cycle_analytics/staging_event_fetcher_spec.rb
+12
-0
spec/lib/gitlab/cycle_analytics/staging_event_spec.rb
spec/lib/gitlab/cycle_analytics/staging_event_spec.rb
+0
-10
spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
+8
-0
spec/lib/gitlab/cycle_analytics/test_event_fetcher_spec.rb
spec/lib/gitlab/cycle_analytics/test_event_fetcher_spec.rb
+12
-0
spec/lib/gitlab/cycle_analytics/test_event_spec.rb
spec/lib/gitlab/cycle_analytics/test_event_spec.rb
+0
-10
spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
+8
-0
spec/models/cycle_analytics/code_spec.rb
spec/models/cycle_analytics/code_spec.rb
+11
-11
spec/models/cycle_analytics/issue_spec.rb
spec/models/cycle_analytics/issue_spec.rb
+2
-2
spec/models/cycle_analytics/plan_spec.rb
spec/models/cycle_analytics/plan_spec.rb
+2
-2
spec/models/cycle_analytics/production_spec.rb
spec/models/cycle_analytics/production_spec.rb
+3
-3
spec/models/cycle_analytics/review_spec.rb
spec/models/cycle_analytics/review_spec.rb
+2
-2
spec/models/cycle_analytics/staging_spec.rb
spec/models/cycle_analytics/staging_spec.rb
+3
-3
spec/models/cycle_analytics/test_spec.rb
spec/models/cycle_analytics/test_spec.rb
+5
-5
spec/serializers/analytics_stage_serializer_spec.rb
spec/serializers/analytics_stage_serializer_spec.rb
+24
-0
spec/serializers/analytics_summary_serializer_spec.rb
spec/serializers/analytics_summary_serializer_spec.rb
+29
-0
spec/support/cycle_analytics_helpers/test_generation.rb
spec/support/cycle_analytics_helpers/test_generation.rb
+6
-7
No files found.
app/controllers/concerns/cycle_analytics_params.rb
View file @
745e0f87
module
CycleAnalyticsParams
module
CycleAnalyticsParams
extend
ActiveSupport
::
Concern
extend
ActiveSupport
::
Concern
def
options
(
params
)
@options
||=
{
from:
start_date
(
params
),
current_user:
current_user
}
end
def
start_date
(
params
)
def
start_date
(
params
)
params
[
:start_date
]
==
'30'
?
30
.
days
.
ago
:
90
.
days
.
ago
params
[
:start_date
]
==
'30'
?
30
.
days
.
ago
:
90
.
days
.
ago
end
end
...
...
app/controllers/projects/cycle_analytics/events_controller.rb
View file @
745e0f87
...
@@ -9,56 +9,52 @@ module Projects
...
@@ -9,56 +9,52 @@ module Projects
before_action
:authorize_read_merge_request!
,
only:
[
:code
,
:review
]
before_action
:authorize_read_merge_request!
,
only:
[
:code
,
:review
]
def
issue
def
issue
render_events
(
events
.
issue_
events
)
render_events
(
cycle_analytics
[
:issue
].
events
)
end
end
def
plan
def
plan
render_events
(
events
.
plan_
events
)
render_events
(
cycle_analytics
[
:plan
].
events
)
end
end
def
code
def
code
render_events
(
events
.
code_
events
)
render_events
(
cycle_analytics
[
:code
].
events
)
end
end
def
test
def
test
options
[
:branch
]
=
events_params
[
:branch_name
]
options
(
events_params
)
[
:branch
]
=
events_params
[
:branch_name
]
render_events
(
events
.
test_
events
)
render_events
(
cycle_analytics
[
:test
].
events
)
end
end
def
review
def
review
render_events
(
events
.
review_
events
)
render_events
(
cycle_analytics
[
:review
].
events
)
end
end
def
staging
def
staging
render_events
(
events
.
staging_
events
)
render_events
(
cycle_analytics
[
:staging
].
events
)
end
end
def
production
def
production
render_events
(
events
.
production_
events
)
render_events
(
cycle_analytics
[
:production
].
events
)
end
end
private
private
def
render_events
(
events
_list
)
def
render_events
(
events
)
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
html
format
.
html
format
.
json
{
render
json:
{
events:
events
_list
}
}
format
.
json
{
render
json:
{
events:
events
}
}
end
end
end
end
def
events
def
cycle_analytics
@events
||=
Gitlab
::
CycleAnalytics
::
Events
.
new
(
project:
project
,
options:
options
)
@cycle_analytics
||=
::
CycleAnalytics
.
new
(
project
,
options
(
events_params
))
end
def
options
@options
||=
{
from:
start_date
(
events_params
),
current_user:
current_user
}
end
end
def
events_params
def
events_params
return
{}
unless
params
[
:events
].
present?
return
{}
unless
params
[
:events
].
present?
params
[
:events
].
slice
(
:start_date
,
:branch_name
)
params
[
:events
].
permit
(
:start_date
,
:branch_name
)
end
end
end
end
end
end
...
...
app/controllers/projects/cycle_analytics_controller.rb
View file @
745e0f87
...
@@ -6,11 +6,9 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
...
@@ -6,11 +6,9 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
before_action
:authorize_read_cycle_analytics!
before_action
:authorize_read_cycle_analytics!
def
show
def
show
@cycle_analytics
=
::
CycleAnalytics
.
new
(
@project
,
current_user
,
from:
start_date
(
cycle_analytics_params
))
@cycle_analytics
=
::
CycleAnalytics
.
new
(
@project
,
options
(
cycle_analytics_params
))
stats_values
,
cycle_analytics_json
=
generate_cycle_analytics_data
@cycle_analytics_no_data
=
@cycle_analytics
.
no_stats?
@cycle_analytics_no_data
=
stats_values
.
blank?
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
html
format
.
html
...
@@ -23,50 +21,14 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
...
@@ -23,50 +21,14 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
def
cycle_analytics_params
def
cycle_analytics_params
return
{}
unless
params
[
:cycle_analytics
].
present?
return
{}
unless
params
[
:cycle_analytics
].
present?
{
start_date:
params
[
:cycle_analytics
][
:start_date
]
}
params
[
:cycle_analytics
].
permit
(
:start_date
)
end
end
def
generate_cycle_analytics_data
def
cycle_analytics_json
stats_values
=
[]
{
summary:
@cycle_analytics
.
summary
,
cycle_analytics_view_data
=
[[
:issue
,
"Issue"
,
"Related Issues"
,
"Time before an issue gets scheduled"
],
stats:
@cycle_analytics
.
stats
,
[
:plan
,
"Plan"
,
"Related Commits"
,
"Time before an issue starts implementation"
],
permissions:
@cycle_analytics
.
permissions
(
user:
current_user
)
[
:code
,
"Code"
,
"Related Merge Requests"
,
"Time spent coding"
],
[
:test
,
"Test"
,
"Relative Builds Trigger by Commits"
,
"The time taken to build and test the application"
],
[
:review
,
"Review"
,
"Relative Merged Requests"
,
"The time taken to review the code"
],
[
:staging
,
"Staging"
,
"Relative Deployed Builds"
,
"The time taken in staging"
],
[
:production
,
"Production"
,
"Related Issues"
,
"The total time taken from idea to production"
]]
stats
=
cycle_analytics_view_data
.
reduce
([])
do
|
stats
,
(
stage_method
,
stage_text
,
stage_legend
,
stage_description
)
|
value
=
@cycle_analytics
.
send
(
stage_method
).
presence
stats_values
<<
value
.
abs
if
value
stats
<<
{
title:
stage_text
,
description:
stage_description
,
legend:
stage_legend
,
value:
value
&&
!
value
.
zero?
?
distance_of_time_in_words
(
value
)
:
nil
}
stats
end
issues
=
@cycle_analytics
.
summary
.
new_issues
commits
=
@cycle_analytics
.
summary
.
commits
deploys
=
@cycle_analytics
.
summary
.
deploys
summary
=
[
{
title:
"New Issue"
.
pluralize
(
issues
),
value:
issues
},
{
title:
"Commit"
.
pluralize
(
commits
),
value:
commits
},
{
title:
"Deploy"
.
pluralize
(
deploys
),
value:
deploys
}
]
cycle_analytics_hash
=
{
summary:
summary
,
stats:
stats
,
permissions:
@cycle_analytics
.
permissions
(
user:
current_user
)
}
}
[
stats_values
,
cycle_analytics_hash
]
end
end
end
end
app/models/cycle_analytics.rb
View file @
745e0f87
class
CycleAnalytics
class
CycleAnalytics
STAGES
=
%i[issue plan code test review staging production]
.
freeze
STAGES
=
%i[issue plan code test review staging production]
.
freeze
def
initialize
(
project
,
current_user
,
from
:
)
def
initialize
(
project
,
options
)
@project
=
project
@project
=
project
@current_user
=
current_user
@options
=
options
@from
=
from
@fetcher
=
Gitlab
::
CycleAnalytics
::
MetricsFetcher
.
new
(
project:
project
,
from:
from
,
branch:
nil
)
end
end
def
summary
def
summary
@summary
||=
Summary
.
new
(
@project
,
@current_user
,
from:
@from
)
@summary
||=
::
Gitlab
::
CycleAnalytics
::
StageSummary
.
new
(
@project
,
from:
@options
[
:from
],
current_user:
@options
[
:current_user
]).
data
end
end
def
permissions
(
user
:)
def
stats
Gitlab
::
CycleAnalytics
::
Permissions
.
get
(
user:
user
,
project:
@project
)
@stats
||=
stats_per_stage
end
end
def
issue
def
no_stats?
@fetcher
.
calculate_metric
(
:issue
,
stats
.
all?
{
|
hash
|
hash
[
:value
].
nil?
}
Issue
.
arel_table
[
:created_at
],
[
Issue
::
Metrics
.
arel_table
[
:first_associated_with_milestone_at
],
Issue
::
Metrics
.
arel_table
[
:first_added_to_board_at
]])
end
end
def
plan
def
permissions
(
user
:)
@fetcher
.
calculate_metric
(
:plan
,
Gitlab
::
CycleAnalytics
::
Permissions
.
get
(
user:
user
,
project:
@project
)
[
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
@fetcher
.
calculate_metric
(
:code
,
Issue
::
Metrics
.
arel_table
[
:first_mentioned_in_commit_at
],
MergeRequest
.
arel_table
[
:created_at
])
end
def
test
@fetcher
.
calculate_metric
(
:test
,
MergeRequest
::
Metrics
.
arel_table
[
:latest_build_started_at
],
MergeRequest
::
Metrics
.
arel_table
[
:latest_build_finished_at
])
end
end
def
review
def
[]
(
stage_name
)
@fetcher
.
calculate_metric
(
:review
,
Gitlab
::
CycleAnalytics
::
Stage
[
stage_name
].
new
(
project:
@project
,
options:
@options
)
MergeRequest
.
arel_table
[
:created_at
],
MergeRequest
::
Metrics
.
arel_table
[
:merged_at
])
end
end
def
staging
private
@fetcher
.
calculate_metric
(
:staging
,
MergeRequest
::
Metrics
.
arel_table
[
:merged_at
],
MergeRequest
::
Metrics
.
arel_table
[
:first_deployed_to_production_at
])
end
def
production
def
stats_per_stage
@fetcher
.
calculate_metric
(
:production
,
STAGES
.
map
do
|
stage_name
|
Issue
.
arel_table
[
:created_at
],
self
[
stage_name
].
as_json
MergeRequest
::
Metrics
.
arel_table
[
:first_deployed_to_production_at
])
end
end
end
end
end
app/models/cycle_analytics/summary.rb
View file @
745e0f87
class
CycleAnalytics
class
Summary
def
initialize
(
project
,
current_user
,
from
:)
@project
=
project
@current_user
=
current_user
@from
=
from
end
def
new_issues
IssuesFinder
.
new
(
@current_user
,
project_id:
@project
.
id
).
execute
.
created_after
(
@from
).
count
end
def
commits
ref
=
@project
.
default_branch
.
presence
count_commits_for
(
ref
)
end
def
deploys
@project
.
deployments
.
where
(
"created_at > ?"
,
@from
).
count
end
private
# Don't use the `Gitlab::Git::Repository#log` method, because it enforces
# a limit. Since we need a commit count, we _can't_ enforce a limit, so
# the easiest way forward is to replicate the relevant portions of the
# `log` function here.
def
count_commits_for
(
ref
)
return
unless
ref
repository
=
@project
.
repository
.
raw_repository
sha
=
@project
.
repository
.
commit
(
ref
).
sha
cmd
=
%W(
#{
Gitlab
.
config
.
git
.
bin_path
}
--git-dir=
#{
repository
.
path
}
log)
cmd
<<
'--format=%H'
cmd
<<
"--after=
#{
@from
.
iso8601
}
"
cmd
<<
sha
raw_output
=
IO
.
popen
(
cmd
)
{
|
io
|
io
.
read
}
raw_output
.
lines
.
count
end
end
end
app/serializers/analytics_stage_entity.rb
0 → 100644
View file @
745e0f87
class
AnalyticsStageEntity
<
Grape
::
Entity
include
EntityDateHelper
expose
:title
expose
:description
expose
:median
,
as: :value
do
|
stage
|
stage
.
median
&&
!
stage
.
median
.
zero?
?
distance_of_time_in_words
(
stage
.
median
)
:
nil
end
end
app/serializers/analytics_stage_serializer.rb
0 → 100644
View file @
745e0f87
class
AnalyticsStageSerializer
<
BaseSerializer
entity
AnalyticsStageEntity
end
app/serializers/analytics_summary_entity.rb
0 → 100644
View file @
745e0f87
class
AnalyticsSummaryEntity
<
Grape
::
Entity
expose
:value
,
safe:
true
expose
:title
do
|
object
|
object
.
title
.
pluralize
(
object
.
value
)
end
end
app/serializers/analytics_summary_serializer.rb
0 → 100644
View file @
745e0f87
class
AnalyticsSummarySerializer
<
BaseSerializer
entity
AnalyticsSummaryEntity
end
lib/gitlab/cycle_analytics/base_event.rb
→
lib/gitlab/cycle_analytics/base_event
_fetcher
.rb
View file @
745e0f87
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
BaseEvent
class
BaseEvent
Fetcher
include
MetricsTables
include
BaseQuery
attr_reader
:
stage
,
:start_time_attrs
,
:end_time_attrs
,
:projections
,
:query
attr_reader
:
projections
,
:query
,
:stage
,
:order
def
initialize
(
project
:,
options
:)
def
initialize
(
project
:,
stage
:,
options
:)
@query
=
EventsQuery
.
new
(
project:
project
,
options:
options
)
@project
=
project
@project
=
project
@stage
=
stage
@options
=
options
@options
=
options
end
end
...
@@ -19,10 +19,8 @@ module Gitlab
...
@@ -19,10 +19,8 @@ module Gitlab
end
.
compact
end
.
compact
end
end
def
custom_query
(
_base_query
);
end
def
order
def
order
@order
||
@start_time_attrs
@order
||
default_order
end
end
private
private
...
@@ -34,7 +32,17 @@ module Gitlab
...
@@ -34,7 +32,17 @@ module Gitlab
end
end
def
event_result
def
event_result
@event_result
||=
@query
.
execute
(
self
).
to_a
@event_result
||=
ActiveRecord
::
Base
.
connection
.
exec_query
(
events_query
.
to_sql
).
to_a
end
def
events_query
diff_fn
=
subtract_datetimes_diff
(
base_query
,
@options
[
:start_time_attrs
],
@options
[
:end_time_attrs
])
base_query
.
project
(
extract_diff_epoch
(
diff_fn
).
as
(
'total_time'
),
*
projections
).
order
(
order
.
desc
)
end
def
default_order
[
@options
[
:start_time_attrs
]].
flatten
.
first
end
end
def
serialize
(
_event
)
def
serialize
(
_event
)
...
...
lib/gitlab/cycle_analytics/
metrics_fetcher
.rb
→
lib/gitlab/cycle_analytics/
base_query
.rb
View file @
745e0f87
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
MetricsFetcher
module
BaseQuery
include
MetricsTables
include
Gitlab
::
Database
::
Median
include
Gitlab
::
Database
::
Median
include
Gitlab
::
Database
::
DateTime
include
Gitlab
::
Database
::
DateTime
include
MetricsTables
DEPLOYMENT_METRIC_STAGES
=
%i[production staging]
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
}
"
)
# Build a `SELECT` query. We find the first of the `end_time_attrs` that isn't `NULL` (call this end_time).
private
# Next, we find the first of the start_time_attrs that isn't `NULL` (call this start_time).
# We compute the (end_time - start_time) interval, and give it an alias based on the current
# cycle analytics stage.
interval_query
=
Arel
::
Nodes
::
As
.
new
(
cte_table
,
subtract_datetimes
(
base_query_for
(
name
),
start_time_attrs
,
end_time_attrs
,
name
.
to_s
))
median_datetime
(
cte_table
,
interval_query
,
name
)
def
base_query
@base_query
||=
stage_query
end
end
# Join table with a row for every <issue,merge_request> pair (where the merge request
def
stage_query
# closes the given issue) with issue and merge request metrics included. The metrics
# are loaded with an inner join, so issues / merge requests without metrics are
# automatically excluded.
def
base_query_for
(
name
)
# Load issues
query
=
mr_closing_issues_table
.
join
(
issue_table
).
on
(
issue_table
[
:id
].
eq
(
mr_closing_issues_table
[
:issue_id
])).
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
(
issue_metrics_table
).
on
(
issue_table
[
:id
].
eq
(
issue_metrics_table
[
:issue_id
])).
where
(
issue_table
[
:project_id
].
eq
(
@project
.
id
)).
where
(
issue_table
[
:project_id
].
eq
(
@project
.
id
)).
where
(
issue_table
[
:deleted_at
].
eq
(
nil
)).
where
(
issue_table
[
:deleted_at
].
eq
(
nil
)).
where
(
issue_table
[
:created_at
].
gteq
(
@from
))
where
(
issue_table
[
:created_at
].
gteq
(
@options
[
:from
]))
query
=
query
.
where
(
build_table
[
:ref
].
eq
(
@branch
))
if
name
==
:test
&&
@branch
# Load merge_requests
# Load merge_requests
query
=
query
.
join
(
mr_table
,
Arel
::
Nodes
::
OuterJoin
).
query
=
query
.
join
(
mr_table
,
Arel
::
Nodes
::
OuterJoin
).
...
@@ -48,11 +24,6 @@ module Gitlab
...
@@ -48,11 +24,6 @@ module Gitlab
join
(
mr_metrics_table
).
join
(
mr_metrics_table
).
on
(
mr_table
[
:id
].
eq
(
mr_metrics_table
[
:merge_request_id
]))
on
(
mr_table
[
:id
].
eq
(
mr_metrics_table
[
:merge_request_id
]))
if
DEPLOYMENT_METRIC_STAGES
.
include?
(
name
)
# Limit to merge requests that have been deployed to production after `@from`
query
.
where
(
mr_metrics_table
[
:first_deployed_to_production_at
].
gteq
(
@from
))
end
query
query
end
end
end
end
...
...
lib/gitlab/cycle_analytics/base_stage.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
BaseStage
include
BaseQuery
def
initialize
(
project
:,
options
:)
@project
=
project
@options
=
options
end
def
events
event_fetcher
.
fetch
end
def
as_json
AnalyticsStageSerializer
.
new
.
represent
(
self
).
as_json
end
def
title
name
.
to_s
.
capitalize
end
def
median
cte_table
=
Arel
::
Table
.
new
(
"cte_table_for_
#{
name
}
"
)
# 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).
# We compute the (end_time - start_time) interval, and give it an alias based on the current
# cycle analytics stage.
interval_query
=
Arel
::
Nodes
::
As
.
new
(
cte_table
,
subtract_datetimes
(
base_query
.
dup
,
start_time_attrs
,
end_time_attrs
,
name
.
to_s
))
median_datetime
(
cte_table
,
interval_query
,
name
)
end
def
name
raise
NotImplementedError
.
new
(
"Expected
#{
self
.
name
}
to implement name"
)
end
private
def
event_fetcher
@event_fetcher
||=
Gitlab
::
CycleAnalytics
::
EventFetcher
[
name
].
new
(
project:
@project
,
stage:
name
,
options:
event_options
)
end
def
event_options
@options
.
merge
(
start_time_attrs:
start_time_attrs
,
end_time_attrs:
end_time_attrs
)
end
end
end
end
lib/gitlab/cycle_analytics/
review_event
.rb
→
lib/gitlab/cycle_analytics/
code_event_fetcher
.rb
View file @
745e0f87
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
ReviewEvent
<
BaseEvent
class
CodeEventFetcher
<
BaseEventFetcher
include
MergeRequestAllowed
include
MergeRequestAllowed
def
initialize
(
*
args
)
def
initialize
(
*
args
)
@stage
=
:review
@start_time_attrs
=
mr_table
[
:created_at
]
@end_time_attrs
=
mr_metrics_table
[
:merged_at
]
@projections
=
[
mr_table
[
:title
],
@projections
=
[
mr_table
[
:title
],
mr_table
[
:iid
],
mr_table
[
:iid
],
mr_table
[
:id
],
mr_table
[
:id
],
mr_table
[
:created_at
],
mr_table
[
:created_at
],
mr_table
[
:state
],
mr_table
[
:state
],
mr_table
[
:author_id
]]
mr_table
[
:author_id
]]
@order
=
mr_table
[
:created_at
]
super
(
*
args
)
super
(
*
args
)
end
end
private
def
serialize
(
event
)
def
serialize
(
event
)
AnalyticsMergeRequestSerializer
.
new
(
project:
@project
).
represent
(
event
).
as_json
AnalyticsMergeRequestSerializer
.
new
(
project:
@project
).
represent
(
event
).
as_json
end
end
...
...
lib/gitlab/cycle_analytics/code_stage.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
CodeStage
<
BaseStage
def
start_time_attrs
@start_time_attrs
||=
issue_metrics_table
[
:first_mentioned_in_commit_at
]
end
def
end_time_attrs
@end_time_attrs
||=
mr_table
[
:created_at
]
end
def
name
:code
end
def
description
"Time until first merge request"
end
end
end
end
lib/gitlab/cycle_analytics/event_fetcher.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
module
EventFetcher
def
self
.
[]
(
stage_name
)
CycleAnalytics
.
const_get
(
"
#{
stage_name
.
to_s
.
camelize
}
EventFetcher"
)
end
end
end
end
lib/gitlab/cycle_analytics/events.rb
deleted
100644 → 0
View file @
f185d9e9
module
Gitlab
module
CycleAnalytics
class
Events
def
initialize
(
project
:,
options
:)
@project
=
project
@options
=
options
end
def
issue_events
IssueEvent
.
new
(
project:
@project
,
options:
@options
).
fetch
end
def
plan_events
PlanEvent
.
new
(
project:
@project
,
options:
@options
).
fetch
end
def
code_events
CodeEvent
.
new
(
project:
@project
,
options:
@options
).
fetch
end
def
test_events
TestEvent
.
new
(
project:
@project
,
options:
@options
).
fetch
end
def
review_events
ReviewEvent
.
new
(
project:
@project
,
options:
@options
).
fetch
end
def
staging_events
StagingEvent
.
new
(
project:
@project
,
options:
@options
).
fetch
end
def
production_events
ProductionEvent
.
new
(
project:
@project
,
options:
@options
).
fetch
end
end
end
end
lib/gitlab/cycle_analytics/events_query.rb
deleted
100644 → 0
View file @
f185d9e9
module
Gitlab
module
CycleAnalytics
class
EventsQuery
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_class
)
@stage_class
=
stage_class
ActiveRecord
::
Base
.
connection
.
exec_query
(
query
.
to_sql
)
end
private
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
)
@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
def
extract_epoch
(
arel_attribute
)
return
arel_attribute
unless
Gitlab
::
Database
.
postgresql?
Arel
.
sql
(
%Q{EXTRACT(EPOCH FROM (
#{
arel_attribute
.
to_sql
}
))}
)
end
end
end
end
lib/gitlab/cycle_analytics/issue_event.rb
deleted
100644 → 0
View file @
f185d9e9
module
Gitlab
module
CycleAnalytics
class
IssueEvent
<
BaseEvent
include
IssueAllowed
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
]]
super
(
*
args
)
end
private
def
serialize
(
event
)
AnalyticsIssueSerializer
.
new
(
project:
@project
).
represent
(
event
).
as_json
end
end
end
end
lib/gitlab/cycle_analytics/
production_event
.rb
→
lib/gitlab/cycle_analytics/
issue_event_fetcher
.rb
View file @
745e0f87
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
ProductionEvent
<
BaseEvent
class
IssueEventFetcher
<
BaseEventFetcher
include
IssueAllowed
include
IssueAllowed
def
initialize
(
*
args
)
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
],
@projections
=
[
issue_table
[
:title
],
issue_table
[
:iid
],
issue_table
[
:iid
],
issue_table
[
:id
],
issue_table
[
:id
],
...
...
lib/gitlab/cycle_analytics/issue_stage.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
IssueStage
<
BaseStage
def
start_time_attrs
@start_time_attrs
||=
issue_table
[
:created_at
]
end
def
end_time_attrs
@end_time_attrs
||=
[
issue_metrics_table
[
:first_associated_with_milestone_at
],
issue_metrics_table
[
:first_added_to_board_at
]]
end
def
name
:issue
end
def
description
"Time before an issue gets scheduled"
end
end
end
end
lib/gitlab/cycle_analytics/plan_event.rb
→
lib/gitlab/cycle_analytics/plan_event
_fetcher
.rb
View file @
745e0f87
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
PlanEvent
<
BaseEvent
class
PlanEvent
Fetcher
<
BaseEventFetcher
def
initialize
(
*
args
)
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'
),
@projections
=
[
mr_diff_table
[
:st_commits
].
as
(
'commits'
),
issue_metrics_table
[
:first_mentioned_in_commit_at
]]
issue_metrics_table
[
:first_mentioned_in_commit_at
]]
super
(
*
args
)
super
(
*
args
)
end
end
def
custom_query
(
base_query
)
def
events_query
base_query
.
join
(
mr_diff_table
).
on
(
mr_diff_table
[
:merge_request_id
].
eq
(
mr_table
[
:id
]))
base_query
.
join
(
mr_diff_table
).
on
(
mr_diff_table
[
:merge_request_id
].
eq
(
mr_table
[
:id
]))
super
end
end
private
private
...
...
lib/gitlab/cycle_analytics/plan_stage.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
PlanStage
<
BaseStage
def
start_time_attrs
@start_time_attrs
||=
[
issue_metrics_table
[
:first_associated_with_milestone_at
],
issue_metrics_table
[
:first_added_to_board_at
]]
end
def
end_time_attrs
@end_time_attrs
||=
issue_metrics_table
[
:first_mentioned_in_commit_at
]
end
def
name
:plan
end
def
description
"Time before an issue starts implementation"
end
end
end
end
lib/gitlab/cycle_analytics/production_event_fetcher.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
ProductionEventFetcher
<
IssueEventFetcher
end
end
end
lib/gitlab/cycle_analytics/production_helper.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
module
ProductionHelper
def
stage_query
super
.
where
(
mr_metrics_table
[
:first_deployed_to_production_at
].
gteq
(
@options
[
:from
]))
end
end
end
end
lib/gitlab/cycle_analytics/production_stage.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
ProductionStage
<
BaseStage
include
ProductionHelper
def
start_time_attrs
@start_time_attrs
||=
issue_table
[
:created_at
]
end
def
end_time_attrs
@end_time_attrs
||=
mr_metrics_table
[
:first_deployed_to_production_at
]
end
def
name
:production
end
def
description
"From issue creation until deploy to production"
end
def
query
# Limit to merge requests that have been deployed to production after `@from`
query
.
where
(
mr_metrics_table
[
:first_deployed_to_production_at
].
gteq
(
@from
))
end
end
end
end
lib/gitlab/cycle_analytics/
code_event
.rb
→
lib/gitlab/cycle_analytics/
review_event_fetcher
.rb
View file @
745e0f87
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
CodeEvent
<
BaseEvent
class
ReviewEventFetcher
<
BaseEventFetcher
include
MergeRequestAllowed
include
MergeRequestAllowed
def
initialize
(
*
args
)
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
],
@projections
=
[
mr_table
[
:title
],
mr_table
[
:iid
],
mr_table
[
:iid
],
mr_table
[
:id
],
mr_table
[
:id
],
mr_table
[
:created_at
],
mr_table
[
:created_at
],
mr_table
[
:state
],
mr_table
[
:state
],
mr_table
[
:author_id
]]
mr_table
[
:author_id
]]
@order
=
mr_table
[
:created_at
]
super
(
*
args
)
super
(
*
args
)
end
end
private
def
serialize
(
event
)
def
serialize
(
event
)
AnalyticsMergeRequestSerializer
.
new
(
project:
@project
).
represent
(
event
).
as_json
AnalyticsMergeRequestSerializer
.
new
(
project:
@project
).
represent
(
event
).
as_json
end
end
...
...
lib/gitlab/cycle_analytics/review_stage.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
ReviewStage
<
BaseStage
def
start_time_attrs
@start_time_attrs
||=
mr_table
[
:created_at
]
end
def
end_time_attrs
@end_time_attrs
||=
mr_metrics_table
[
:merged_at
]
end
def
name
:review
end
def
description
"Time between merge request creation and merge/close"
end
end
end
end
lib/gitlab/cycle_analytics/stage.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
module
Stage
def
self
.
[]
(
stage_name
)
CycleAnalytics
.
const_get
(
"
#{
stage_name
.
to_s
.
camelize
}
Stage"
)
end
end
end
end
lib/gitlab/cycle_analytics/stage_summary.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
StageSummary
def
initialize
(
project
,
from
:,
current_user
:)
@project
=
project
@from
=
from
@current_user
=
current_user
end
def
data
[
serialize
(
Summary
::
Issue
.
new
(
project:
@project
,
from:
@from
,
current_user:
@current_user
)),
serialize
(
Summary
::
Commit
.
new
(
project:
@project
,
from:
@from
)),
serialize
(
Summary
::
Deploy
.
new
(
project:
@project
,
from:
@from
))]
end
private
def
serialize
(
summary_object
)
AnalyticsSummarySerializer
.
new
.
represent
(
summary_object
).
as_json
end
end
end
end
lib/gitlab/cycle_analytics/staging_event.rb
→
lib/gitlab/cycle_analytics/staging_event
_fetcher
.rb
View file @
745e0f87
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
StagingEvent
<
BaseEvent
class
StagingEvent
Fetcher
<
BaseEventFetcher
def
initialize
(
*
args
)
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
]]
@projections
=
[
build_table
[
:id
]]
@order
=
build_table
[
:created_at
]
@order
=
build_table
[
:created_at
]
...
@@ -17,8 +14,10 @@ module Gitlab
...
@@ -17,8 +14,10 @@ module Gitlab
super
super
end
end
def
custom_query
(
base_query
)
def
events_query
base_query
.
join
(
build_table
).
on
(
mr_metrics_table
[
:pipeline_id
].
eq
(
build_table
[
:commit_id
]))
base_query
.
join
(
build_table
).
on
(
mr_metrics_table
[
:pipeline_id
].
eq
(
build_table
[
:commit_id
]))
super
end
end
private
private
...
...
lib/gitlab/cycle_analytics/staging_stage.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
StagingStage
<
BaseStage
include
ProductionHelper
def
start_time_attrs
@start_time_attrs
||=
mr_metrics_table
[
:merged_at
]
end
def
end_time_attrs
@end_time_attrs
||=
mr_metrics_table
[
:first_deployed_to_production_at
]
end
def
name
:staging
end
def
description
"From merge request merge until deploy to production"
end
end
end
end
lib/gitlab/cycle_analytics/summary/base.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
module
Summary
class
Base
def
initialize
(
project
:,
from
:)
@project
=
project
@from
=
from
end
def
title
self
.
class
.
name
.
demodulize
end
def
value
raise
NotImplementedError
.
new
(
"Expected
#{
self
.
name
}
to implement value"
)
end
end
end
end
end
lib/gitlab/cycle_analytics/summary/commit.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
module
Summary
class
Commit
<
Base
def
value
@value
||=
count_commits
end
private
# Don't use the `Gitlab::Git::Repository#log` method, because it enforces
# a limit. Since we need a commit count, we _can't_ enforce a limit, so
# the easiest way forward is to replicate the relevant portions of the
# `log` function here.
def
count_commits
return
unless
ref
repository
=
@project
.
repository
.
raw_repository
sha
=
@project
.
repository
.
commit
(
ref
).
sha
cmd
=
%W(git --git-dir=
#{
repository
.
path
}
log)
cmd
<<
'--format=%H'
cmd
<<
"--after=
#{
@from
.
iso8601
}
"
cmd
<<
sha
output
,
status
=
Gitlab
::
Popen
.
popen
(
cmd
)
raise
IOError
,
output
unless
status
.
zero?
output
.
lines
.
count
end
def
ref
@ref
||=
@project
.
default_branch
.
presence
end
end
end
end
end
lib/gitlab/cycle_analytics/summary/deploy.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
module
Summary
class
Deploy
<
Base
def
value
@value
||=
@project
.
deployments
.
where
(
"created_at > ?"
,
@from
).
count
end
end
end
end
end
lib/gitlab/cycle_analytics/summary/issue.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
module
Summary
class
Issue
<
Base
def
initialize
(
project
:,
from
:,
current_user
:)
@project
=
project
@from
=
from
@current_user
=
current_user
end
def
title
'New Issue'
end
def
value
@value
||=
IssuesFinder
.
new
(
@current_user
,
project_id:
@project
.
id
).
execute
.
created_after
(
@from
).
count
end
end
end
end
end
lib/gitlab/cycle_analytics/test_event.rb
deleted
100644 → 0
View file @
f185d9e9
module
Gitlab
module
CycleAnalytics
class
TestEvent
<
StagingEvent
def
initialize
(
*
args
)
super
(
*
args
)
@stage
=
:test
@start_time_attrs
=
mr_metrics_table
[
:latest_build_started_at
]
@end_time_attrs
=
mr_metrics_table
[
:latest_build_finished_at
]
end
end
end
end
lib/gitlab/cycle_analytics/test_event_fetcher.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
TestEventFetcher
<
StagingEventFetcher
end
end
end
lib/gitlab/cycle_analytics/test_stage.rb
0 → 100644
View file @
745e0f87
module
Gitlab
module
CycleAnalytics
class
TestStage
<
BaseStage
def
start_time_attrs
@start_time_attrs
||=
mr_metrics_table
[
:latest_build_started_at
]
end
def
end_time_attrs
@end_time_attrs
||=
mr_metrics_table
[
:latest_build_finished_at
]
end
def
name
:test
end
def
description
"Total test time for all commits/merges"
end
def
stage_query
if
@options
[
:branch
]
super
.
where
(
build_table
[
:ref
].
eq
(
@options
[
:branch
]))
else
super
end
end
end
end
end
lib/gitlab/database/median.rb
View file @
745e0f87
...
@@ -103,6 +103,11 @@ module Gitlab
...
@@ -103,6 +103,11 @@ module Gitlab
Arel
.
sql
(
%Q{EXTRACT(EPOCH FROM "
#{
arel_attribute
.
relation
.
name
}
"."
#{
arel_attribute
.
name
}
")}
)
Arel
.
sql
(
%Q{EXTRACT(EPOCH FROM "
#{
arel_attribute
.
relation
.
name
}
"."
#{
arel_attribute
.
name
}
")}
)
end
end
def
extract_diff_epoch
(
diff
)
return
diff
unless
Gitlab
::
Database
.
postgresql?
Arel
.
sql
(
%Q{EXTRACT(EPOCH FROM (
#{
diff
.
to_sql
}
))}
)
end
# Need to cast '0' to an INTERVAL before we can check if the interval is positive
# Need to cast '0' to an INTERVAL before we can check if the interval is positive
def
zero_interval
def
zero_interval
Arel
::
Nodes
::
NamedFunction
.
new
(
"CAST"
,
[
Arel
.
sql
(
"'0' AS INTERVAL"
)])
Arel
::
Nodes
::
NamedFunction
.
new
(
"CAST"
,
[
Arel
.
sql
(
"'0' AS INTERVAL"
)])
...
...
spec/lib/gitlab/cycle_analytics/
production_event
_spec.rb
→
spec/lib/gitlab/cycle_analytics/
code_event_fetcher
_spec.rb
View file @
745e0f87
require
'spec_helper'
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
ProductionEvent
do
describe
Gitlab
::
CycleAnalytics
::
CodeEventFetcher
do
let
(
:stage_name
)
{
:code
}
it_behaves_like
'default query config'
do
it_behaves_like
'default query config'
do
it
'has
the
default order'
do
it
'has
a
default order'
do
expect
(
event
.
order
).
to
eq
(
event
.
start_time_attrs
)
expect
(
event
.
order
).
not_to
be_nil
end
end
end
end
end
end
spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_stage_spec'
describe
Gitlab
::
CycleAnalytics
::
CodeStage
do
let
(
:stage_name
)
{
:code
}
it_behaves_like
'base stage'
end
spec/lib/gitlab/cycle_analytics/events_spec.rb
View file @
745e0f87
This diff is collapsed.
Click to expand it.
spec/lib/gitlab/cycle_analytics/issue_event_fetcher_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
IssueEventFetcher
do
let
(
:stage_name
)
{
:issue
}
it_behaves_like
'default query config'
end
spec/lib/gitlab/cycle_analytics/issue_event_spec.rb
deleted
100644 → 0
View file @
f185d9e9
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
IssueEvent
do
it_behaves_like
'default query config'
do
it
'has the default order'
do
expect
(
event
.
order
).
to
eq
(
event
.
start_time_attrs
)
end
end
end
spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_stage_spec'
describe
Gitlab
::
CycleAnalytics
::
IssueStage
do
let
(
:stage_name
)
{
:issue
}
it_behaves_like
'base stage'
end
spec/lib/gitlab/cycle_analytics/plan_event_spec.rb
→
spec/lib/gitlab/cycle_analytics/plan_event_
fetcher_
spec.rb
View file @
745e0f87
require
'spec_helper'
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
PlanEvent
do
describe
Gitlab
::
CycleAnalytics
::
PlanEventFetcher
do
it_behaves_like
'default query config'
do
let
(
:stage_name
)
{
:plan
}
it
'has the default order'
do
expect
(
event
.
order
).
to
eq
(
event
.
start_time_attrs
)
end
it_behaves_like
'default query config'
do
context
'no commits'
do
context
'no commits'
do
it
'does not blow up if there are no commits'
do
it
'does not blow up if there are no commits'
do
allow
_any_instance_of
(
Gitlab
::
CycleAnalytics
::
EventsQuery
).
to
receive
(
:execute
).
and_return
([{}])
allow
(
event
).
to
receive
(
:event_result
).
and_return
([{}])
expect
{
event
.
fetch
}.
not_to
raise_error
expect
{
event
.
fetch
}.
not_to
raise_error
end
end
...
...
spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_stage_spec'
describe
Gitlab
::
CycleAnalytics
::
PlanStage
do
let
(
:stage_name
)
{
:plan
}
it_behaves_like
'base stage'
end
spec/lib/gitlab/cycle_analytics/production_event_fetcher_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
ProductionEventFetcher
do
let
(
:stage_name
)
{
:production
}
it_behaves_like
'default query config'
end
spec/lib/gitlab/cycle_analytics/production_stage_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_stage_spec'
describe
Gitlab
::
CycleAnalytics
::
ProductionStage
do
let
(
:stage_name
)
{
:production
}
it_behaves_like
'base stage'
end
spec/lib/gitlab/cycle_analytics/review_event_fetcher_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
ReviewEventFetcher
do
let
(
:stage_name
)
{
:review
}
it_behaves_like
'default query config'
end
spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_stage_spec'
describe
Gitlab
::
CycleAnalytics
::
ReviewStage
do
let
(
:stage_name
)
{
:review
}
it_behaves_like
'base stage'
end
spec/lib/gitlab/cycle_analytics/shared_event_spec.rb
View file @
745e0f87
require
'spec_helper'
require
'spec_helper'
shared_examples
'default query config'
do
shared_examples
'default query config'
do
let
(
:event
)
{
described_class
.
new
(
project:
double
,
options:
{})
}
let
(
:project
)
{
create
(
:empty_project
)
}
let
(
:event
)
{
described_class
.
new
(
project:
project
,
stage:
stage_name
,
options:
{
from:
1
.
day
.
ago
})
}
it
'has the start attributes'
do
expect
(
event
.
start_time_attrs
).
not_to
be_nil
end
it
'has the stage attribute'
do
it
'has the stage attribute'
do
expect
(
event
.
stage
).
not_to
be_nil
expect
(
event
.
stage
).
not_to
be_nil
end
end
it
'has the end attributes'
do
expect
(
event
.
end_time_attrs
).
not_to
be_nil
end
it
'has the projection attributes'
do
it
'has the projection attributes'
do
expect
(
event
.
projections
).
not_to
be_nil
expect
(
event
.
projections
).
not_to
be_nil
end
end
...
...
spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
shared_examples
'base stage'
do
let
(
:stage
)
{
described_class
.
new
(
project:
double
,
options:
{})
}
before
do
allow
(
stage
).
to
receive
(
:median
).
and_return
(
1.12
)
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
BaseEventFetcher
).
to
receive
(
:event_result
).
and_return
({})
end
it
'has the median data value'
do
expect
(
stage
.
as_json
[
:value
]).
not_to
be_nil
end
it
'has the median data stage'
do
expect
(
stage
.
as_json
[
:title
]).
not_to
be_nil
end
it
'has the median data description'
do
expect
(
stage
.
as_json
[
:description
]).
not_to
be_nil
end
it
'has the title'
do
expect
(
stage
.
title
).
to
eq
(
stage_name
.
to_s
.
capitalize
)
end
it
'has the events'
do
expect
(
stage
.
events
).
not_to
be_nil
end
end
spec/
models/cycle_analytics/
summary_spec.rb
→
spec/
lib/gitlab/cycle_analytics/stage_
summary_spec.rb
View file @
745e0f87
require
'spec_helper'
require
'spec_helper'
describe
CycleAnalytics
::
Summary
,
models:
true
do
describe
Gitlab
::
CycleAnalytics
::
Stage
Summary
,
models:
true
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:from
)
{
Time
.
now
}
let
(
:from
)
{
1
.
day
.
ago
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
subject
{
described_class
.
new
(
project
,
user
,
from:
from
)
}
subject
{
described_class
.
new
(
project
,
from:
Time
.
now
,
current_user:
user
).
data
}
describe
"#new_issues"
do
describe
"#new_issues"
do
it
"finds the number of issues created after the 'from date'"
do
it
"finds the number of issues created after the 'from date'"
do
Timecop
.
freeze
(
5
.
days
.
ago
)
{
create
(
:issue
,
project:
project
)
}
Timecop
.
freeze
(
5
.
days
.
ago
)
{
create
(
:issue
,
project:
project
)
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create
(
:issue
,
project:
project
)
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create
(
:issue
,
project:
project
)
}
expect
(
subject
.
new_issues
).
to
eq
(
1
)
expect
(
subject
.
first
[
:value
]
).
to
eq
(
1
)
end
end
it
"doesn't find issues from other projects"
do
it
"doesn't find issues from other projects"
do
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create
(
:issue
,
project:
create
(
:project
))
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create
(
:issue
,
project:
create
(
:project
))
}
expect
(
subject
.
new_issues
).
to
eq
(
0
)
expect
(
subject
.
first
[
:value
]
).
to
eq
(
0
)
end
end
end
end
...
@@ -26,19 +26,19 @@ describe CycleAnalytics::Summary, models: true do
...
@@ -26,19 +26,19 @@ describe CycleAnalytics::Summary, models: true do
Timecop
.
freeze
(
5
.
days
.
ago
)
{
create_commit
(
"Test message"
,
project
,
user
,
'master'
)
}
Timecop
.
freeze
(
5
.
days
.
ago
)
{
create_commit
(
"Test message"
,
project
,
user
,
'master'
)
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create_commit
(
"Test message"
,
project
,
user
,
'master'
)
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create_commit
(
"Test message"
,
project
,
user
,
'master'
)
}
expect
(
subject
.
commits
).
to
eq
(
1
)
expect
(
subject
.
second
[
:value
]
).
to
eq
(
1
)
end
end
it
"doesn't find commits from other projects"
do
it
"doesn't find commits from other projects"
do
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create_commit
(
"Test message"
,
create
(
:project
),
user
,
'master'
)
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create_commit
(
"Test message"
,
create
(
:project
),
user
,
'master'
)
}
expect
(
subject
.
commits
).
to
eq
(
0
)
expect
(
subject
.
second
[
:value
]
).
to
eq
(
0
)
end
end
it
"finds a large (> 100) snumber of commits if present"
do
it
"finds a large (> 100) snumber of commits if present"
do
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create_commit
(
"Test message"
,
project
,
user
,
'master'
,
count:
100
)
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create_commit
(
"Test message"
,
project
,
user
,
'master'
,
count:
100
)
}
expect
(
subject
.
commits
).
to
eq
(
100
)
expect
(
subject
.
second
[
:value
]
).
to
eq
(
100
)
end
end
end
end
...
@@ -47,13 +47,13 @@ describe CycleAnalytics::Summary, models: true do
...
@@ -47,13 +47,13 @@ describe CycleAnalytics::Summary, models: true do
Timecop
.
freeze
(
5
.
days
.
ago
)
{
create
(
:deployment
,
project:
project
)
}
Timecop
.
freeze
(
5
.
days
.
ago
)
{
create
(
:deployment
,
project:
project
)
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create
(
:deployment
,
project:
project
)
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create
(
:deployment
,
project:
project
)
}
expect
(
subject
.
deploys
).
to
eq
(
1
)
expect
(
subject
.
third
[
:value
]
).
to
eq
(
1
)
end
end
it
"doesn't find commits from other projects"
do
it
"doesn't find commits from other projects"
do
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create
(
:deployment
,
project:
create
(
:project
))
}
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create
(
:deployment
,
project:
create
(
:project
))
}
expect
(
subject
.
deploys
).
to
eq
(
0
)
expect
(
subject
.
third
[
:value
]
).
to
eq
(
0
)
end
end
end
end
end
end
spec/lib/gitlab/cycle_analytics/
review_event
_spec.rb
→
spec/lib/gitlab/cycle_analytics/
staging_event_fetcher
_spec.rb
View file @
745e0f87
require
'spec_helper'
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
ReviewEvent
do
describe
Gitlab
::
CycleAnalytics
::
StagingEventFetcher
do
let
(
:stage_name
)
{
:staging
}
it_behaves_like
'default query config'
do
it_behaves_like
'default query config'
do
it
'has
the
default order'
do
it
'has
a
default order'
do
expect
(
event
.
order
).
to
eq
(
event
.
start_time_attrs
)
expect
(
event
.
order
).
not_to
be_nil
end
end
end
end
end
end
spec/lib/gitlab/cycle_analytics/staging_event_spec.rb
deleted
100644 → 0
View file @
f185d9e9
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
StagingEvent
do
it_behaves_like
'default query config'
do
it
'does not have the default order'
do
expect
(
event
.
order
).
not_to
eq
(
event
.
start_time_attrs
)
end
end
end
spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_stage_spec'
describe
Gitlab
::
CycleAnalytics
::
StagingStage
do
let
(
:stage_name
)
{
:staging
}
it_behaves_like
'base stage'
end
spec/lib/gitlab/cycle_analytics/
code_event
_spec.rb
→
spec/lib/gitlab/cycle_analytics/
test_event_fetcher
_spec.rb
View file @
745e0f87
require
'spec_helper'
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
CodeEvent
do
describe
Gitlab
::
CycleAnalytics
::
TestEventFetcher
do
let
(
:stage_name
)
{
:test
}
it_behaves_like
'default query config'
do
it_behaves_like
'default query config'
do
it
'
does not have the
default order'
do
it
'
has a
default order'
do
expect
(
event
.
order
).
not_to
eq
(
event
.
start_time_attrs
)
expect
(
event
.
order
).
not_to
be_nil
end
end
end
end
end
end
spec/lib/gitlab/cycle_analytics/test_event_spec.rb
deleted
100644 → 0
View file @
f185d9e9
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_event_spec'
describe
Gitlab
::
CycleAnalytics
::
TestEvent
do
it_behaves_like
'default query config'
do
it
'does not have the default order'
do
expect
(
event
.
order
).
not_to
eq
(
event
.
start_time_attrs
)
end
end
end
spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
require
'lib/gitlab/cycle_analytics/shared_stage_spec'
describe
Gitlab
::
CycleAnalytics
::
TestStage
do
let
(
:stage_name
)
{
:test
}
it_behaves_like
'base stage'
end
spec/models/cycle_analytics/code_spec.rb
View file @
745e0f87
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#code', feature: true do
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#code', feature: true do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
subject
{
CycleAnalytics
.
new
(
project
,
user
,
from:
from_date
)
}
subject
{
CycleAnalytics
.
new
(
project
,
from:
from_date
)
}
context
'with deployment'
do
context
'with deployment'
do
generate_cycle_analytics_spec
(
generate_cycle_analytics_spec
(
...
@@ -16,10 +16,10 @@ describe 'CycleAnalytics#code', feature: true do
...
@@ -16,10 +16,10 @@ describe 'CycleAnalytics#code', feature: true do
->
(
context
,
data
)
do
->
(
context
,
data
)
do
context
.
create_commit_referencing_issue
(
data
[
:issue
])
context
.
create_commit_referencing_issue
(
data
[
:issue
])
end
]],
end
]],
end_time_conditions:
[[
"merge request that closes issue is created"
,
end_time_conditions:
[[
"merge request that closes issue is created"
,
->
(
context
,
data
)
do
->
(
context
,
data
)
do
context
.
create_merge_request_closing_issue
(
data
[
:issue
])
context
.
create_merge_request_closing_issue
(
data
[
:issue
])
end
]],
end
]],
post_fn:
->
(
context
,
data
)
do
post_fn:
->
(
context
,
data
)
do
context
.
merge_merge_requests_closing_issue
(
data
[
:issue
])
context
.
merge_merge_requests_closing_issue
(
data
[
:issue
])
context
.
deploy_master
context
.
deploy_master
...
@@ -37,7 +37,7 @@ describe 'CycleAnalytics#code', feature: true do
...
@@ -37,7 +37,7 @@ describe 'CycleAnalytics#code', feature: true do
deploy_master
deploy_master
end
end
expect
(
subject
.
code
).
to
be_nil
expect
(
subject
[
:code
].
median
).
to
be_nil
end
end
end
end
end
end
...
@@ -50,10 +50,10 @@ describe 'CycleAnalytics#code', feature: true do
...
@@ -50,10 +50,10 @@ describe 'CycleAnalytics#code', feature: true do
->
(
context
,
data
)
do
->
(
context
,
data
)
do
context
.
create_commit_referencing_issue
(
data
[
:issue
])
context
.
create_commit_referencing_issue
(
data
[
:issue
])
end
]],
end
]],
end_time_conditions:
[[
"merge request that closes issue is created"
,
end_time_conditions:
[[
"merge request that closes issue is created"
,
->
(
context
,
data
)
do
->
(
context
,
data
)
do
context
.
create_merge_request_closing_issue
(
data
[
:issue
])
context
.
create_merge_request_closing_issue
(
data
[
:issue
])
end
]],
end
]],
post_fn:
->
(
context
,
data
)
do
post_fn:
->
(
context
,
data
)
do
context
.
merge_merge_requests_closing_issue
(
data
[
:issue
])
context
.
merge_merge_requests_closing_issue
(
data
[
:issue
])
end
)
end
)
...
@@ -69,7 +69,7 @@ describe 'CycleAnalytics#code', feature: true do
...
@@ -69,7 +69,7 @@ describe 'CycleAnalytics#code', feature: true do
merge_merge_requests_closing_issue
(
issue
)
merge_merge_requests_closing_issue
(
issue
)
end
end
expect
(
subject
.
code
).
to
be_nil
expect
(
subject
[
:code
].
median
).
to
be_nil
end
end
end
end
end
end
...
...
spec/models/cycle_analytics/issue_spec.rb
View file @
745e0f87
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#issue', models: true do
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#issue', models: true do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
subject
{
CycleAnalytics
.
new
(
project
,
user
,
from:
from_date
)
}
subject
{
CycleAnalytics
.
new
(
project
,
from:
from_date
)
}
generate_cycle_analytics_spec
(
generate_cycle_analytics_spec
(
phase: :issue
,
phase: :issue
,
...
@@ -42,7 +42,7 @@ describe 'CycleAnalytics#issue', models: true do
...
@@ -42,7 +42,7 @@ describe 'CycleAnalytics#issue', models: true do
merge_merge_requests_closing_issue
(
issue
)
merge_merge_requests_closing_issue
(
issue
)
end
end
expect
(
subject
.
issue
).
to
be_nil
expect
(
subject
[
:issue
].
median
).
to
be_nil
end
end
end
end
end
end
spec/models/cycle_analytics/plan_spec.rb
View file @
745e0f87
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#plan', feature: true do
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#plan', feature: true do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
subject
{
CycleAnalytics
.
new
(
project
,
user
,
from:
from_date
)
}
subject
{
CycleAnalytics
.
new
(
project
,
from:
from_date
)
}
generate_cycle_analytics_spec
(
generate_cycle_analytics_spec
(
phase: :plan
,
phase: :plan
,
...
@@ -44,7 +44,7 @@ describe 'CycleAnalytics#plan', feature: true do
...
@@ -44,7 +44,7 @@ describe 'CycleAnalytics#plan', feature: true do
create_merge_request_closing_issue
(
issue
,
source_branch:
branch_name
)
create_merge_request_closing_issue
(
issue
,
source_branch:
branch_name
)
merge_merge_requests_closing_issue
(
issue
)
merge_merge_requests_closing_issue
(
issue
)
expect
(
subject
.
issue
).
to
be_nil
expect
(
subject
[
:issue
].
median
).
to
be_nil
end
end
end
end
end
end
spec/models/cycle_analytics/production_spec.rb
View file @
745e0f87
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#production', feature: true do
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#production', feature: true do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
subject
{
CycleAnalytics
.
new
(
project
,
user
,
from:
from_date
)
}
subject
{
CycleAnalytics
.
new
(
project
,
from:
from_date
)
}
generate_cycle_analytics_spec
(
generate_cycle_analytics_spec
(
phase: :production
,
phase: :production
,
...
@@ -35,7 +35,7 @@ describe 'CycleAnalytics#production', feature: true do
...
@@ -35,7 +35,7 @@ describe 'CycleAnalytics#production', feature: true do
deploy_master
deploy_master
end
end
expect
(
subject
.
productio
n
).
to
be_nil
expect
(
subject
[
:production
].
media
n
).
to
be_nil
end
end
end
end
...
@@ -48,7 +48,7 @@ describe 'CycleAnalytics#production', feature: true do
...
@@ -48,7 +48,7 @@ describe 'CycleAnalytics#production', feature: true do
deploy_master
(
environment:
'staging'
)
deploy_master
(
environment:
'staging'
)
end
end
expect
(
subject
.
productio
n
).
to
be_nil
expect
(
subject
[
:production
].
media
n
).
to
be_nil
end
end
end
end
end
end
spec/models/cycle_analytics/review_spec.rb
View file @
745e0f87
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#review', feature: true do
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#review', feature: true do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
subject
{
CycleAnalytics
.
new
(
project
,
user
,
from:
from_date
)
}
subject
{
CycleAnalytics
.
new
(
project
,
from:
from_date
)
}
generate_cycle_analytics_spec
(
generate_cycle_analytics_spec
(
phase: :review
,
phase: :review
,
...
@@ -27,7 +27,7 @@ describe 'CycleAnalytics#review', feature: true do
...
@@ -27,7 +27,7 @@ describe 'CycleAnalytics#review', feature: true do
MergeRequests
::
MergeService
.
new
(
project
,
user
).
execute
(
create
(
:merge_request
))
MergeRequests
::
MergeService
.
new
(
project
,
user
).
execute
(
create
(
:merge_request
))
end
end
expect
(
subject
.
review
).
to
be_nil
expect
(
subject
[
:review
].
median
).
to
be_nil
end
end
end
end
end
end
spec/models/cycle_analytics/staging_spec.rb
View file @
745e0f87
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#staging', feature: true do
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#staging', feature: true do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
subject
{
CycleAnalytics
.
new
(
project
,
user
,
from:
from_date
)
}
subject
{
CycleAnalytics
.
new
(
project
,
from:
from_date
)
}
generate_cycle_analytics_spec
(
generate_cycle_analytics_spec
(
phase: :staging
,
phase: :staging
,
...
@@ -45,7 +45,7 @@ describe 'CycleAnalytics#staging', feature: true do
...
@@ -45,7 +45,7 @@ describe 'CycleAnalytics#staging', feature: true do
deploy_master
deploy_master
end
end
expect
(
subject
.
staging
).
to
be_nil
expect
(
subject
[
:staging
].
median
).
to
be_nil
end
end
end
end
...
@@ -58,7 +58,7 @@ describe 'CycleAnalytics#staging', feature: true do
...
@@ -58,7 +58,7 @@ describe 'CycleAnalytics#staging', feature: true do
deploy_master
(
environment:
'staging'
)
deploy_master
(
environment:
'staging'
)
end
end
expect
(
subject
.
staging
).
to
be_nil
expect
(
subject
[
:staging
].
median
).
to
be_nil
end
end
end
end
end
end
spec/models/cycle_analytics/test_spec.rb
View file @
745e0f87
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#test', feature: true do
...
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#test', feature: true do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:from_date
)
{
10
.
days
.
ago
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
subject
{
CycleAnalytics
.
new
(
project
,
user
,
from:
from_date
)
}
subject
{
CycleAnalytics
.
new
(
project
,
from:
from_date
)
}
generate_cycle_analytics_spec
(
generate_cycle_analytics_spec
(
phase: :test
,
phase: :test
,
...
@@ -35,7 +35,7 @@ describe 'CycleAnalytics#test', feature: true do
...
@@ -35,7 +35,7 @@ describe 'CycleAnalytics#test', feature: true do
merge_merge_requests_closing_issue
(
issue
)
merge_merge_requests_closing_issue
(
issue
)
end
end
expect
(
subject
.
test
).
to
be_nil
expect
(
subject
[
:test
].
median
).
to
be_nil
end
end
end
end
...
@@ -48,7 +48,7 @@ describe 'CycleAnalytics#test', feature: true do
...
@@ -48,7 +48,7 @@ describe 'CycleAnalytics#test', feature: true do
pipeline
.
succeed!
pipeline
.
succeed!
end
end
expect
(
subject
.
test
).
to
be_nil
expect
(
subject
[
:test
].
median
).
to
be_nil
end
end
end
end
...
@@ -65,7 +65,7 @@ describe 'CycleAnalytics#test', feature: true do
...
@@ -65,7 +65,7 @@ describe 'CycleAnalytics#test', feature: true do
merge_merge_requests_closing_issue
(
issue
)
merge_merge_requests_closing_issue
(
issue
)
end
end
expect
(
subject
.
test
).
to
be_nil
expect
(
subject
[
:test
].
median
).
to
be_nil
end
end
end
end
...
@@ -82,7 +82,7 @@ describe 'CycleAnalytics#test', feature: true do
...
@@ -82,7 +82,7 @@ describe 'CycleAnalytics#test', feature: true do
merge_merge_requests_closing_issue
(
issue
)
merge_merge_requests_closing_issue
(
issue
)
end
end
expect
(
subject
.
test
).
to
be_nil
expect
(
subject
[
:test
].
median
).
to
be_nil
end
end
end
end
end
end
spec/serializers/analytics_stage_serializer_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
describe
AnalyticsStageSerializer
do
let
(
:serializer
)
do
described_class
.
new
.
represent
(
resource
)
end
let
(
:json
)
{
serializer
.
as_json
}
let
(
:resource
)
{
Gitlab
::
CycleAnalytics
::
CodeStage
.
new
(
project:
double
,
options:
{})
}
before
do
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
BaseStage
).
to
receive
(
:median
).
and_return
(
1.12
)
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
BaseEventFetcher
).
to
receive
(
:event_result
).
and_return
({})
end
it
'it generates payload for single object'
do
expect
(
json
).
to
be_kind_of
Hash
end
it
'contains important elements of AnalyticsStage'
do
expect
(
json
).
to
include
(
:title
,
:description
,
:value
)
end
end
spec/serializers/analytics_summary_serializer_spec.rb
0 → 100644
View file @
745e0f87
require
'spec_helper'
describe
AnalyticsSummarySerializer
do
let
(
:serializer
)
do
described_class
.
new
.
represent
(
resource
)
end
let
(
:json
)
{
serializer
.
as_json
}
let
(
:project
)
{
create
(
:empty_project
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:resource
)
do
Gitlab
::
CycleAnalytics
::
Summary
::
Issue
.
new
(
project:
double
,
from:
1
.
day
.
ago
,
current_user:
user
)
end
before
do
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
Summary
::
Issue
).
to
receive
(
:value
).
and_return
(
1.12
)
end
it
'it generates payload for single object'
do
expect
(
json
).
to
be_kind_of
Hash
end
it
'contains important elements of AnalyticsStage'
do
expect
(
json
).
to
include
(
:title
,
:value
)
end
end
spec/support/cycle_analytics_helpers/test_generation.rb
View file @
745e0f87
...
@@ -2,7 +2,6 @@
...
@@ -2,7 +2,6 @@
# Note: The ABC size is large here because we have a method generating test cases with
# Note: The ABC size is large here because we have a method generating test cases with
# multiple nested contexts. This shouldn't count as a violation.
# multiple nested contexts. This shouldn't count as a violation.
module
CycleAnalyticsHelpers
module
CycleAnalyticsHelpers
module
TestGeneration
module
TestGeneration
# Generate the most common set of specs that all cycle analytics phases need to have.
# Generate the most common set of specs that all cycle analytics phases need to have.
...
@@ -51,7 +50,7 @@ module CycleAnalyticsHelpers
...
@@ -51,7 +50,7 @@ module CycleAnalyticsHelpers
end
end
median_time_difference
=
time_differences
.
sort
[
2
]
median_time_difference
=
time_differences
.
sort
[
2
]
expect
(
subject
.
send
(
phase
)
).
to
be_within
(
5
).
of
(
median_time_difference
)
expect
(
subject
[
phase
].
median
).
to
be_within
(
5
).
of
(
median_time_difference
)
end
end
context
"when the data belongs to another project"
do
context
"when the data belongs to another project"
do
...
@@ -83,7 +82,7 @@ module CycleAnalyticsHelpers
...
@@ -83,7 +82,7 @@ module CycleAnalyticsHelpers
# Turn off the stub before checking assertions
# Turn off the stub before checking assertions
allow
(
self
).
to
receive
(
:project
).
and_call_original
allow
(
self
).
to
receive
(
:project
).
and_call_original
expect
(
subject
.
send
(
phase
)
).
to
be_nil
expect
(
subject
[
phase
].
median
).
to
be_nil
end
end
end
end
...
@@ -106,7 +105,7 @@ module CycleAnalyticsHelpers
...
@@ -106,7 +105,7 @@ module CycleAnalyticsHelpers
Timecop
.
freeze
(
end_time
+
1
.
day
)
{
post_fn
[
self
,
data
]
}
if
post_fn
Timecop
.
freeze
(
end_time
+
1
.
day
)
{
post_fn
[
self
,
data
]
}
if
post_fn
expect
(
subject
.
send
(
phase
)
).
to
be_nil
expect
(
subject
[
phase
].
median
).
to
be_nil
end
end
end
end
end
end
...
@@ -126,7 +125,7 @@ module CycleAnalyticsHelpers
...
@@ -126,7 +125,7 @@ module CycleAnalyticsHelpers
Timecop
.
freeze
(
end_time
+
1
.
day
)
{
post_fn
[
self
,
data
]
}
if
post_fn
Timecop
.
freeze
(
end_time
+
1
.
day
)
{
post_fn
[
self
,
data
]
}
if
post_fn
end
end
expect
(
subject
.
send
(
phase
)
).
to
be_nil
expect
(
subject
[
phase
].
median
).
to
be_nil
end
end
end
end
end
end
...
@@ -145,7 +144,7 @@ module CycleAnalyticsHelpers
...
@@ -145,7 +144,7 @@ module CycleAnalyticsHelpers
post_fn
[
self
,
data
]
if
post_fn
post_fn
[
self
,
data
]
if
post_fn
end
end
expect
(
subject
.
send
(
phase
)
).
to
be_nil
expect
(
subject
[
phase
].
median
).
to
be_nil
end
end
end
end
end
end
...
@@ -153,7 +152,7 @@ module CycleAnalyticsHelpers
...
@@ -153,7 +152,7 @@ module CycleAnalyticsHelpers
context
"when none of the start / end conditions are matched"
do
context
"when none of the start / end conditions are matched"
do
it
"returns nil"
do
it
"returns nil"
do
expect
(
subject
.
send
(
phase
)
).
to
be_nil
expect
(
subject
[
phase
].
median
).
to
be_nil
end
end
end
end
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment