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
b115baff
Commit
b115baff
authored
Jun 14, 2021
by
Adam Hegyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move lead and cycle time classes out from Group NS
parent
77d8e925
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
293 additions
and
100 deletions
+293
-100
app/models/analytics/cycle_analytics/project_level.rb
app/models/analytics/cycle_analytics/project_level.rb
+1
-0
ee/app/controllers/ee/projects/analytics/cycle_analytics/summary_controller.rb
.../projects/analytics/cycle_analytics/summary_controller.rb
+10
-1
ee/app/models/analytics/cycle_analytics/group_level.rb
ee/app/models/analytics/cycle_analytics/group_level.rb
+7
-4
ee/app/models/ee/analytics/cycle_analytics/project_level.rb
ee/app/models/ee/analytics/cycle_analytics/project_level.rb
+19
-0
ee/config/routes/project.rb
ee/config/routes/project.rb
+4
-0
ee/lib/gitlab/analytics/cycle_analytics/summary/base_time.rb
ee/lib/gitlab/analytics/cycle_analytics/summary/base_time.rb
+55
-0
ee/lib/gitlab/analytics/cycle_analytics/summary/cycle_time.rb
...ib/gitlab/analytics/cycle_analytics/summary/cycle_time.rb
+23
-0
ee/lib/gitlab/analytics/cycle_analytics/summary/group/base_time.rb
...tlab/analytics/cycle_analytics/summary/group/base_time.rb
+0
-57
ee/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary.rb
...ytics/cycle_analytics/summary/group/stage_time_summary.rb
+30
-32
ee/lib/gitlab/analytics/cycle_analytics/summary/lead_time.rb
ee/lib/gitlab/analytics/cycle_analytics/summary/lead_time.rb
+23
-0
ee/lib/gitlab/analytics/cycle_analytics/summary/stage_time_summary.rb
...b/analytics/cycle_analytics/summary/stage_time_summary.rb
+48
-0
ee/spec/controllers/projects/analytics/cycle_analytics/summary_controller_spec.rb
...ects/analytics/cycle_analytics/summary_controller_spec.rb
+67
-2
ee/spec/lib/gitlab/analytics/cycle_analytics/summary/stage_time_summary_spec.rb
...lytics/cycle_analytics/summary/stage_time_summary_spec.rb
+6
-4
No files found.
app/models/analytics/cycle_analytics/project_level.rb
View file @
b115baff
...
...
@@ -47,3 +47,4 @@ module Analytics
end
end
end
Analytics
::
CycleAnalytics
::
ProjectLevel
.
prepend_mod_with
(
'Analytics::CycleAnalytics::ProjectLevel'
)
ee/app/controllers/ee/projects/analytics/cycle_analytics/summary_controller.rb
View file @
b115baff
# frozen_string_literal: true
module
EE::Projects::Analytics::CycleAnalytics::SummaryController
extend
ActiveSupport
::
Concern
extend
::
Gitlab
::
Utils
::
Override
def
time_summary
if
project
.
licensed_feature_available?
(
:cycle_analytics_for_projects
)
render
json:
project_level
.
time_summary
else
render_404
end
end
private
override
:allowed_params
def
allowed_params
return
super
unless
@project
.
licensed_feature_available?
(
:cycle_analytics_for_projects
)
# rubocop: disable Gitlab/ModuleWithInstanceVariables
return
super
unless
project
.
licensed_feature_available?
(
:cycle_analytics_for_projects
)
request_params
.
to_data_collector_params
end
...
...
ee/app/models/analytics/cycle_analytics/group_level.rb
View file @
b115baff
...
...
@@ -18,10 +18,13 @@ module Analytics
end
def
time_summary
@time_summary
||=
Gitlab
::
Analytics
::
CycleAnalytics
::
Summary
::
Group
::
StageTimeSummary
.
new
(
group
,
options:
options
)
.
data
@time_summary
||=
begin
stage
=
::
Analytics
::
CycleAnalytics
::
GroupStage
.
new
(
group:
group
)
Gitlab
::
Analytics
::
CycleAnalytics
::
Summary
::
StageTimeSummary
.
new
(
stage
,
options:
options
)
.
data
end
end
end
end
...
...
ee/app/models/ee/analytics/cycle_analytics/project_level.rb
0 → 100644
View file @
b115baff
# frozen_string_literal: true
module
EE
module
Analytics
module
CycleAnalytics
module
ProjectLevel
def
time_summary
@time_summary
||=
begin
stage
=
::
Analytics
::
CycleAnalytics
::
ProjectStage
.
new
(
project:
project
)
::
Gitlab
::
Analytics
::
CycleAnalytics
::
Summary
::
StageTimeSummary
.
new
(
stage
,
options:
options
)
.
data
end
end
end
end
end
end
ee/config/routes/project.rb
View file @
b115baff
...
...
@@ -95,6 +95,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources
:code_reviews
,
only:
[
:index
]
resource
:issues_analytics
,
only:
[
:show
]
resource
:merge_request_analytics
,
only: :show
scope
module: :cycle_analytics
,
as:
'cycle_analytics'
,
path:
'value_stream_analytics'
do
get
'/time_summary'
=>
'summary#time_summary'
end
end
resources
:approvers
,
only: :destroy
...
...
ee/lib/gitlab/analytics/cycle_analytics/summary/base_time.rb
0 → 100644
View file @
b115baff
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
Summary
class
BaseTime
def
initialize
(
stage
:,
current_user
:,
options
:)
@stage
=
stage
@current_user
=
current_user
@options
=
options
assign_event_identifiers
end
def
value
@value
||=
Gitlab
::
CycleAnalytics
::
Summary
::
Value
::
PrettyNumeric
.
new
(
data_collector
.
median
.
days
&
.
round
(
1
))
end
def
unit
n_
(
'day'
,
'days'
,
value
)
end
def
start_event_identifier
raise
NotImplementedError
,
"Expected
#{
self
.
name
}
to implement start_event_identifier"
end
def
end_event_identifier
raise
NotImplementedError
,
"Expected
#{
self
.
name
}
to implement end_event_identifier"
end
private
def
assign_event_identifiers
@stage
.
start_event_identifier
=
start_event_identifier
@stage
.
end_event_identifier
=
end_event_identifier
end
def
data_collector
Gitlab
::
Analytics
::
CycleAnalytics
::
DataCollector
.
new
(
stage:
@stage
,
params:
{
from:
@options
[
:from
],
to:
@options
[
:to
]
||
DateTime
.
now
,
project_ids:
@options
[
:projects
],
end_event_filter:
@options
[
:end_event_filter
],
current_user:
@current_user
}.
merge
(
@options
.
slice
(
*::
Gitlab
::
Analytics
::
CycleAnalytics
::
RequestParams
::
FINDER_PARAM_NAMES
))
)
end
end
end
end
end
end
ee/lib/gitlab/analytics/cycle_analytics/summary/
group/
cycle_time.rb
→
ee/lib/gitlab/analytics/cycle_analytics/summary/cycle_time.rb
View file @
b115baff
...
...
@@ -4,19 +4,17 @@ module Gitlab
module
Analytics
module
CycleAnalytics
module
Summary
module
Group
class
CycleTime
<
BaseTime
def
title
_
(
'Cycle Time'
)
end
class
CycleTime
<
BaseTime
def
title
_
(
'Cycle Time'
)
end
def
start_event_identifier
:issue_first_mentioned_in_commit
end
def
start_event_identifier
:issue_first_mentioned_in_commit
end
def
end_event_identifier
:issue_closed
end
def
end_event_identifier
:issue_closed
end
end
end
...
...
ee/lib/gitlab/analytics/cycle_analytics/summary/group/base_time.rb
deleted
100644 → 0
View file @
77d8e925
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
Summary
module
Group
class
BaseTime
<
Group
::
Base
def
initialize
(
group
:,
current_user
:,
options
:)
@group
=
group
@current_user
=
current_user
@options
=
options
end
def
value
@value
||=
Gitlab
::
CycleAnalytics
::
Summary
::
Value
::
PrettyNumeric
.
new
(
data_collector
.
median
.
days
&
.
round
(
1
))
end
def
unit
n_
(
'day'
,
'days'
,
value
)
end
def
start_event_identifier
raise
NotImplementedError
,
"Expected
#{
self
.
name
}
to implement start_event_identifier"
end
def
end_event_identifier
raise
NotImplementedError
,
"Expected
#{
self
.
name
}
to implement end_event_identifier"
end
private
def
stage
::
Analytics
::
CycleAnalytics
::
GroupStage
.
new
(
group:
@group
,
start_event_identifier:
start_event_identifier
,
end_event_identifier:
end_event_identifier
)
end
def
data_collector
Gitlab
::
Analytics
::
CycleAnalytics
::
DataCollector
.
new
(
stage:
stage
,
params:
{
from:
@options
[
:from
],
to:
@options
[
:to
]
||
DateTime
.
now
,
project_ids:
@options
[
:projects
],
end_event_filter:
@options
[
:end_event_filter
],
current_user:
@current_user
}.
merge
(
@options
.
slice
(
*::
Gitlab
::
Analytics
::
CycleAnalytics
::
RequestParams
::
FINDER_PARAM_NAMES
))
)
end
end
end
end
end
end
end
ee/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary.rb
View file @
b115baff
...
...
@@ -4,44 +4,42 @@ module Gitlab
module
Analytics
module
CycleAnalytics
module
Summary
module
Group
class
StageTimeSummary
attr_reader
:group
,
:current_user
,
:options
class
StageTimeSummary
attr_reader
:stage
,
:current_user
,
:options
def
initialize
(
group
,
options
:)
@group
=
group
@current_user
=
options
[
:current_user
]
@options
=
options
end
def
initialize
(
stage
,
options
:)
@stage
=
stage
@current_user
=
options
[
:current_user
]
@options
=
options
end
def
data
[
lead_time
,
cycle_time
]
end
def
data
[
lead_time
,
cycle_time
]
end
private
private
def
lead_time
serialize
(
Summary
::
Group
::
LeadTime
.
new
(
group:
group
,
current_user:
current_user
,
options:
options
),
with_unit:
true
)
end
def
lead_time
serialize
(
Summary
::
LeadTime
.
new
(
stage:
stage
,
current_user:
current_user
,
options:
options
),
with_unit:
true
)
end
def
cycle_time
serialize
(
Summary
::
Group
::
CycleTime
.
new
(
group:
group
,
current_user:
current_user
,
options:
options
),
with_unit:
true
)
end
def
cycle_time
serialize
(
Summary
::
CycleTime
.
new
(
stage:
stage
,
current_user:
current_user
,
options:
options
),
with_unit:
true
)
end
def
serialize
(
summary_object
,
with_unit:
false
)
AnalyticsSummarySerializer
.
new
.
represent
(
summary_object
,
with_unit:
with_unit
)
end
def
serialize
(
summary_object
,
with_unit:
false
)
AnalyticsSummarySerializer
.
new
.
represent
(
summary_object
,
with_unit:
with_unit
)
end
end
end
...
...
ee/lib/gitlab/analytics/cycle_analytics/summary/
group/
lead_time.rb
→
ee/lib/gitlab/analytics/cycle_analytics/summary/lead_time.rb
View file @
b115baff
...
...
@@ -4,19 +4,17 @@ module Gitlab
module
Analytics
module
CycleAnalytics
module
Summary
module
Group
class
LeadTime
<
BaseTime
def
title
_
(
'Lead Time'
)
end
class
LeadTime
<
BaseTime
def
title
_
(
'Lead Time'
)
end
def
start_event_identifier
:issue_created
end
def
start_event_identifier
:issue_created
end
def
end_event_identifier
:issue_closed
end
def
end_event_identifier
:issue_closed
end
end
end
...
...
ee/lib/gitlab/analytics/cycle_analytics/summary/stage_time_summary.rb
0 → 100644
View file @
b115baff
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
Summary
class
StageTimeSummary
attr_reader
:stage
,
:current_user
,
:options
def
initialize
(
stage
,
options
:)
@stage
=
stage
@current_user
=
options
[
:current_user
]
@options
=
options
end
def
data
[
lead_time
,
cycle_time
]
end
private
def
lead_time
serialize
(
Summary
::
LeadTime
.
new
(
stage:
stage
,
current_user:
current_user
,
options:
options
),
with_unit:
true
)
end
def
cycle_time
serialize
(
Summary
::
CycleTime
.
new
(
stage:
stage
,
current_user:
current_user
,
options:
options
),
with_unit:
true
)
end
def
serialize
(
summary_object
,
with_unit:
false
)
AnalyticsSummarySerializer
.
new
.
represent
(
summary_object
,
with_unit:
with_unit
)
end
end
end
end
end
end
ee/spec/controllers/projects/analytics/cycle_analytics/summary_controller_spec.rb
View file @
b115baff
...
...
@@ -20,15 +20,16 @@ RSpec.describe Projects::Analytics::CycleAnalytics::SummaryController do
subject
{
get
:show
,
params:
params
}
before
do
project
.
add_reporter
(
user
)
params
[
:author_username
]
=
issue_with_author
.
author
.
username
project
.
add_reporter
(
user
)
end
context
'when cycle_analytics_for_projects feature is available'
do
before
do
stub_licensed_features
(
cycle_analytics_for_projects:
true
)
end
it
'filters by author username'
do
subject
...
...
@@ -50,4 +51,68 @@ RSpec.describe Projects::Analytics::CycleAnalytics::SummaryController do
end
end
end
describe
'GET "time_summary"'
do
let_it_be
(
:first_mentioned_in_commit_at
)
{
Date
.
new
(
2015
,
1
,
1
)
}
let_it_be
(
:closed_at
)
{
Date
.
new
(
2015
,
2
,
1
)
}
let_it_be
(
:closed_issue
)
do
create
(
:issue
,
project:
project
,
created_at:
closed_at
,
closed_at:
closed_at
).
tap
do
|
issue
|
issue
.
metrics
.
update!
(
first_mentioned_in_commit_at:
first_mentioned_in_commit_at
)
end
end
subject
{
get
:time_summary
,
params:
params
}
context
'when cycle_analytics_for_projects feature is available'
do
before
do
stub_licensed_features
(
cycle_analytics_for_projects:
true
)
project
.
add_reporter
(
user
)
end
it
'succeeds'
do
subject
expect
(
response
).
to
be_successful
end
it
'returns correct value'
do
expected_cycle_time
=
(
closed_at
-
first_mentioned_in_commit_at
).
to_i
subject
expect
(
json_response
.
last
[
"value"
].
to_i
).
to
eq
(
expected_cycle_time
)
end
context
'when analytics_disabled features are disabled'
do
it
'renders 404'
do
project
.
add_reporter
(
user
)
project
.
project_feature
.
update!
(
analytics_access_level:
ProjectFeature
::
DISABLED
)
subject
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
end
context
'when user is not part of the project'
do
it
'renders 404'
do
subject
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
context
'when the feature is not available'
do
it
'renders 404'
do
project
.
add_reporter
(
user
)
subject
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
end
end
ee/spec/lib/gitlab/analytics/cycle_analytics/summary/
group/
stage_time_summary_spec.rb
→
ee/spec/lib/gitlab/analytics/cycle_analytics/summary/stage_time_summary_spec.rb
View file @
b115baff
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Gitlab
::
Analytics
::
CycleAnalytics
::
Summary
::
Group
::
StageTimeSummary
do
RSpec
.
describe
Gitlab
::
Analytics
::
CycleAnalytics
::
Summary
::
StageTimeSummary
do
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:project
)
{
create
(
:project
,
:repository
,
namespace:
group
)
}
let_it_be
(
:project_2
)
{
create
(
:project
,
:repository
,
namespace:
group
)
}
let_it_be
(
:user
)
{
create
(
:user
)
}
let
(
:from
)
{
1
.
day
.
ago
}
let
(
:to
)
{
nil
}
let
(
:options
)
{
{
from:
from
,
to:
to
,
current_user:
user
}
}
let
(
:stage
)
{
Analytics
::
CycleAnalytics
::
GroupStage
.
new
(
group:
group
)
}
subject
{
described_class
.
new
(
group
,
options:
options
).
data
}
subject
{
described_class
.
new
(
stage
,
options:
options
).
data
}
around
do
|
example
|
freeze_time
{
example
.
run
}
...
...
@@ -101,7 +103,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageTimeSumma
create
(
:closed_issue
,
created_at:
3
.
days
.
ago
,
closed_at:
Time
.
zone
.
now
,
project:
create
(
:project
,
namespace:
group
))
end
subject
{
described_class
.
new
(
group
,
options:
{
from:
from
,
current_user:
user
,
projects:
[
project
.
id
,
project_2
.
id
]
}).
data
}
subject
{
described_class
.
new
(
stage
,
options:
{
from:
from
,
current_user:
user
,
projects:
[
project
.
id
,
project_2
.
id
]
}).
data
}
it
'finds the lead time of issues from those projects'
do
# Median of 1, 2, 4, not including new issue
...
...
@@ -178,7 +180,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageTimeSumma
issue_4
.
metrics
.
update!
(
first_mentioned_in_commit_at:
3
.
days
.
ago
)
end
subject
{
described_class
.
new
(
group
,
options:
{
from:
from
,
current_user:
user
,
projects:
[
project
.
id
,
project_2
.
id
]
}).
data
}
subject
{
described_class
.
new
(
stage
,
options:
{
from:
from
,
current_user:
user
,
projects:
[
project
.
id
,
project_2
.
id
]
}).
data
}
it
'finds the cycle time of issues from those projects'
do
# Median of 1, 2, 4, not including new issue
...
...
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