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
ace0a005
Commit
ace0a005
authored
Aug 29, 2016
by
Lin Jen-Shin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Smartly calculate real running time and pending time
parent
64366209
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
200 additions
and
1 deletion
+200
-1
app/models/ci/pipeline.rb
app/models/ci/pipeline.rb
+7
-1
db/migrate/20160829122117_add_pending_duration_to_pipelines.rb
...grate/20160829122117_add_pending_duration_to_pipelines.rb
+8
-0
lib/gitlab/ci/pipeline_duration.rb
lib/gitlab/ci/pipeline_duration.rb
+90
-0
spec/lib/gitlab/ci/pipeline_duration_spec.rb
spec/lib/gitlab/ci/pipeline_duration_spec.rb
+95
-0
No files found.
app/models/ci/pipeline.rb
View file @
ace0a005
...
...
@@ -258,7 +258,13 @@ module Ci
end
def
update_duration
self
.
duration
=
calculate_duration
calculated_status
=
%w[success failed running canceled]
calculated_builds
=
builds
.
latest
.
where
(
status:
calculated_status
)
calculator
=
PipelineDuration
.
from_builds
(
calculated_builds
)
self
.
duration
=
calculator
.
duration
self
.
pending_duration
=
started_at
-
created_at
+
calculator
.
pending_duration
end
def
execute_hooks
...
...
db/migrate/20160829122117_add_pending_duration_to_pipelines.rb
0 → 100644
View file @
ace0a005
class
AddPendingDurationToPipelines
<
ActiveRecord
::
Migration
DOWNTIME
=
false
def
change
add_column
:ci_commits
,
:pending_duration
,
:integer
end
end
lib/gitlab/ci/pipeline_duration.rb
0 → 100644
View file @
ace0a005
module
Gitlab
module
Ci
class
PipelineDuration
SegmentStruct
=
Struct
.
new
(
:first
,
:last
)
class
Segment
<
SegmentStruct
def
duration
last
-
first
end
end
def
self
.
from_builds
(
builds
)
now
=
Time
.
now
segments
=
builds
.
map
do
|
b
|
Segment
.
new
(
b
.
started_at
,
b
.
finished_at
||
now
)
end
new
(
segments
)
end
attr_reader
:duration
,
:pending_duration
def
initialize
(
segments
)
process
(
segments
.
sort_by
(
&
:first
))
end
private
def
process
(
segments
)
merged
=
process_segments
(
segments
)
@duration
=
process_duration
(
merged
)
@pending_duration
=
process_pending_duration
(
merged
,
@duration
)
end
def
process_segments
(
segments
)
if
segments
.
empty?
segments
else
segments
[
1
..-
1
].
inject
([
segments
.
first
])
do
|
current
,
target
|
left
,
result
=
insert_segment
(
current
,
target
)
if
left
# left is the latest one
result
<<
left
else
result
end
end
end
end
def
insert_segment
(
segments
,
init
)
segments
.
inject
([
init
,
[]])
do
|
target_result
,
member
|
target
,
result
=
target_result
if
target
.
nil?
# done
result
<<
member
[
nil
,
result
]
elsif
merged
=
try_merge_segment
(
target
,
member
)
# overlapped
[
merged
,
result
]
# merge and keep finding the hole
elsif
target
.
last
<
member
.
first
# found the hole
result
<<
target
<<
member
[
nil
,
result
]
else
result
<<
member
target_result
end
end
end
def
try_merge_segment
(
target
,
member
)
if
target
.
first
<=
member
.
last
&&
target
.
last
>=
member
.
first
Segment
.
new
([
target
.
first
,
member
.
first
].
min
,
[
target
.
last
,
member
.
last
].
max
)
end
end
def
process_duration
(
segments
)
segments
.
inject
(
0
)
do
|
result
,
seg
|
result
+
seg
.
duration
end
end
def
process_pending_duration
(
segments
,
duration
)
total
=
segments
.
last
.
last
-
segments
.
first
.
first
total
-
duration
end
end
end
end
spec/lib/gitlab/ci/pipeline_duration_spec.rb
0 → 100644
View file @
ace0a005
require
'spec_helper'
describe
Gitlab
::
Ci
::
PipelineDuration
do
let
(
:calculator
)
{
create_calculator
(
data
)
}
shared_examples
'calculating duration'
do
it
do
expect
(
calculator
.
duration
).
to
eq
(
duration
)
expect
(
calculator
.
pending_duration
).
to
eq
(
pending_duration
)
end
end
context
'test sample A'
do
let
(
:data
)
do
[[
0
,
1
],
[
1
,
2
],
[
3
,
4
],
[
5
,
6
]]
end
let
(
:duration
)
{
4
}
let
(
:pending_duration
)
{
2
}
it_behaves_like
'calculating duration'
end
context
'test sample B'
do
let
(
:data
)
do
[[
0
,
1
],
[
1
,
2
],
[
2
,
3
],
[
3
,
4
],
[
0
,
4
]]
end
let
(
:duration
)
{
4
}
let
(
:pending_duration
)
{
0
}
it_behaves_like
'calculating duration'
end
context
'test sample C'
do
let
(
:data
)
do
[[
0
,
4
],
[
2
,
6
],
[
5
,
7
],
[
8
,
9
]]
end
let
(
:duration
)
{
8
}
let
(
:pending_duration
)
{
1
}
it_behaves_like
'calculating duration'
end
context
'test sample D'
do
let
(
:data
)
do
[[
0
,
1
],
[
2
,
3
],
[
4
,
5
],
[
6
,
7
]]
end
let
(
:duration
)
{
4
}
let
(
:pending_duration
)
{
3
}
it_behaves_like
'calculating duration'
end
context
'test sample E'
do
let
(
:data
)
do
[[
0
,
1
],
[
3
,
9
],
[
3
,
4
],
[
3
,
5
],
[
3
,
8
],
[
4
,
5
],
[
4
,
7
],
[
5
,
8
]]
end
let
(
:duration
)
{
7
}
let
(
:pending_duration
)
{
2
}
it_behaves_like
'calculating duration'
end
def
create_calculator
(
data
)
segments
=
data
.
shuffle
.
map
do
|
(
first
,
last
)
|
Gitlab
::
Ci
::
PipelineDuration
::
Segment
.
new
(
first
,
last
)
end
Gitlab
::
Ci
::
PipelineDuration
.
new
(
segments
)
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