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
06f1ddbf
Commit
06f1ddbf
authored
Aug 23, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab-ce master
parents
5a9ca9e4
3203367e
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
635 additions
and
0 deletions
+635
-0
app/models/analytics/cycle_analytics/project_stage.rb
app/models/analytics/cycle_analytics/project_stage.rb
+5
-0
app/models/concerns/analytics/cycle_analytics/stage.rb
app/models/concerns/analytics/cycle_analytics/stage.rb
+68
-0
lib/gitlab/analytics/cycle_analytics/default_stages.rb
lib/gitlab/analytics/cycle_analytics/default_stages.rb
+98
-0
lib/gitlab/analytics/cycle_analytics/stage_events.rb
lib/gitlab/analytics/cycle_analytics/stage_events.rb
+71
-0
lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb
...nalytics/cycle_analytics/stage_events/code_stage_start.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/issue_created.rb
...b/analytics/cycle_analytics/stage_events/issue_created.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit.rb
...analytics/stage_events/issue_first_mentioned_in_commit.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end.rb
...analytics/cycle_analytics/stage_events/issue_stage_end.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created.rb
...ics/cycle_analytics/stage_events/merge_request_created.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production.rb
...tage_events/merge_request_first_deployed_to_production.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished.rb
...alytics/stage_events/merge_request_last_build_finished.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started.rb
...nalytics/stage_events/merge_request_last_build_started.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged.rb
...tics/cycle_analytics/stage_events/merge_request_merged.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start.rb
...nalytics/cycle_analytics/stage_events/plan_stage_start.rb
+23
-0
lib/gitlab/analytics/cycle_analytics/stage_events/simple_stage_event.rb
...lytics/cycle_analytics/stage_events/simple_stage_event.rb
+13
-0
lib/gitlab/analytics/cycle_analytics/stage_events/stage_event.rb
...lab/analytics/cycle_analytics/stage_events/stage_event.rb
+28
-0
locale/gitlab.pot
locale/gitlab.pot
+24
-0
spec/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event_spec.rb
...nalytics/cycle_analytics/stage_events/stage_event_spec.rb
+10
-0
spec/models/analytics/cycle_analytics/project_stage_spec.rb
spec/models/analytics/cycle_analytics/project_stage_spec.rb
+14
-0
spec/support/shared_examples/cycle_analytics_stage_examples.rb
...support/shared_examples/cycle_analytics_stage_examples.rb
+74
-0
No files found.
app/models/analytics/cycle_analytics/project_stage.rb
View file @
06f1ddbf
...
@@ -3,7 +3,12 @@
...
@@ -3,7 +3,12 @@
module
Analytics
module
Analytics
module
CycleAnalytics
module
CycleAnalytics
class
ProjectStage
<
ApplicationRecord
class
ProjectStage
<
ApplicationRecord
include
Analytics
::
CycleAnalytics
::
Stage
validates
:project
,
presence:
true
belongs_to
:project
belongs_to
:project
alias_attribute
:parent
,
:project
end
end
end
end
end
end
app/models/concerns/analytics/cycle_analytics/stage.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Analytics
module
CycleAnalytics
module
Stage
extend
ActiveSupport
::
Concern
included
do
validates
:name
,
presence:
true
validates
:start_event_identifier
,
presence:
true
validates
:end_event_identifier
,
presence:
true
validate
:validate_stage_event_pairs
enum
start_event_identifier:
Gitlab
::
Analytics
::
CycleAnalytics
::
StageEvents
.
to_enum
,
_prefix: :start_event_identifier
enum
end_event_identifier:
Gitlab
::
Analytics
::
CycleAnalytics
::
StageEvents
.
to_enum
,
_prefix: :end_event_identifier
alias_attribute
:custom_stage?
,
:custom
end
def
parent
=
(
_
)
raise
NotImplementedError
end
def
parent
raise
NotImplementedError
end
def
start_event
Gitlab
::
Analytics
::
CycleAnalytics
::
StageEvents
[
start_event_identifier
].
new
(
params_for_start_event
)
end
def
end_event
Gitlab
::
Analytics
::
CycleAnalytics
::
StageEvents
[
end_event_identifier
].
new
(
params_for_end_event
)
end
def
params_for_start_event
{}
end
def
params_for_end_event
{}
end
def
default_stage?
!
custom
end
# The model that is going to be queried, Issue or MergeRequest
def
subject_model
start_event
.
object_type
end
private
def
validate_stage_event_pairs
return
if
start_event_identifier
.
nil?
||
end_event_identifier
.
nil?
unless
pairing_rules
.
fetch
(
start_event
.
class
,
[]).
include?
(
end_event
.
class
)
errors
.
add
(
:end_event
,
:not_allowed_for_the_given_start_event
)
end
end
def
pairing_rules
Gitlab
::
Analytics
::
CycleAnalytics
::
StageEvents
.
pairing_rules
end
end
end
end
lib/gitlab/analytics/cycle_analytics/default_stages.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
# This module represents the default Cycle Analytics stages that are currently provided by CE
# Each method returns a hash that can be used to build a new stage object.
#
# Example:
#
# params = Gitlab::Analytics::CycleAnalytics::DefaultStages.params_for_issue_stage
# Analytics::CycleAnalytics::ProjectStage.new(params)
module
Gitlab
module
Analytics
module
CycleAnalytics
module
DefaultStages
def
self
.
all
[
params_for_issue_stage
,
params_for_plan_stage
,
params_for_code_stage
,
params_for_test_stage
,
params_for_review_stage
,
params_for_staging_stage
,
params_for_production_stage
]
end
def
self
.
params_for_issue_stage
{
name:
'issue'
,
custom:
false
,
# this stage won't be customizable, we provide it as it is
relative_position:
1
,
# when opening the CycleAnalytics page in CE, this stage will be the first item
start_event_identifier: :issue_created
,
# IssueCreated class is used as start event
end_event_identifier: :issue_stage_end
# IssueStageEnd class is used as end event
}
end
def
self
.
params_for_plan_stage
{
name:
'plan'
,
custom:
false
,
relative_position:
2
,
start_event_identifier: :plan_stage_start
,
end_event_identifier: :issue_first_mentioned_in_commit
}
end
def
self
.
params_for_code_stage
{
name:
'code'
,
custom:
false
,
relative_position:
3
,
start_event_identifier: :code_stage_start
,
end_event_identifier: :merge_request_created
}
end
def
self
.
params_for_test_stage
{
name:
'test'
,
custom:
false
,
relative_position:
4
,
start_event_identifier: :merge_request_last_build_started
,
end_event_identifier: :merge_request_last_build_finished
}
end
def
self
.
params_for_review_stage
{
name:
'review'
,
custom:
false
,
relative_position:
5
,
start_event_identifier: :merge_request_created
,
end_event_identifier: :merge_request_merged
}
end
def
self
.
params_for_staging_stage
{
name:
'staging'
,
custom:
false
,
relative_position:
6
,
start_event_identifier: :merge_request_merged
,
end_event_identifier: :merge_request_first_deployed_to_production
}
end
def
self
.
params_for_production_stage
{
name:
'production'
,
custom:
false
,
relative_position:
7
,
start_event_identifier: :merge_request_merged
,
end_event_identifier: :merge_request_first_deployed_to_production
}
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
# Convention:
# Issue: < 100
# MergeRequest: >= 100 && < 1000
# Custom events for default stages: >= 1000 (legacy)
ENUM_MAPPING
=
{
StageEvents
::
IssueCreated
=>
1
,
StageEvents
::
IssueFirstMentionedInCommit
=>
2
,
StageEvents
::
MergeRequestCreated
=>
100
,
StageEvents
::
MergeRequestFirstDeployedToProduction
=>
101
,
StageEvents
::
MergeRequestLastBuildFinished
=>
102
,
StageEvents
::
MergeRequestLastBuildStarted
=>
103
,
StageEvents
::
MergeRequestMerged
=>
104
,
StageEvents
::
CodeStageStart
=>
1_000
,
StageEvents
::
IssueStageEnd
=>
1_001
,
StageEvents
::
PlanStageStart
=>
1_002
}.
freeze
EVENTS
=
ENUM_MAPPING
.
keys
.
freeze
# Defines which start_event and end_event pairs are allowed
PAIRING_RULES
=
{
StageEvents
::
PlanStageStart
=>
[
StageEvents
::
IssueFirstMentionedInCommit
],
StageEvents
::
CodeStageStart
=>
[
StageEvents
::
MergeRequestCreated
],
StageEvents
::
IssueCreated
=>
[
StageEvents
::
IssueStageEnd
],
StageEvents
::
MergeRequestCreated
=>
[
StageEvents
::
MergeRequestMerged
],
StageEvents
::
MergeRequestLastBuildStarted
=>
[
StageEvents
::
MergeRequestLastBuildFinished
],
StageEvents
::
MergeRequestMerged
=>
[
StageEvents
::
MergeRequestFirstDeployedToProduction
]
}.
freeze
def
[]
(
identifier
)
events
.
find
{
|
e
|
e
.
identifier
.
to_s
.
eql?
(
identifier
.
to_s
)
}
||
raise
(
KeyError
)
end
# hash for defining ActiveRecord enum: identifier => number
def
to_enum
ENUM_MAPPING
.
each_with_object
({})
{
|
(
k
,
v
),
hash
|
hash
[
k
.
identifier
]
=
v
}
end
# will be overridden in EE with custom events
def
pairing_rules
PAIRING_RULES
end
# will be overridden in EE with custom events
def
events
EVENTS
end
module_function
:[]
,
:to_enum
,
:pairing_rules
,
:events
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
CodeStageStart
<
SimpleStageEvent
def
self
.
name
s_
(
"CycleAnalyticsEvent|Issue first mentioned in a commit"
)
end
def
self
.
identifier
:code_stage_start
end
def
object_type
MergeRequest
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/issue_created.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
IssueCreated
<
SimpleStageEvent
def
self
.
name
s_
(
"CycleAnalyticsEvent|Issue created"
)
end
def
self
.
identifier
:issue_created
end
def
object_type
Issue
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
IssueFirstMentionedInCommit
<
SimpleStageEvent
def
self
.
name
s_
(
"CycleAnalyticsEvent|Issue first mentioned in a commit"
)
end
def
self
.
identifier
:issue_first_mentioned_in_commit
end
def
object_type
Issue
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
IssueStageEnd
<
SimpleStageEvent
def
self
.
name
PlanStageStart
.
name
end
def
self
.
identifier
:issue_stage_end
end
def
object_type
Issue
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
MergeRequestCreated
<
SimpleStageEvent
def
self
.
name
s_
(
"CycleAnalyticsEvent|Merge request created"
)
end
def
self
.
identifier
:merge_request_created
end
def
object_type
MergeRequest
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
MergeRequestFirstDeployedToProduction
<
SimpleStageEvent
def
self
.
name
s_
(
"CycleAnalyticsEvent|Merge request first deployed to production"
)
end
def
self
.
identifier
:merge_request_first_deployed_to_production
end
def
object_type
MergeRequest
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
MergeRequestLastBuildFinished
<
SimpleStageEvent
def
self
.
name
s_
(
"CycleAnalyticsEvent|Merge request last build finish time"
)
end
def
self
.
identifier
:merge_request_last_build_finished
end
def
object_type
MergeRequest
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
MergeRequestLastBuildStarted
<
SimpleStageEvent
def
self
.
name
s_
(
"CycleAnalyticsEvent|Merge request last build start time"
)
end
def
self
.
identifier
:merge_request_last_build_started
end
def
object_type
MergeRequest
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
MergeRequestMerged
<
SimpleStageEvent
def
self
.
name
s_
(
"CycleAnalyticsEvent|Merge request merged"
)
end
def
self
.
identifier
:merge_request_merged
end
def
object_type
MergeRequest
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
class
PlanStageStart
<
SimpleStageEvent
def
self
.
name
s_
(
"CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board"
)
end
def
self
.
identifier
:plan_stage_start
end
def
object_type
Issue
end
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/simple_stage_event.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
# Represents a simple event that usually refers to one database column and does not require additional user input
class
SimpleStageEvent
<
StageEvent
end
end
end
end
end
lib/gitlab/analytics/cycle_analytics/stage_events/stage_event.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
module
Gitlab
module
Analytics
module
CycleAnalytics
module
StageEvents
# Base class for expressing an event that can be used for a stage.
class
StageEvent
def
initialize
(
params
)
@params
=
params
end
def
self
.
name
raise
NotImplementedError
end
def
self
.
identifier
raise
NotImplementedError
end
def
object_type
raise
NotImplementedError
end
end
end
end
end
end
locale/gitlab.pot
View file @
06f1ddbf
...
@@ -4421,6 +4421,30 @@ msgstr ""
...
@@ -4421,6 +4421,30 @@ msgstr ""
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
msgstr ""
msgid "CycleAnalyticsEvent|Issue created"
msgstr ""
msgid "CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board"
msgstr ""
msgid "CycleAnalyticsEvent|Issue first mentioned in a commit"
msgstr ""
msgid "CycleAnalyticsEvent|Merge request created"
msgstr ""
msgid "CycleAnalyticsEvent|Merge request first deployed to production"
msgstr ""
msgid "CycleAnalyticsEvent|Merge request last build finish time"
msgstr ""
msgid "CycleAnalyticsEvent|Merge request last build start time"
msgstr ""
msgid "CycleAnalyticsEvent|Merge request merged"
msgstr ""
msgid "CycleAnalyticsStage|Code"
msgid "CycleAnalyticsStage|Code"
msgstr ""
msgstr ""
...
...
spec/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event_spec.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Analytics
::
CycleAnalytics
::
StageEvents
::
StageEvent
do
it
{
expect
(
described_class
).
to
respond_to
(
:name
)
}
it
{
expect
(
described_class
).
to
respond_to
(
:identifier
)
}
it
{
expect
(
described_class
.
new
({})).
to
respond_to
(
:object_type
)
}
end
spec/models/analytics/cycle_analytics/project_stage_spec.rb
View file @
06f1ddbf
...
@@ -6,4 +6,18 @@ describe Analytics::CycleAnalytics::ProjectStage do
...
@@ -6,4 +6,18 @@ describe Analytics::CycleAnalytics::ProjectStage do
describe
'associations'
do
describe
'associations'
do
it
{
is_expected
.
to
belong_to
(
:project
)
}
it
{
is_expected
.
to
belong_to
(
:project
)
}
end
end
it
'default stages must be valid'
do
project
=
create
(
:project
)
Gitlab
::
Analytics
::
CycleAnalytics
::
DefaultStages
.
all
.
each
do
|
params
|
stage
=
described_class
.
new
(
params
.
merge
(
project:
project
))
expect
(
stage
).
to
be_valid
end
end
it_behaves_like
"cycle analytics stage"
do
let
(
:parent
)
{
create
(
:project
)
}
let
(
:parent_name
)
{
:project
}
end
end
end
spec/support/shared_examples/cycle_analytics_stage_examples.rb
0 → 100644
View file @
06f1ddbf
# frozen_string_literal: true
shared_examples_for
'cycle analytics stage'
do
let
(
:valid_params
)
do
{
name:
'My Stage'
,
parent:
parent
,
start_event_identifier: :merge_request_created
,
end_event_identifier: :merge_request_merged
}
end
describe
'validation'
do
it
'is valid'
do
expect
(
described_class
.
new
(
valid_params
)).
to
be_valid
end
it
'validates presence of parent'
do
stage
=
described_class
.
new
(
valid_params
.
except
(
:parent
))
expect
(
stage
).
not_to
be_valid
expect
(
stage
.
errors
.
details
[
parent_name
]).
to
eq
([{
error: :blank
}])
end
it
'validates presence of start_event_identifier'
do
stage
=
described_class
.
new
(
valid_params
.
except
(
:start_event_identifier
))
expect
(
stage
).
not_to
be_valid
expect
(
stage
.
errors
.
details
[
:start_event_identifier
]).
to
eq
([{
error: :blank
}])
end
it
'validates presence of end_event_identifier'
do
stage
=
described_class
.
new
(
valid_params
.
except
(
:end_event_identifier
))
expect
(
stage
).
not_to
be_valid
expect
(
stage
.
errors
.
details
[
:end_event_identifier
]).
to
eq
([{
error: :blank
}])
end
it
'is invalid when end_event is not allowed for the given start_event'
do
invalid_params
=
valid_params
.
merge
(
start_event_identifier: :merge_request_merged
,
end_event_identifier: :merge_request_created
)
stage
=
described_class
.
new
(
invalid_params
)
expect
(
stage
).
not_to
be_valid
expect
(
stage
.
errors
.
details
[
:end_event
]).
to
eq
([{
error: :not_allowed_for_the_given_start_event
}])
end
end
describe
'#subject_model'
do
it
'infers the model from the start event'
do
stage
=
described_class
.
new
(
valid_params
)
expect
(
stage
.
subject_model
).
to
eq
(
MergeRequest
)
end
end
describe
'#start_event'
do
it
'builds start_event object based on start_event_identifier'
do
stage
=
described_class
.
new
(
start_event_identifier:
'merge_request_created'
)
expect
(
stage
.
start_event
).
to
be_a_kind_of
(
Gitlab
::
Analytics
::
CycleAnalytics
::
StageEvents
::
MergeRequestCreated
)
end
end
describe
'#end_event'
do
it
'builds end_event object based on end_event_identifier'
do
stage
=
described_class
.
new
(
end_event_identifier:
'merge_request_merged'
)
expect
(
stage
.
end_event
).
to
be_a_kind_of
(
Gitlab
::
Analytics
::
CycleAnalytics
::
StageEvents
::
MergeRequestMerged
)
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