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 @@
module
Analytics
module
CycleAnalytics
class
ProjectStage
<
ApplicationRecord
include
Analytics
::
CycleAnalytics
::
Stage
validates
:project
,
presence:
true
belongs_to
:project
alias_attribute
:parent
,
:project
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 ""
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
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"
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
describe
'associations'
do
it
{
is_expected
.
to
belong_to
(
:project
)
}
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
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