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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
f041c389
Commit
f041c389
authored
7 years ago
by
Phil Hughes
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into breadcrumbs-improvements
parents
a27c0013
6523ba1d
No related merge requests found
Changes
56
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
56 changed files
with
6864 additions
and
2168 deletions
+6864
-2168
app/assets/javascripts/monitoring/components/graph.vue
app/assets/javascripts/monitoring/components/graph.vue
+48
-66
app/assets/javascripts/monitoring/components/graph/flag.vue
app/assets/javascripts/monitoring/components/graph/flag.vue
+1
-14
app/assets/javascripts/monitoring/components/graph/legend.vue
...assets/javascripts/monitoring/components/graph/legend.vue
+59
-24
app/assets/javascripts/monitoring/components/monitoring_paths.vue
...ts/javascripts/monitoring/components/monitoring_paths.vue
+40
-0
app/assets/javascripts/monitoring/mixins/monitoring_mixins.js
...assets/javascripts/monitoring/mixins/monitoring_mixins.js
+2
-2
app/assets/javascripts/monitoring/stores/monitoring_store.js
app/assets/javascripts/monitoring/stores/monitoring_store.js
+41
-37
app/assets/javascripts/monitoring/utils/measurements.js
app/assets/javascripts/monitoring/utils/measurements.js
+6
-6
app/assets/javascripts/monitoring/utils/multiple_time_series.js
...sets/javascripts/monitoring/utils/multiple_time_series.js
+80
-0
app/assets/stylesheets/framework/selects.scss
app/assets/stylesheets/framework/selects.scss
+1
-0
app/assets/stylesheets/pages/environments.scss
app/assets/stylesheets/pages/environments.scss
+9
-3
app/models/ci/trigger_request.rb
app/models/ci/trigger_request.rb
+4
-0
app/models/commit_status.rb
app/models/commit_status.rb
+13
-0
app/presenters/ci/build_presenter.rb
app/presenters/ci/build_presenter.rb
+11
-0
app/services/ci/create_trigger_request_service.rb
app/services/ci/create_trigger_request_service.rb
+0
-19
app/services/projects/update_pages_service.rb
app/services/projects/update_pages_service.rb
+1
-1
app/views/projects/jobs/_sidebar.html.haml
app/views/projects/jobs/_sidebar.html.haml
+4
-4
app/workers/stuck_ci_jobs_worker.rb
app/workers/stuck_ci_jobs_worker.rb
+1
-1
changelogs/unreleased/additional-time-series-charts.yml
changelogs/unreleased/additional-time-series-charts.yml
+5
-0
changelogs/unreleased/feature-sm-34518-extend-api-pipeline-schedule-variable-new.yml
...re-sm-34518-extend-api-pipeline-schedule-variable-new.yml
+5
-0
changelogs/unreleased/feature-sm-37239-implement-failure_reason-on-ci_builds.yml
...eature-sm-37239-implement-failure_reason-on-ci_builds.yml
+5
-0
db/migrate/20170830125940_add_failure_reason_to_ci_builds.rb
db/migrate/20170830125940_add_failure_reason_to_ci_builds.rb
+9
-0
db/schema.rb
db/schema.rb
+2
-1
doc/api/pipeline_schedules.md
doc/api/pipeline_schedules.md
+90
-1
doc/ci/yaml/README.md
doc/ci/yaml/README.md
+1
-1
lib/api/commit_statuses.rb
lib/api/commit_statuses.rb
+1
-1
lib/api/entities.rb
lib/api/entities.rb
+2
-1
lib/api/pipeline_schedules.rb
lib/api/pipeline_schedules.rb
+69
-16
lib/api/runner.rb
lib/api/runner.rb
+3
-1
lib/api/v3/triggers.rb
lib/api/v3/triggers.rb
+19
-13
spec/factories/ci/builds.rb
spec/factories/ci/builds.rb
+1
-1
spec/factories/ci/pipeline_variables.rb
spec/factories/ci/pipeline_variables.rb
+0
-0
spec/factories/ci/trigger_requests.rb
spec/factories/ci/trigger_requests.rb
+0
-9
spec/features/projects/jobs_spec.rb
spec/features/projects/jobs_spec.rb
+29
-11
spec/fixtures/api/schemas/pipeline_schedule.json
spec/fixtures/api/schemas/pipeline_schedule.json
+4
-0
spec/fixtures/api/schemas/pipeline_schedule_variable.json
spec/fixtures/api/schemas/pipeline_schedule_variable.json
+8
-0
spec/javascripts/monitoring/graph/flag_spec.js
spec/javascripts/monitoring/graph/flag_spec.js
+0
-4
spec/javascripts/monitoring/graph/legend_spec.js
spec/javascripts/monitoring/graph/legend_spec.js
+59
-63
spec/javascripts/monitoring/graph_row_spec.js
spec/javascripts/monitoring/graph_row_spec.js
+6
-6
spec/javascripts/monitoring/graph_spec.js
spec/javascripts/monitoring/graph_spec.js
+8
-26
spec/javascripts/monitoring/mock_data.js
spec/javascripts/monitoring/mock_data.js
+5837
-1743
spec/javascripts/monitoring/monitoring_paths_spec.js
spec/javascripts/monitoring/monitoring_paths_spec.js
+34
-0
spec/javascripts/monitoring/utils/multiple_time_series_spec.js
...javascripts/monitoring/utils/multiple_time_series_spec.js
+21
-0
spec/lib/gitlab/import_export/safe_model_attributes.yml
spec/lib/gitlab/import_export/safe_model_attributes.yml
+1
-0
spec/models/ci/build_spec.rb
spec/models/ci/build_spec.rb
+24
-4
spec/models/ci/trigger_request_spec.rb
spec/models/ci/trigger_request_spec.rb
+17
-0
spec/models/commit_status_spec.rb
spec/models/commit_status_spec.rb
+21
-0
spec/presenters/ci/build_presenter_spec.rb
spec/presenters/ci/build_presenter_spec.rb
+34
-0
spec/requests/api/commit_statuses_spec.rb
spec/requests/api/commit_statuses_spec.rb
+3
-0
spec/requests/api/pipeline_schedules_spec.rb
spec/requests/api/pipeline_schedules_spec.rb
+159
-1
spec/requests/api/runner_spec.rb
spec/requests/api/runner_spec.rb
+48
-8
spec/requests/api/v3/triggers_spec.rb
spec/requests/api/v3/triggers_spec.rb
+3
-2
spec/services/ci/create_trigger_request_service_spec.rb
spec/services/ci/create_trigger_request_service_spec.rb
+0
-52
spec/services/ci/retry_build_service_spec.rb
spec/services/ci/retry_build_service_spec.rb
+1
-1
spec/services/projects/update_pages_service_spec.rb
spec/services/projects/update_pages_service_spec.rb
+1
-0
spec/views/projects/jobs/show.html.haml_spec.rb
spec/views/projects/jobs/show.html.haml_spec.rb
+0
-16
spec/workers/stuck_ci_jobs_worker_spec.rb
spec/workers/stuck_ci_jobs_worker_spec.rb
+13
-9
No files found.
app/assets/javascripts/monitoring/components/graph.vue
View file @
f041c389
...
...
@@ -3,11 +3,12 @@
import
GraphLegend
from
'
./graph/legend.vue
'
;
import
GraphFlag
from
'
./graph/flag.vue
'
;
import
GraphDeployment
from
'
./graph/deployment.vue
'
;
import
monitoringPaths
from
'
./monitoring_paths.vue
'
;
import
MonitoringMixin
from
'
../mixins/monitoring_mixins
'
;
import
eventHub
from
'
../event_hub
'
;
import
measurements
from
'
../utils/measurements
'
;
import
{
formatRelevantDigits
}
from
'
../../lib/utils/number_utils
'
;
import
{
timeScaleFormat
}
from
'
../utils/date_time_formatters
'
;
import
createTimeSeries
from
'
../utils/multiple_time_series
'
;
import
bp
from
'
../../breakpoints
'
;
const
bisectDate
=
d3
.
bisector
(
d
=>
d
.
time
).
left
;
...
...
@@ -36,32 +37,29 @@
data
()
{
return
{
baseGraphHeight
:
450
,
baseGraphWidth
:
600
,
graphHeight
:
450
,
graphWidth
:
600
,
graphHeightOffset
:
120
,
xScale
:
{},
yScale
:
{},
margin
:
{},
data
:
[],
unitOfDisplay
:
''
,
areaColorRgb
:
'
#8fbce8
'
,
lineColorRgb
:
'
#1f78d1
'
,
yAxisLabel
:
''
,
legendTitle
:
''
,
reducedDeploymentData
:
[],
area
:
''
,
line
:
''
,
measurements
:
measurements
.
large
,
currentData
:
{
time
:
new
Date
(),
value
:
0
,
},
current
YCoordinate
:
0
,
current
DataIndex
:
0
,
currentXCoordinate
:
0
,
currentFlagPosition
:
0
,
metricUsage
:
''
,
showFlag
:
false
,
showDeployInfo
:
true
,
timeSeries
:
[],
};
},
...
...
@@ -69,16 +67,17 @@
GraphLegend
,
GraphFlag
,
GraphDeployment
,
monitoringPaths
,
},
computed
:
{
outterViewBox
()
{
return
`0 0
${
this
.
graphWidth
}
${
this
.
g
raphHeight
}
`
;
return
`0 0
${
this
.
baseGraphWidth
}
${
this
.
baseG
raphHeight
}
`
;
},
innerViewBox
()
{
if
((
this
.
g
raphWidth
-
150
)
>
0
)
{
return
`0 0
${
this
.
graphWidth
-
150
}
${
this
.
g
raphHeight
}
`
;
if
((
this
.
baseG
raphWidth
-
150
)
>
0
)
{
return
`0 0
${
this
.
baseGraphWidth
-
150
}
${
this
.
baseG
raphHeight
}
`
;
}
return
'
0 0 0 0
'
;
},
...
...
@@ -89,7 +88,7 @@
paddingBottomRootSvg
()
{
return
{
paddingBottom
:
`
${(
Math
.
ceil
(
this
.
graphHeight
*
100
)
/
this
.
g
raphWidth
)
||
0
}
%`
,
paddingBottom
:
`
${(
Math
.
ceil
(
this
.
baseGraphHeight
*
100
)
/
this
.
baseG
raphWidth
)
||
0
}
%`
,
};
},
},
...
...
@@ -104,17 +103,16 @@
this
.
margin
=
measurements
.
small
.
margin
;
this
.
measurements
=
measurements
.
small
;
}
this
.
data
=
query
.
result
[
0
].
values
;
this
.
unitOfDisplay
=
query
.
unit
||
''
;
this
.
yAxisLabel
=
this
.
graphData
.
y_label
||
'
Values
'
;
this
.
legendTitle
=
query
.
label
||
'
Average
'
;
this
.
graphWidth
=
this
.
$refs
.
baseSvg
.
clientWidth
-
this
.
margin
.
left
-
this
.
margin
.
right
;
this
.
graphHeight
=
this
.
graphHeight
-
this
.
margin
.
top
-
this
.
margin
.
bottom
;
if
(
this
.
data
!==
undefined
)
{
this
.
renderAxesPaths
()
;
this
.
formatDeployment
s
();
}
this
.
baseGraphHeight
=
this
.
graphHeight
;
this
.
baseGraphWidth
=
this
.
graphWidth
;
this
.
renderAxesPath
s
();
this
.
formatDeployments
();
},
handleMouseOverGraph
(
e
)
{
...
...
@@ -123,16 +121,17 @@
point
.
y
=
e
.
clientY
;
point
=
point
.
matrixTransform
(
this
.
$refs
.
graphData
.
getScreenCTM
().
inverse
());
point
.
x
=
point
.
x
+=
7
;
const
timeValueOverlay
=
this
.
xScale
.
invert
(
point
.
x
);
const
overlayIndex
=
bisectDate
(
this
.
data
,
timeValueOverlay
,
1
);
const
d0
=
this
.
data
[
overlayIndex
-
1
];
const
d1
=
this
.
data
[
overlayIndex
];
const
firstTimeSeries
=
this
.
timeSeries
[
0
];
const
timeValueOverlay
=
firstTimeSeries
.
timeSeriesScaleX
.
invert
(
point
.
x
);
const
overlayIndex
=
bisectDate
(
firstTimeSeries
.
values
,
timeValueOverlay
,
1
);
const
d0
=
firstTimeSeries
.
values
[
overlayIndex
-
1
];
const
d1
=
firstTimeSeries
.
values
[
overlayIndex
];
if
(
d0
===
undefined
||
d1
===
undefined
)
return
;
const
evalTime
=
timeValueOverlay
-
d0
[
0
]
>
d1
[
0
]
-
timeValueOverlay
;
this
.
currentData
=
evalTime
?
d1
:
d0
;
this
.
currentXCoordinate
=
Math
.
floor
(
this
.
xScale
(
this
.
currentData
.
time
));
this
.
currentDataIndex
=
evalTime
?
overlayIndex
:
(
overlayIndex
-
1
);
this
.
currentXCoordinate
=
Math
.
floor
(
firstTimeSeries
.
timeSeriesScaleX
(
this
.
currentData
.
time
));
const
currentDeployXPos
=
this
.
mouseOverDeployInfo
(
point
.
x
);
this
.
currentYCoordinate
=
this
.
yScale
(
this
.
currentData
.
value
);
if
(
this
.
currentXCoordinate
>
(
this
.
graphWidth
-
200
))
{
this
.
currentFlagPosition
=
this
.
currentXCoordinate
-
103
;
...
...
@@ -145,17 +144,25 @@
}
else
{
this
.
showFlag
=
true
;
}
this
.
metricUsage
=
`
${
formatRelevantDigits
(
this
.
currentData
.
value
)}
${
this
.
unitOfDisplay
}
`
;
},
renderAxesPaths
()
{
this
.
timeSeries
=
createTimeSeries
(
this
.
graphData
.
queries
[
0
].
result
,
this
.
graphWidth
,
this
.
graphHeight
,
this
.
graphHeightOffset
);
if
(
this
.
timeSeries
.
length
>
3
)
{
this
.
baseGraphHeight
=
this
.
baseGraphHeight
+=
(
this
.
timeSeries
.
length
-
3
)
*
20
;
}
const
axisXScale
=
d3
.
time
.
scale
()
.
range
([
0
,
this
.
graphWidth
]);
this
.
y
Scale
=
d3
.
scale
.
linear
()
const
axisY
Scale
=
d3
.
scale
.
linear
()
.
range
([
this
.
graphHeight
-
this
.
graphHeightOffset
,
0
]);
axisXScale
.
domain
(
d3
.
extent
(
this
.
data
,
d
=>
d
.
time
));
this
.
yScale
.
domain
([
0
,
d3
.
max
(
this
.
data
.
map
(
d
=>
d
.
value
))]);
axisXScale
.
domain
(
d3
.
extent
(
this
.
timeSeries
[
0
].
values
,
d
=>
d
.
time
));
axisYScale
.
domain
([
0
,
d3
.
max
(
this
.
timeSeries
[
0
].
values
.
map
(
d
=>
d
.
value
))]);
const
xAxis
=
d3
.
svg
.
axis
()
.
scale
(
axisXScale
)
...
...
@@ -164,7 +171,7 @@
.
orient
(
'
bottom
'
);
const
yAxis
=
d3
.
svg
.
axis
()
.
scale
(
this
.
y
Scale
)
.
scale
(
axisY
Scale
)
.
ticks
(
measurements
.
yTicks
)
.
orient
(
'
left
'
);
...
...
@@ -180,25 +187,6 @@
.
attr
(
'
class
'
,
'
axis-tick
'
);
}
// Avoid adding the class to the first tick, to prevent coloring
});
// This will select all of the ticks once they're rendered
this
.
xScale
=
d3
.
time
.
scale
()
.
range
([
0
,
this
.
graphWidth
-
70
]);
this
.
xScale
.
domain
(
d3
.
extent
(
this
.
data
,
d
=>
d
.
time
));
const
areaFunction
=
d3
.
svg
.
area
()
.
x
(
d
=>
this
.
xScale
(
d
.
time
))
.
y0
(
this
.
graphHeight
-
this
.
graphHeightOffset
)
.
y1
(
d
=>
this
.
yScale
(
d
.
value
))
.
interpolate
(
'
linear
'
);
const
lineFunction
=
d3
.
svg
.
line
()
.
x
(
d
=>
this
.
xScale
(
d
.
time
))
.
y
(
d
=>
this
.
yScale
(
d
.
value
));
this
.
line
=
lineFunction
(
this
.
data
);
this
.
area
=
areaFunction
(
this
.
data
);
},
},
...
...
@@ -245,30 +233,25 @@
:graph-height=
"graphHeight"
:margin=
"margin"
:measurements=
"measurements"
:area-color-rgb=
"areaColorRgb"
:legend-title=
"legendTitle"
:y-axis-label=
"yAxisLabel"
:metric-usage=
"metricUsage"
:time-series=
"timeSeries"
:unit-of-display=
"unitOfDisplay"
:current-data-index=
"currentDataIndex"
/>
<svg
class=
"graph-data"
:viewBox=
"innerViewBox"
ref=
"graphData"
>
<path
class=
"metric-area"
:d=
"area"
:fill=
"areaColorRgb"
transform=
"translate(-5, 20)"
>
</path>
<path
class=
"metric-line"
:d=
"line"
:stroke=
"lineColorRgb"
fill=
"none"
stroke-width=
"2"
transform=
"translate(-5, 20)"
>
</path>
<graph-deployment
<monitoring-paths
v-for=
"(path, index) in timeSeries"
:key=
"index"
:generated-line-path=
"path.linePath"
:generated-area-path=
"path.areaPath"
:line-color=
"path.lineColor"
:area-color=
"path.areaColor"
/>
<monitoring-deployment
:show-deploy-info=
"showDeployInfo"
:deployment-data=
"reducedDeploymentData"
:graph-height=
"graphHeight"
...
...
@@ -277,7 +260,6 @@
<graph-flag
v-if=
"showFlag"
:current-x-coordinate=
"currentXCoordinate"
:current-y-coordinate=
"currentYCoordinate"
:current-data=
"currentData"
:current-flag-position=
"currentFlagPosition"
:graph-height=
"graphHeight"
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/monitoring/components/graph/flag.vue
View file @
f041c389
...
...
@@ -7,10 +7,6 @@
type
:
Number
,
required
:
true
,
},
currentYCoordinate
:
{
type
:
Number
,
required
:
true
,
},
currentFlagPosition
:
{
type
:
Number
,
required
:
true
,
...
...
@@ -60,16 +56,7 @@
:y2=
"calculatedHeight"
transform=
"translate(-5, 20)"
>
</line>
<circle
class=
"circle-metric"
:fill=
"circleColorRgb"
stroke=
"#000"
:cx=
"currentXCoordinate"
:cy=
"currentYCoordinate"
r=
"5"
transform=
"translate(-5, 20)"
>
</circle>
<svg
<svg
class=
"rect-text-metric"
:x=
"currentFlagPosition"
y=
"0"
>
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/monitoring/components/graph/legend.vue
View file @
f041c389
<
script
>
import
{
formatRelevantDigits
}
from
'
../../../lib/utils/number_utils
'
;
export
default
{
props
:
{
graphWidth
:
{
...
...
@@ -17,10 +19,6 @@
type
:
Object
,
required
:
true
,
},
areaColorRgb
:
{
type
:
String
,
required
:
true
,
},
legendTitle
:
{
type
:
String
,
required
:
true
,
...
...
@@ -29,15 +27,25 @@
type
:
String
,
required
:
true
,
},
metricUsage
:
{
timeSeries
:
{
type
:
Array
,
required
:
true
,
},
unitOfDisplay
:
{
type
:
String
,
required
:
true
,
},
currentDataIndex
:
{
type
:
Number
,
required
:
true
,
},
},
data
()
{
return
{
yLabelWidth
:
0
,
yLabelHeight
:
0
,
seriesXPosition
:
0
,
metricUsageXPosition
:
0
,
};
},
computed
:
{
...
...
@@ -63,10 +71,28 @@
yPosition
()
{
return
((
this
.
graphHeight
-
this
.
margin
.
top
)
+
this
.
measurements
.
axisLabelLineOffset
)
||
0
;
},
},
methods
:
{
translateLegendGroup
(
index
)
{
return
`translate(0,
${
12
*
(
index
)}
)`
;
},
formatMetricUsage
(
series
)
{
return
`
${
formatRelevantDigits
(
series
.
values
[
this
.
currentDataIndex
].
value
)}
${
this
.
unitOfDisplay
}
`
;
},
},
mounted
()
{
this
.
$nextTick
(()
=>
{
const
bbox
=
this
.
$refs
.
ylabel
.
getBBox
();
this
.
metricUsageXPosition
=
0
;
this
.
seriesXPosition
=
0
;
if
(
this
.
$refs
.
legendTitleSvg
!=
null
)
{
this
.
seriesXPosition
=
this
.
$refs
.
legendTitleSvg
[
0
].
getBBox
().
width
;
}
if
(
this
.
$refs
.
seriesTitleSvg
!=
null
)
{
this
.
metricUsageXPosition
=
this
.
$refs
.
seriesTitleSvg
[
0
].
getBBox
().
width
;
}
this
.
yLabelWidth
=
bbox
.
width
+
10
;
// Added some padding
this
.
yLabelHeight
=
bbox
.
height
+
5
;
});
...
...
@@ -121,24 +147,33 @@
dy=
".35em"
>
Time
</text>
<rect
:fill=
"areaColorRgb"
:width=
"measurements.legends.width"
:height=
"measurements.legends.height"
x=
"20"
:y=
"graphHeight - measurements.legendOffset"
>
</rect>
<text
class=
"text-metric-title"
x=
"50"
:y=
"graphHeight - 25"
>
{{
legendTitle
}}
</text>
<text
class=
"text-metric-usage"
x=
"50"
:y=
"graphHeight - 10"
>
{{
metricUsage
}}
</text>
<g
class=
"legend-group"
v-for=
"(series, index) in timeSeries"
:key=
"index"
:transform=
"translateLegendGroup(index)"
>
<rect
:fill=
"series.areaColor"
:width=
"measurements.legends.width"
:height=
"measurements.legends.height"
x=
"20"
:y=
"graphHeight - measurements.legendOffset"
>
</rect>
<text
v-if=
"timeSeries.length > 1"
class=
"legend-metric-title"
ref=
"legendTitleSvg"
x=
"38"
:y=
"graphHeight - 30"
>
{{
legendTitle
}}
Series
{{
index
+
1
}}
{{
formatMetricUsage
(
series
)
}}
</text>
<text
v-else
class=
"legend-metric-title"
ref=
"legendTitleSvg"
x=
"38"
:y=
"graphHeight - 30"
>
{{
legendTitle
}}
{{
formatMetricUsage
(
series
)
}}
</text>
</g>
</g>
</
template
>
This diff is collapsed.
Click to expand it.
app/assets/javascripts/monitoring/components/monitoring_paths.vue
0 → 100644
View file @
f041c389
<
script
>
export
default
{
props
:
{
generatedLinePath
:
{
type
:
String
,
required
:
true
,
},
generatedAreaPath
:
{
type
:
String
,
required
:
true
,
},
lineColor
:
{
type
:
String
,
required
:
true
,
},
areaColor
:
{
type
:
String
,
required
:
true
,
},
},
};
</
script
>
<
template
>
<g>
<path
class=
"metric-area"
:d=
"generatedAreaPath"
:fill=
"areaColor"
transform=
"translate(-5, 20)"
>
</path>
<path
class=
"metric-line"
:d=
"generatedLinePath"
:stroke=
"lineColor"
fill=
"none"
stroke-width=
"1"
transform=
"translate(-5, 20)"
>
</path>
</g>
</
template
>
This diff is collapsed.
Click to expand it.
app/assets/javascripts/monitoring/mixins/monitoring_mixins.js
View file @
f041c389
...
...
@@ -21,9 +21,9 @@ const mixins = {
formatDeployments
()
{
this
.
reducedDeploymentData
=
this
.
deploymentData
.
reduce
((
deploymentDataArray
,
deployment
)
=>
{
const
time
=
new
Date
(
deployment
.
created_at
);
const
xPos
=
Math
.
floor
(
this
.
xScale
(
time
));
const
xPos
=
Math
.
floor
(
this
.
timeSeries
[
0
].
timeSeriesScaleX
(
time
));
time
.
setSeconds
(
this
.
data
[
0
].
time
.
getSeconds
());
time
.
setSeconds
(
this
.
timeSeries
[
0
].
values
[
0
].
time
.
getSeconds
());
if
(
xPos
>=
0
)
{
deploymentDataArray
.
push
({
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/monitoring/stores/monitoring_store.js
View file @
f041c389
import
_
from
'
underscore
'
;
class
MonitoringStore
{
function
sortMetrics
(
metrics
)
{
return
_
.
chain
(
metrics
).
sortBy
(
'
weight
'
).
sortBy
(
'
title
'
).
value
();
}
function
normalizeMetrics
(
metrics
)
{
return
metrics
.
map
(
metric
=>
({
...
metric
,
queries
:
metric
.
queries
.
map
(
query
=>
({
...
query
,
result
:
query
.
result
.
map
(
result
=>
({
...
result
,
values
:
result
.
values
.
map
(([
timestamp
,
value
])
=>
({
time
:
new
Date
(
timestamp
*
1000
),
value
,
})),
})),
})),
}));
}
function
collate
(
array
,
rows
=
2
)
{
const
collatedArray
=
[];
let
row
=
[];
array
.
forEach
((
value
,
index
)
=>
{
row
.
push
(
value
);
if
((
index
+
1
)
%
rows
===
0
)
{
collatedArray
.
push
(
row
);
row
=
[];
}
});
if
(
row
.
length
>
0
)
{
collatedArray
.
push
(
row
);
}
return
collatedArray
;
}
export
default
class
MonitoringStore
{
constructor
()
{
this
.
groups
=
[];
this
.
deploymentData
=
[];
}
// eslint-disable-next-line class-methods-use-this
createArrayRows
(
metrics
=
[])
{
const
currentMetrics
=
metrics
;
const
availableMetrics
=
[];
let
metricsRow
=
[];
let
index
=
1
;
Object
.
keys
(
currentMetrics
).
forEach
((
key
)
=>
{
const
metricValues
=
currentMetrics
[
key
].
queries
[
0
].
result
[
0
].
values
;
if
(
metricValues
!=
null
)
{
const
literalMetrics
=
metricValues
.
map
(
metric
=>
({
time
:
new
Date
(
metric
[
0
]
*
1000
),
value
:
metric
[
1
],
}));
currentMetrics
[
key
].
queries
[
0
].
result
[
0
].
values
=
literalMetrics
;
metricsRow
.
push
(
currentMetrics
[
key
]);
if
(
index
%
2
===
0
)
{
availableMetrics
.
push
(
metricsRow
);
metricsRow
=
[];
}
index
=
index
+=
1
;
}
});
if
(
metricsRow
.
length
>
0
)
{
availableMetrics
.
push
(
metricsRow
);
}
return
availableMetrics
;
}
storeMetrics
(
groups
=
[])
{
this
.
groups
=
groups
.
map
((
group
)
=>
{
const
currentGroup
=
group
;
currentGroup
.
metrics
=
_
.
chain
(
group
.
metrics
).
sortBy
(
'
weight
'
).
sortBy
(
'
title
'
).
value
();
currentGroup
.
metrics
=
this
.
createArrayRows
(
currentGroup
.
metrics
);
return
currentGroup
;
});
this
.
groups
=
groups
.
map
(
group
=>
({
...
group
,
metrics
:
collate
(
normalizeMetrics
(
sortMetrics
(
group
.
metrics
))),
}));
}
storeDeploymentData
(
deploymentData
=
[])
{
...
...
@@ -57,5 +63,3 @@ class MonitoringStore {
return
metricsCount
;
}
}
export
default
MonitoringStore
;
This diff is collapsed.
Click to expand it.
app/assets/javascripts/monitoring/utils/measurements.js
View file @
f041c389
...
...
@@ -7,15 +7,15 @@ export default {
left
:
40
,
},
legends
:
{
width
:
1
5
,
height
:
25
,
width
:
1
0
,
height
:
3
,
},
backgroundLegend
:
{
width
:
30
,
height
:
50
,
},
axisLabelLineOffset
:
-
20
,
legendOffset
:
3
5
,
legendOffset
:
3
3
,
},
large
:
{
// This covers both md and lg screen sizes
margin
:
{
...
...
@@ -25,15 +25,15 @@ export default {
left
:
80
,
},
legends
:
{
width
:
20
,
height
:
3
0
,
width
:
15
,
height
:
3
,
},
backgroundLegend
:
{
width
:
30
,
height
:
150
,
},
axisLabelLineOffset
:
20
,
legendOffset
:
3
8
,
legendOffset
:
3
6
,
},
xTicks
:
8
,
yTicks
:
3
,
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/monitoring/utils/multiple_time_series.js
0 → 100644
View file @
f041c389
import
d3
from
'
d3
'
;
import
_
from
'
underscore
'
;
export
default
function
createTimeSeries
(
seriesData
,
graphWidth
,
graphHeight
,
graphHeightOffset
)
{
const
maxValues
=
seriesData
.
map
((
timeSeries
,
index
)
=>
{
const
maxValue
=
d3
.
max
(
timeSeries
.
values
.
map
(
d
=>
d
.
value
));
return
{
maxValue
,
index
,
};
});
const
maxValueFromSeries
=
_
.
max
(
maxValues
,
val
=>
val
.
maxValue
);
let
timeSeriesNumber
=
1
;
let
lineColor
=
'
#1f78d1
'
;
let
areaColor
=
'
#8fbce8
'
;
return
seriesData
.
map
((
timeSeries
)
=>
{
const
timeSeriesScaleX
=
d3
.
time
.
scale
()
.
range
([
0
,
graphWidth
-
70
]);
const
timeSeriesScaleY
=
d3
.
scale
.
linear
()
.
range
([
graphHeight
-
graphHeightOffset
,
0
]);
timeSeriesScaleX
.
domain
(
d3
.
extent
(
timeSeries
.
values
,
d
=>
d
.
time
));
timeSeriesScaleY
.
domain
([
0
,
maxValueFromSeries
.
maxValue
]);
const
lineFunction
=
d3
.
svg
.
line
()
.
x
(
d
=>
timeSeriesScaleX
(
d
.
time
))
.
y
(
d
=>
timeSeriesScaleY
(
d
.
value
));
const
areaFunction
=
d3
.
svg
.
area
()
.
x
(
d
=>
timeSeriesScaleX
(
d
.
time
))
.
y0
(
graphHeight
-
graphHeightOffset
)
.
y1
(
d
=>
timeSeriesScaleY
(
d
.
value
))
.
interpolate
(
'
linear
'
);
switch
(
timeSeriesNumber
)
{
case
1
:
lineColor
=
'
#1f78d1
'
;
areaColor
=
'
#8fbce8
'
;
break
;
case
2
:
lineColor
=
'
#fc9403
'
;
areaColor
=
'
#feca81
'
;
break
;
case
3
:
lineColor
=
'
#db3b21
'
;
areaColor
=
'
#ed9d90
'
;
break
;
case
4
:
lineColor
=
'
#1aaa55
'
;
areaColor
=
'
#8dd5aa
'
;
break
;
case
5
:
lineColor
=
'
#6666c4
'
;
areaColor
=
'
#d1d1f0
'
;
break
;
default
:
lineColor
=
'
#1f78d1
'
;
areaColor
=
'
#8fbce8
'
;
break
;
}
if
(
timeSeriesNumber
<=
5
)
{
timeSeriesNumber
=
timeSeriesNumber
+=
1
;
}
else
{
timeSeriesNumber
=
1
;
}
return
{
linePath
:
lineFunction
(
timeSeries
.
values
),
areaPath
:
areaFunction
(
timeSeries
.
values
),
timeSeriesScaleX
,
values
:
timeSeries
.
values
,
lineColor
,
areaColor
,
};
});
}
This diff is collapsed.
Click to expand it.
app/assets/stylesheets/framework/selects.scss
View file @
f041c389
...
...
@@ -272,6 +272,7 @@ body[data-page="projects:new"] #select2-drop,
body
[
data-page
=
"projects:merge_requests:edit"
]
#select2-drop
,
body
[
data-page
=
"projects:blob:new"
]
#select2-drop
,
body
[
data-page
=
"profiles:show"
]
#select2-drop
,
body
[
data-page
=
"projects:issues:show"
]
#select2-drop
,
body
[
data-page
=
"projects:blob:edit"
]
#select2-drop
{
&
.select2-drop
{
border
:
1px
solid
$dropdown-border-color
;
...
...
This diff is collapsed.
Click to expand it.
app/assets/stylesheets/pages/environments.scss
View file @
f041c389
...
...
@@ -169,7 +169,7 @@
}
.metric-area
{
opacity
:
0
.
8
;
opacity
:
0
.
25
;
}
.prometheus-graph-overlay
{
...
...
@@ -251,8 +251,14 @@
font-weight
:
$gl-font-weight-bold
;
}
.label-axis-text
,
.text-metric-usage
{
.label-axis-text
{
fill
:
$black
;
font-weight
:
$gl-font-weight-normal
;
font-size
:
10px
;
}
.text-metric-usage
,
.legend-metric-title
{
fill
:
$black
;
font-weight
:
$gl-font-weight-normal
;
font-size
:
12px
;
...
...
This diff is collapsed.
Click to expand it.
app/models/ci/trigger_request.rb
View file @
f041c389
...
...
@@ -6,6 +6,10 @@ module Ci
belongs_to
:pipeline
,
foreign_key: :commit_id
has_many
:builds
# We switched to Ci::PipelineVariable from Ci::TriggerRequest.variables.
# Ci::TriggerRequest doesn't save variables anymore.
validates
:variables
,
absence:
true
serialize
:variables
# rubocop:disable Cop/ActiveRecordSerialize
def
user_variables
...
...
This diff is collapsed.
Click to expand it.
app/models/commit_status.rb
View file @
f041c389
...
...
@@ -38,6 +38,14 @@ class CommitStatus < ActiveRecord::Base
scope
:retried_ordered
,
->
{
retried
.
ordered
.
includes
(
project: :namespace
)
}
scope
:after_stage
,
->
(
index
)
{
where
(
'stage_idx > ?'
,
index
)
}
enum
failure_reason:
{
unknown_failure:
nil
,
script_failure:
1
,
api_failure:
2
,
stuck_or_timeout_failure:
3
,
runner_system_failure:
4
}
state_machine
:status
do
event
:process
do
transition
[
:skipped
,
:manual
]
=>
:created
...
...
@@ -79,6 +87,11 @@ class CommitStatus < ActiveRecord::Base
commit_status
.
finished_at
=
Time
.
now
end
before_transition
any
=>
:failed
do
|
commit_status
,
transition
|
failure_reason
=
transition
.
args
.
first
commit_status
.
failure_reason
=
failure_reason
end
after_transition
do
|
commit_status
,
transition
|
next
if
transition
.
loopback?
...
...
This diff is collapsed.
Click to expand it.
app/presenters/ci/build_presenter.rb
View file @
f041c389
...
...
@@ -17,5 +17,16 @@ module Ci
"Job is redundant and is auto-canceled by Pipeline #
#{
auto_canceled_by_id
}
"
end
end
def
trigger_variables
return
[]
unless
trigger_request
@trigger_variables
||=
if
pipeline
.
variables
.
any?
pipeline
.
variables
.
map
(
&
:to_runner_variable
)
else
trigger_request
.
user_variables
end
end
end
end
This diff is collapsed.
Click to expand it.
app/services/ci/create_trigger_request_service.rb
deleted
100644 → 0
View file @
a27c0013
# This class is deprecated because we're closing Ci::TriggerRequest.
# New class is PipelineTriggerService (app/services/ci/pipeline_trigger_service.rb)
# which is integrated with Ci::PipelineVariable instaed of Ci::TriggerRequest.
# We remove this class after we removed v1 and v3 API. This class is still being
# referred by such legacy code.
module
Ci
module
CreateTriggerRequestService
Result
=
Struct
.
new
(
:trigger_request
,
:pipeline
)
def
self
.
execute
(
project
,
trigger
,
ref
,
variables
=
nil
)
trigger_request
=
trigger
.
trigger_requests
.
create
(
variables:
variables
)
pipeline
=
Ci
::
CreatePipelineService
.
new
(
project
,
trigger
.
owner
,
ref:
ref
)
.
execute
(
:trigger
,
ignore_skip_ci:
true
,
trigger_request:
trigger_request
)
Result
.
new
(
trigger_request
,
pipeline
)
end
end
end
This diff is collapsed.
Click to expand it.
app/services/projects/update_pages_service.rb
View file @
f041c389
...
...
@@ -53,7 +53,7 @@ module Projects
log_error
(
"Projects::UpdatePagesService:
#{
message
}
"
)
@status
.
allow_failure
=
!
latest?
@status
.
description
=
message
@status
.
drop
@status
.
drop
(
:script_failure
)
super
end
...
...
This diff is collapsed.
Click to expand it.
app/views/projects/jobs/_sidebar.html.haml
View file @
f041c389
...
...
@@ -46,14 +46,14 @@
%span
.build-light-text
Token:
#{
@build
.
trigger_request
.
trigger
.
short_token
}
-
if
@build
.
trigger_
request
.
variables
-
if
@build
.
trigger_
variables
.
any?
%p
%button
.btn.group.btn-group-justified.reveal-variables
Reveal Variables
%dl
.js-build-variables.trigger-build-variables.hide
-
@build
.
trigger_
request
.
variables
.
each
do
|
key
,
valu
e
|
%dt
.js-build-variable.trigger-build-variable
=
key
%dd
.js-build-value.trigger-build-value
=
value
-
@build
.
trigger_
variables
.
each
do
|
trigger_variabl
e
|
%dt
.js-build-variable.trigger-build-variable
=
trigger_variable
[
:key
]
%dd
.js-build-value.trigger-build-value
=
trigger_variable
[
:value
]
%div
{
class:
(
@build
.
pipeline
.
stages_count
>
1
?
"block"
:
"block-last"
)
}
%p
...
...
This diff is collapsed.
Click to expand it.
app/workers/stuck_ci_jobs_worker.rb
View file @
f041c389
...
...
@@ -53,7 +53,7 @@ class StuckCiJobsWorker
def
drop_build
(
type
,
build
,
status
,
timeout
)
Rails
.
logger
.
info
"
#{
self
.
class
}
: Dropping
#{
type
}
build
#{
build
.
id
}
for runner
#{
build
.
runner_id
}
(status:
#{
status
}
, timeout:
#{
timeout
}
)"
Gitlab
::
OptimisticLocking
.
retry_lock
(
build
,
3
)
do
|
b
|
b
.
drop
b
.
drop
(
:stuck_or_timeout_failure
)
end
end
end
This diff is collapsed.
Click to expand it.
changelogs/unreleased/additional-time-series-charts.yml
0 → 100644
View file @
f041c389
---
title
:
Added support the multiple time series for prometheus monitoring
merge_request
:
!36893
author
:
type
:
changed
This diff is collapsed.
Click to expand it.
changelogs/unreleased/feature-sm-34518-extend-api-pipeline-schedule-variable-new.yml
0 → 100644
View file @
f041c389
---
title
:
'
Extend
API:
Pipeline
Schedule
Variable'
merge_request
:
13653
author
:
type
:
added
This diff is collapsed.
Click to expand it.
changelogs/unreleased/feature-sm-37239-implement-failure_reason-on-ci_builds.yml
0 → 100644
View file @
f041c389
---
title
:
Implement `failure_reason` on `ci_builds`
merge_request
:
13937
author
:
type
:
added
This diff is collapsed.
Click to expand it.
db/migrate/20170830125940_add_failure_reason_to_ci_builds.rb
0 → 100644
View file @
f041c389
class
AddFailureReasonToCiBuilds
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
def
change
add_column
:ci_builds
,
:failure_reason
,
:integer
end
end
This diff is collapsed.
Click to expand it.
db/schema.rb
View file @
f041c389
...
...
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
201708
24162758
)
do
ActiveRecord
::
Schema
.
define
(
version:
201708
30125940
)
do
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
...
...
@@ -247,6 +247,7 @@ ActiveRecord::Schema.define(version: 20170824162758) do
t
.
boolean
"retried"
t
.
integer
"stage_id"
t
.
boolean
"protected"
t
.
integer
"failure_reason"
end
add_index
"ci_builds"
,
[
"auto_canceled_by_id"
],
name:
"index_ci_builds_on_auto_canceled_by_id"
,
using: :btree
...
...
This diff is collapsed.
Click to expand it.
doc/api/pipeline_schedules.md
View file @
f041c389
...
...
@@ -84,7 +84,13 @@ curl --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" "https://gitlab.example.com/
"state"
:
"active"
,
"avatar_url"
:
"http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
,
"web_url"
:
"https://gitlab.example.com/root"
}
},
"variables"
:
[
{
"key"
:
"TEST_VARIABLE_1"
,
"value"
:
"TEST_1"
}
]
}
```
...
...
@@ -271,3 +277,86 @@ curl --request DELETE --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" "https://gi
}
}
```
## Pipeline schedule variable
> [Introduced][ce-34518] in GitLab 10.0.
## Create a new pipeline schedule variable
Create a new variable of a pipeline schedule.
```
POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables
```
| Attribute | Type | required | Description |
|------------------------|----------------|----------|--------------------------|
|
`id`
| integer/string | yes | The ID or
[
URL-encoded path of the project
](
README.md#namespaced-path-encoding
)
owned by the authenticated user |
|
`pipeline_schedule_id`
| integer | yes | The pipeline schedule id |
|
`key`
| string | yes | The
`key`
of a variable; must have no more than 255 characters; only
`A-Z`
,
`a-z`
,
`0-9`
, and
`_`
are allowed |
|
`value`
| string | yes | The
`value`
of a variable |
```
sh
curl
--request
POST
--header
"PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ"
--form
"key=NEW_VARIABLE"
--form
"value=new value"
"https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables"
```
```
json
{
"key"
:
"NEW_VARIABLE"
,
"value"
:
"new value"
}
```
## Edit a pipeline schedule variable
Updates the variable of a pipeline schedule.
```
PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key
```
| Attribute | Type | required | Description |
|------------------------|----------------|----------|--------------------------|
|
`id`
| integer/string | yes | The ID or
[
URL-encoded path of the project
](
README.md#namespaced-path-encoding
)
owned by the authenticated user |
|
`pipeline_schedule_id`
| integer | yes | The pipeline schedule id |
|
`key`
| string | yes | The
`key`
of a variable |
|
`value`
| string | yes | The
`value`
of a variable |
```
sh
curl
--request
PUT
--header
"PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ"
--form
"value=updated value"
"https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables/NEW_VARIABLE"
```
```
json
{
"key"
:
"NEW_VARIABLE"
,
"value"
:
"updated value"
}
```
## Delete a pipeline schedule variable
Delete the variable of a pipeline schedule.
```
DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key
```
| Attribute | Type | required | Description |
|------------------------|----------------|----------|--------------------------|
|
`id`
| integer/string | yes | The ID or
[
URL-encoded path of the project
](
README.md#namespaced-path-encoding
)
owned by the authenticated user |
|
`pipeline_schedule_id`
| integer | yes | The pipeline schedule id |
|
`key`
| string | yes | The
`key`
of a variable |
```
sh
curl
--request
DELETE
--header
"PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ"
"https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables/NEW_VARIABLE"
```
```
json
{
"key"
:
"NEW_VARIABLE"
,
"value"
:
"updated value"
}
```
[
ce-34518
]:
https://gitlab.com/gitlab-org/gitlab-ce/issues/34518
\ No newline at end of file
This diff is collapsed.
Click to expand it.
doc/ci/yaml/README.md
View file @
f041c389
...
...
@@ -130,7 +130,7 @@ There are also two edge cases worth mentioning:
### types
> Deprecated, and
will be removed in 10.0
. Use [stages](#stages) instead.
> Deprecated, and
could be removed in one of the future releases
. Use [stages](#stages) instead.
Alias for
[
stages
](
#stages
)
.
...
...
This diff is collapsed.
Click to expand it.
lib/api/commit_statuses.rb
View file @
f041c389
...
...
@@ -103,7 +103,7 @@ module API
when
'success'
status
.
success!
when
'failed'
status
.
drop!
status
.
drop!
(
:api_failure
)
when
'canceled'
status
.
cancel!
else
...
...
This diff is collapsed.
Click to expand it.
lib/api/entities.rb
View file @
f041c389
...
...
@@ -819,7 +819,7 @@ module API
class
Variable
<
Grape
::
Entity
expose
:key
,
:value
expose
:protected?
,
as: :protected
expose
:protected?
,
as: :protected
,
if:
->
(
entity
,
_
)
{
entity
.
respond_to?
(
:protected?
)
}
end
class
Pipeline
<
PipelineBasic
...
...
@@ -840,6 +840,7 @@ module API
class
PipelineScheduleDetails
<
PipelineSchedule
expose
:last_pipeline
,
using:
Entities
::
PipelineBasic
expose
:variables
,
using:
Entities
::
Variable
end
class
EnvironmentBasic
<
Grape
::
Entity
...
...
This diff is collapsed.
Click to expand it.
lib/api/pipeline_schedules.rb
View file @
f041c389
...
...
@@ -31,10 +31,6 @@ module API
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline schedule id'
end
get
':id/pipeline_schedules/:pipeline_schedule_id'
do
authorize!
:read_pipeline_schedule
,
user_project
not_found!
(
'PipelineSchedule'
)
unless
pipeline_schedule
present
pipeline_schedule
,
with:
Entities
::
PipelineScheduleDetails
end
...
...
@@ -74,9 +70,6 @@ module API
optional
:active
,
type:
Boolean
,
desc:
'The activation of pipeline schedule'
end
put
':id/pipeline_schedules/:pipeline_schedule_id'
do
authorize!
:read_pipeline_schedule
,
user_project
not_found!
(
'PipelineSchedule'
)
unless
pipeline_schedule
authorize!
:update_pipeline_schedule
,
pipeline_schedule
if
pipeline_schedule
.
update
(
declared_params
(
include_missing:
false
))
...
...
@@ -93,9 +86,6 @@ module API
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline schedule id'
end
post
':id/pipeline_schedules/:pipeline_schedule_id/take_ownership'
do
authorize!
:read_pipeline_schedule
,
user_project
not_found!
(
'PipelineSchedule'
)
unless
pipeline_schedule
authorize!
:update_pipeline_schedule
,
pipeline_schedule
if
pipeline_schedule
.
own!
(
current_user
)
...
...
@@ -112,21 +102,84 @@ module API
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline schedule id'
end
delete
':id/pipeline_schedules/:pipeline_schedule_id'
do
authorize!
:read_pipeline_schedule
,
user_project
not_found!
(
'PipelineSchedule'
)
unless
pipeline_schedule
authorize!
:admin_pipeline_schedule
,
pipeline_schedule
destroy_conditionally!
(
pipeline_schedule
)
end
desc
'Create a new pipeline schedule variable'
do
success
Entities
::
Variable
end
params
do
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline schedule id'
requires
:key
,
type:
String
,
desc:
'The key of the variable'
requires
:value
,
type:
String
,
desc:
'The value of the variable'
end
post
':id/pipeline_schedules/:pipeline_schedule_id/variables'
do
authorize!
:update_pipeline_schedule
,
pipeline_schedule
variable_params
=
declared_params
(
include_missing:
false
)
variable
=
pipeline_schedule
.
variables
.
create
(
variable_params
)
if
variable
.
persisted?
present
variable
,
with:
Entities
::
Variable
else
render_validation_error!
(
variable
)
end
end
desc
'Edit a pipeline schedule variable'
do
success
Entities
::
Variable
end
params
do
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline schedule id'
requires
:key
,
type:
String
,
desc:
'The key of the variable'
optional
:value
,
type:
String
,
desc:
'The value of the variable'
end
put
':id/pipeline_schedules/:pipeline_schedule_id/variables/:key'
do
authorize!
:update_pipeline_schedule
,
pipeline_schedule
if
pipeline_schedule_variable
.
update
(
declared_params
(
include_missing:
false
))
present
pipeline_schedule_variable
,
with:
Entities
::
Variable
else
render_validation_error!
(
pipeline_schedule_variable
)
end
end
desc
'Delete a pipeline schedule variable'
do
success
Entities
::
Variable
end
params
do
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline schedule id'
requires
:key
,
type:
String
,
desc:
'The key of the variable'
end
delete
':id/pipeline_schedules/:pipeline_schedule_id/variables/:key'
do
authorize!
:admin_pipeline_schedule
,
pipeline_schedule
status
:accepted
present
pipeline_schedule_variable
.
destroy
,
with:
Entities
::
Variable
end
end
helpers
do
def
pipeline_schedule
@pipeline_schedule
||=
user_project
.
pipeline_schedules
.
preload
(
:owner
,
:last_pipeline
)
.
find_by
(
id:
params
.
delete
(
:pipeline_schedule_id
))
user_project
.
pipeline_schedules
.
preload
(
:owner
,
:last_pipeline
)
.
find_by
(
id:
params
.
delete
(
:pipeline_schedule_id
)).
tap
do
|
pipeline_schedule
|
unless
can?
(
current_user
,
:read_pipeline_schedule
,
pipeline_schedule
)
not_found!
(
'Pipeline Schedule'
)
end
end
end
def
pipeline_schedule_variable
@pipeline_schedule_variable
||=
pipeline_schedule
.
variables
.
find_by
(
key:
params
[
:key
]).
tap
do
|
pipeline_schedule_variable
|
unless
pipeline_schedule_variable
not_found!
(
'Pipeline Schedule Variable'
)
end
end
end
end
end
...
...
This diff is collapsed.
Click to expand it.
lib/api/runner.rb
View file @
f041c389
...
...
@@ -114,6 +114,8 @@ module API
requires
:id
,
type:
Integer
,
desc:
%q(Job's ID)
optional
:trace
,
type:
String
,
desc:
%q(Job's full trace)
optional
:state
,
type:
String
,
desc:
%q(Job's status: success, failed)
optional
:failure_reason
,
type:
String
,
values:
CommitStatus
.
failure_reasons
.
keys
,
desc:
%q(Job's failure_reason)
end
put
'/:id'
do
job
=
authenticate_job!
...
...
@@ -127,7 +129,7 @@ module API
when
'success'
job
.
success
when
'failed'
job
.
drop
job
.
drop
(
params
[
:failure_reason
]
||
:unknown_failure
)
end
end
...
...
This diff is collapsed.
Click to expand it.
lib/api/v3/triggers.rb
View file @
f041c389
...
...
@@ -16,25 +16,31 @@ module API
optional
:variables
,
type:
Hash
,
desc:
'The list of variables to be injected into build'
end
post
":id/(ref/:ref/)trigger/builds"
,
requirements:
{
ref:
/.+/
}
do
project
=
find_project
(
params
[
:id
])
trigger
=
Ci
::
Trigger
.
find_by_token
(
params
[
:token
].
to_s
)
not_found!
unless
project
&&
trigger
unauthorized!
unless
trigger
.
project
==
project
# validate variables
variables
=
params
[
:variables
].
to_h
unless
variables
.
all?
{
|
key
,
value
|
key
.
is_a?
(
String
)
&&
value
.
is_a?
(
String
)
}
params
[
:variables
]
=
params
[
:variables
].
to_h
unless
params
[
:variables
]
.
all?
{
|
key
,
value
|
key
.
is_a?
(
String
)
&&
value
.
is_a?
(
String
)
}
render_api_error!
(
'variables needs to be a map of key-valued strings'
,
400
)
end
# create request and trigger builds
result
=
Ci
::
CreateTriggerRequestService
.
execute
(
project
,
trigger
,
params
[
:ref
].
to_s
,
variables
)
pipeline
=
result
.
pipeline
project
=
find_project
(
params
[
:id
])
not_found!
unless
project
result
=
Ci
::
PipelineTriggerService
.
new
(
project
,
nil
,
params
).
execute
not_found!
unless
result
if
pipeline
.
persisted?
present
result
.
trigger_request
,
with:
::
API
::
V3
::
Entities
::
TriggerRequest
if
result
[
:http_status
]
render_api_error!
(
result
[
:message
],
result
[
:http_status
])
else
render_validation_error!
(
pipeline
)
pipeline
=
result
[
:pipeline
]
# We switched to Ci::PipelineVariable from Ci::TriggerRequest.variables.
# Ci::TriggerRequest doesn't save variables anymore.
# Here is copying Ci::PipelineVariable to Ci::TriggerRequest.variables for presenting the variables.
# The same endpoint in v4 API pressents Pipeline instead of TriggerRequest, so it doesn't need such a process.
trigger_request
=
pipeline
.
trigger_requests
.
last
trigger_request
.
variables
=
params
[
:variables
]
present
trigger_request
,
with:
::
API
::
V3
::
Entities
::
TriggerRequest
end
end
...
...
This diff is collapsed.
Click to expand it.
spec/factories/ci/builds.rb
View file @
f041c389
...
...
@@ -107,7 +107,7 @@ FactoryGirl.define do
end
trait
:triggered
do
trigger_request
factory: :ci_trigger_request
_with_variables
trigger_request
factory: :ci_trigger_request
end
after
(
:build
)
do
|
build
,
evaluator
|
...
...
This diff is collapsed.
Click to expand it.
spec/factories/ci/pipeline_variable
_variable
s.rb
→
spec/factories/ci/pipeline_variables.rb
View file @
f041c389
File moved
This diff is collapsed.
Click to expand it.
spec/factories/ci/trigger_requests.rb
View file @
f041c389
FactoryGirl
.
define
do
factory
:ci_trigger_request
,
class:
Ci
::
TriggerRequest
do
trigger
factory: :ci_trigger
factory
:ci_trigger_request_with_variables
do
variables
do
{
TRIGGER_KEY_1
:
'TRIGGER_VALUE_1'
,
TRIGGER_KEY_2
:
'TRIGGER_VALUE_2'
}
end
end
end
end
This diff is collapsed.
Click to expand it.
spec/features/projects/jobs_spec.rb
View file @
f041c389
...
...
@@ -292,26 +292,44 @@ feature 'Jobs' do
end
feature
'Variables'
do
let
(
:trigger_request
)
{
create
(
:ci_trigger_request
_with_variables
)
}
let
(
:trigger_request
)
{
create
(
:ci_trigger_request
)
}
let
(
:job
)
do
create
:ci_build
,
pipeline:
pipeline
,
trigger_request:
trigger_request
end
before
do
visit
project_job_path
(
project
,
job
)
shared_examples
'expected variables behavior'
do
it
'shows variable key and value after click'
,
js:
true
do
expect
(
page
).
to
have_css
(
'.reveal-variables'
)
expect
(
page
).
not_to
have_css
(
'.js-build-variable'
)
expect
(
page
).
not_to
have_css
(
'.js-build-value'
)
click_button
'Reveal Variables'
expect
(
page
).
not_to
have_css
(
'.reveal-variables'
)
expect
(
page
).
to
have_selector
(
'.js-build-variable'
,
text:
'TRIGGER_KEY_1'
)
expect
(
page
).
to
have_selector
(
'.js-build-value'
,
text:
'TRIGGER_VALUE_1'
)
end
end
it
'shows variable key and value after click'
,
js:
true
do
expect
(
page
).
to
have_css
(
'.reveal-variables'
)
expect
(
page
).
not_to
have_css
(
'.js-build-variable'
)
expect
(
page
).
not_to
have_css
(
'.js-build-value'
)
context
'when variables are stored in trigger_request'
do
before
do
trigger_request
.
update_attribute
(
:variables
,
{
'TRIGGER_KEY_1'
=>
'TRIGGER_VALUE_1'
}
)
click_button
'Reveal Variables'
visit
project_job_path
(
project
,
job
)
end
it_behaves_like
'expected variables behavior'
end
context
'when variables are stored in pipeline_variables'
do
before
do
create
(
:ci_pipeline_variable
,
pipeline:
pipeline
,
key:
'TRIGGER_KEY_1'
,
value:
'TRIGGER_VALUE_1'
)
visit
project_job_path
(
project
,
job
)
end
expect
(
page
).
not_to
have_css
(
'.reveal-variables'
)
expect
(
page
).
to
have_selector
(
'.js-build-variable'
,
text:
'TRIGGER_KEY_1'
)
expect
(
page
).
to
have_selector
(
'.js-build-value'
,
text:
'TRIGGER_VALUE_1'
)
it_behaves_like
'expected variables behavior'
end
end
...
...
This diff is collapsed.
Click to expand it.
spec/fixtures/api/schemas/pipeline_schedule.json
View file @
f041c389
...
...
@@ -31,6 +31,10 @@
"web_url"
:
{
"type"
:
"uri"
}
},
"additionalProperties"
:
false
},
"variables"
:
{
"type"
:
[
"array"
,
"null"
],
"items"
:
{
"$ref"
:
"pipeline_schedule_variable.json"
}
}
},
"required"
:
[
...
...
This diff is collapsed.
Click to expand it.
spec/fixtures/api/schemas/pipeline_schedule_variable.json
0 → 100644
View file @
f041c389
{
"type"
:
[
"object"
,
"null"
],
"properties"
:
{
"key"
:
{
"type"
:
"string"
},
"value"
:
{
"type"
:
"string"
}
},
"additionalProperties"
:
false
}
This diff is collapsed.
Click to expand it.
spec/javascripts/monitoring/graph/flag_spec.js
View file @
f041c389
...
...
@@ -32,10 +32,6 @@ describe('GraphFlag', () => {
.
toEqual
(
component
.
currentXCoordinate
);
expect
(
getCoordinate
(
component
,
'
.selected-metric-line
'
,
'
x2
'
))
.
toEqual
(
component
.
currentXCoordinate
);
expect
(
getCoordinate
(
component
,
'
.circle-metric
'
,
'
cx
'
))
.
toEqual
(
component
.
currentXCoordinate
);
expect
(
getCoordinate
(
component
,
'
.circle-metric
'
,
'
cy
'
))
.
toEqual
(
component
.
currentYCoordinate
);
});
it
(
'
has a SVG with the class rect-text-metric at the currentFlagPosition
'
,
()
=>
{
...
...
This diff is collapsed.
Click to expand it.
spec/javascripts/monitoring/graph/legend_spec.js
View file @
f041c389
import
Vue
from
'
vue
'
;
import
GraphLegend
from
'
~/monitoring/components/graph/legend.vue
'
;
import
measurements
from
'
~/monitoring/utils/measurements
'
;
import
createTimeSeries
from
'
~/monitoring/utils/multiple_time_series
'
;
import
{
singleRowMetricsMultipleSeries
,
convertDatesMultipleSeries
}
from
'
../mock_data
'
;
const
createComponent
=
(
propsData
)
=>
{
const
Component
=
Vue
.
extend
(
GraphLegend
);
...
...
@@ -10,6 +12,28 @@ const createComponent = (propsData) => {
}).
$mount
();
};
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
const
defaultValuesComponent
=
{
graphWidth
:
500
,
graphHeight
:
300
,
graphHeightOffset
:
120
,
margin
:
measurements
.
large
.
margin
,
measurements
:
measurements
.
large
,
areaColorRgb
:
'
#f0f0f0
'
,
legendTitle
:
'
Title
'
,
yAxisLabel
:
'
Values
'
,
metricUsage
:
'
Value
'
,
unitOfDisplay
:
'
Req/Sec
'
,
currentDataIndex
:
0
,
};
const
timeSeries
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
[
0
].
result
,
defaultValuesComponent
.
graphWidth
,
defaultValuesComponent
.
graphHeight
,
defaultValuesComponent
.
graphHeightOffset
);
defaultValuesComponent
.
timeSeries
=
timeSeries
;
function
getTextFromNode
(
component
,
selector
)
{
return
component
.
$el
.
querySelector
(
selector
).
firstChild
.
nodeValue
.
trim
();
}
...
...
@@ -17,95 +41,67 @@ function getTextFromNode(component, selector) {
describe
(
'
GraphLegend
'
,
()
=>
{
describe
(
'
Computed props
'
,
()
=>
{
it
(
'
textTransform
'
,
()
=>
{
const
component
=
createComponent
({
graphWidth
:
500
,
graphHeight
:
300
,
margin
:
measurements
.
large
.
margin
,
measurements
:
measurements
.
large
,
areaColorRgb
:
'
#f0f0f0
'
,
legendTitle
:
'
Title
'
,
yAxisLabel
:
'
Values
'
,
metricUsage
:
'
Value
'
,
});
const
component
=
createComponent
(
defaultValuesComponent
);
expect
(
component
.
textTransform
).
toContain
(
'
translate(15, 120) rotate(-90)
'
);
});
it
(
'
xPosition
'
,
()
=>
{
const
component
=
createComponent
({
graphWidth
:
500
,
graphHeight
:
300
,
margin
:
measurements
.
large
.
margin
,
measurements
:
measurements
.
large
,
areaColorRgb
:
'
#f0f0f0
'
,
legendTitle
:
'
Title
'
,
yAxisLabel
:
'
Values
'
,
metricUsage
:
'
Value
'
,
});
const
component
=
createComponent
(
defaultValuesComponent
);
expect
(
component
.
xPosition
).
toEqual
(
180
);
});
it
(
'
yPosition
'
,
()
=>
{
const
component
=
createComponent
({
graphWidth
:
500
,
graphHeight
:
300
,
margin
:
measurements
.
large
.
margin
,
measurements
:
measurements
.
large
,
areaColorRgb
:
'
#f0f0f0
'
,
legendTitle
:
'
Title
'
,
yAxisLabel
:
'
Values
'
,
metricUsage
:
'
Value
'
,
});
const
component
=
createComponent
(
defaultValuesComponent
);
expect
(
component
.
yPosition
).
toEqual
(
240
);
});
it
(
'
rectTransform
'
,
()
=>
{
const
component
=
createComponent
({
graphWidth
:
500
,
graphHeight
:
300
,
margin
:
measurements
.
large
.
margin
,
measurements
:
measurements
.
large
,
areaColorRgb
:
'
#f0f0f0
'
,
legendTitle
:
'
Title
'
,
yAxisLabel
:
'
Values
'
,
metricUsage
:
'
Value
'
,
});
const
component
=
createComponent
(
defaultValuesComponent
);
expect
(
component
.
rectTransform
).
toContain
(
'
translate(0, 120) rotate(-90)
'
);
});
});
it
(
'
has 2 rect-axis-text rect svg elements
'
,
()
=>
{
const
component
=
createComponent
({
graphWidth
:
500
,
graphHeight
:
300
,
margin
:
measurements
.
large
.
margin
,
measurements
:
measurements
.
large
,
areaColorRgb
:
'
#f0f0f0
'
,
legendTitle
:
'
Title
'
,
yAxisLabel
:
'
Values
'
,
metricUsage
:
'
Value
'
,
describe
(
'
methods
'
,
()
=>
{
it
(
'
translateLegendGroup should only change Y direction
'
,
()
=>
{
const
component
=
createComponent
(
defaultValuesComponent
);
const
translatedCoordinate
=
component
.
translateLegendGroup
(
1
);
expect
(
translatedCoordinate
.
indexOf
(
'
translate(0,
'
)).
not
.
toEqual
(
-
1
);
});
it
(
'
formatMetricUsage should contain the unit of display and the current value selected via "currentDataIndex"
'
,
()
=>
{
const
component
=
createComponent
(
defaultValuesComponent
);
const
formattedMetricUsage
=
component
.
formatMetricUsage
(
timeSeries
[
0
]);
const
valueFromSeries
=
timeSeries
[
0
].
values
[
component
.
currentDataIndex
].
value
;
expect
(
formattedMetricUsage
.
indexOf
(
component
.
unitOfDisplay
)).
not
.
toEqual
(
-
1
);
expect
(
formattedMetricUsage
.
indexOf
(
valueFromSeries
)).
not
.
toEqual
(
-
1
);
});
});
it
(
'
has 2 rect-axis-text rect svg elements
'
,
()
=>
{
const
component
=
createComponent
(
defaultValuesComponent
);
expect
(
component
.
$el
.
querySelectorAll
(
'
.rect-axis-text
'
).
length
).
toEqual
(
2
);
});
it
(
'
contains text to signal the usage, title and time
'
,
()
=>
{
const
component
=
createComponent
({
graphWidth
:
500
,
graphHeight
:
300
,
margin
:
measurements
.
large
.
margin
,
measurements
:
measurements
.
large
,
areaColorRgb
:
'
#f0f0f0
'
,
legendTitle
:
'
Title
'
,
yAxisLabel
:
'
Values
'
,
metricUsage
:
'
Value
'
,
});
const
component
=
createComponent
(
defaultValuesComponent
);
const
titles
=
component
.
$el
.
querySelectorAll
(
'
.legend-metric-title
'
);
expect
(
getTextFromNode
(
component
,
'
.legend-metric-title
'
).
indexOf
(
component
.
legendTitle
)).
not
.
toEqual
(
-
1
);
expect
(
titles
[
0
].
textContent
.
indexOf
(
'
Title
'
)).
not
.
toEqual
(
-
1
);
expect
(
titles
[
1
].
textContent
.
indexOf
(
'
Series
'
)).
not
.
toEqual
(
-
1
);
expect
(
getTextFromNode
(
component
,
'
.y-label-text
'
)).
toEqual
(
component
.
yAxisLabel
);
});
it
(
'
should contain the same number of legend groups as the timeSeries length
'
,
()
=>
{
const
component
=
createComponent
(
defaultValuesComponent
);
expect
(
getTextFromNode
(
component
,
'
.text-metric-title
'
)).
toEqual
(
component
.
legendTitle
);
expect
(
getTextFromNode
(
component
,
'
.text-metric-usage
'
)).
toEqual
(
component
.
metricUsage
);
expect
(
getTextFromNode
(
component
,
'
.label-axis-text
'
)).
toEqual
(
component
.
yAxisLabel
);
expect
(
component
.
$el
.
querySelectorAll
(
'
.legend-group
'
).
length
).
toEqual
(
component
.
timeSeries
.
length
);
});
});
This diff is collapsed.
Click to expand it.
spec/javascripts/monitoring/graph_row_spec.js
View file @
f041c389
import
Vue
from
'
vue
'
;
import
GraphRow
from
'
~/monitoring/components/graph_row.vue
'
;
import
MonitoringMixins
from
'
~/monitoring/mixins/monitoring_mixins
'
;
import
{
deploymentData
,
singleRowMetric
s
}
from
'
./mock_data
'
;
import
{
deploymentData
,
convertDatesMultipleSeries
,
singleRowMetricsMultipleSerie
s
}
from
'
./mock_data
'
;
const
createComponent
=
(
propsData
)
=>
{
const
Component
=
Vue
.
extend
(
GraphRow
);
...
...
@@ -11,15 +11,15 @@ const createComponent = (propsData) => {
}).
$mount
();
};
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
describe
(
'
GraphRow
'
,
()
=>
{
beforeEach
(()
=>
{
spyOn
(
MonitoringMixins
.
methods
,
'
formatDeployments
'
).
and
.
returnValue
({});
});
describe
(
'
Computed props
'
,
()
=>
{
it
(
'
bootstrapClass is set to col-md-6 when rowData is higher/equal to 2
'
,
()
=>
{
const
component
=
createComponent
({
rowData
:
singleRow
Metrics
,
rowData
:
converted
Metrics
,
updateAspectRatio
:
false
,
deploymentData
,
});
...
...
@@ -29,7 +29,7 @@ describe('GraphRow', () => {
it
(
'
bootstrapClass is set to col-md-12 when rowData is lower than 2
'
,
()
=>
{
const
component
=
createComponent
({
rowData
:
[
singleRow
Metrics
[
0
]],
rowData
:
[
converted
Metrics
[
0
]],
updateAspectRatio
:
false
,
deploymentData
,
});
...
...
@@ -40,7 +40,7 @@ describe('GraphRow', () => {
it
(
'
has one column
'
,
()
=>
{
const
component
=
createComponent
({
rowData
:
singleRow
Metrics
,
rowData
:
converted
Metrics
,
updateAspectRatio
:
false
,
deploymentData
,
});
...
...
@@ -51,7 +51,7 @@ describe('GraphRow', () => {
it
(
'
has two columns
'
,
()
=>
{
const
component
=
createComponent
({
rowData
:
singleRow
Metrics
,
rowData
:
converted
Metrics
,
updateAspectRatio
:
false
,
deploymentData
,
});
...
...
This diff is collapsed.
Click to expand it.
spec/javascripts/monitoring/graph_spec.js
View file @
f041c389
import
Vue
from
'
vue
'
;
import
_
from
'
underscore
'
;
import
Graph
from
'
~/monitoring/components/graph.vue
'
;
import
MonitoringMixins
from
'
~/monitoring/mixins/monitoring_mixins
'
;
import
eventHub
from
'
~/monitoring/event_hub
'
;
import
{
deploymentData
,
singleRowMetric
s
}
from
'
./mock_data
'
;
import
{
deploymentData
,
convertDatesMultipleSeries
,
singleRowMetricsMultipleSerie
s
}
from
'
./mock_data
'
;
const
createComponent
=
(
propsData
)
=>
{
const
Component
=
Vue
.
extend
(
Graph
);
...
...
@@ -13,6 +12,8 @@ const createComponent = (propsData) => {
}).
$mount
();
};
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
describe
(
'
Graph
'
,
()
=>
{
beforeEach
(()
=>
{
spyOn
(
MonitoringMixins
.
methods
,
'
formatDeployments
'
).
and
.
returnValue
({});
...
...
@@ -20,7 +21,7 @@ describe('Graph', () => {
it
(
'
has a title
'
,
()
=>
{
const
component
=
createComponent
({
graphData
:
singleRowMetrics
[
0
],
graphData
:
convertedMetrics
[
1
],
classType
:
'
col-md-6
'
,
updateAspectRatio
:
false
,
deploymentData
,
...
...
@@ -29,29 +30,10 @@ describe('Graph', () => {
expect
(
component
.
$el
.
querySelector
(
'
.text-center
'
).
innerText
.
trim
()).
toBe
(
component
.
graphData
.
title
);
});
it
(
'
creates a path for the line and area of the graph
'
,
(
done
)
=>
{
const
component
=
createComponent
({
graphData
:
singleRowMetrics
[
0
],
classType
:
'
col-md-6
'
,
updateAspectRatio
:
false
,
deploymentData
,
});
Vue
.
nextTick
(()
=>
{
expect
(
component
.
area
).
toBeDefined
();
expect
(
component
.
line
).
toBeDefined
();
expect
(
typeof
component
.
area
).
toEqual
(
'
string
'
);
expect
(
typeof
component
.
line
).
toEqual
(
'
string
'
);
expect
(
_
.
isFunction
(
component
.
xScale
)).
toBe
(
true
);
expect
(
_
.
isFunction
(
component
.
yScale
)).
toBe
(
true
);
done
();
});
});
describe
(
'
Computed props
'
,
()
=>
{
it
(
'
axisTransform translates an element Y position depending of its height
'
,
()
=>
{
const
component
=
createComponent
({
graphData
:
singleRowMetrics
[
0
],
graphData
:
convertedMetrics
[
1
],
classType
:
'
col-md-6
'
,
updateAspectRatio
:
false
,
deploymentData
,
...
...
@@ -64,7 +46,7 @@ describe('Graph', () => {
it
(
'
outterViewBox gets a width and height property based on the DOM size of the element
'
,
()
=>
{
const
component
=
createComponent
({
graphData
:
singleRowMetrics
[
0
],
graphData
:
convertedMetrics
[
1
],
classType
:
'
col-md-6
'
,
updateAspectRatio
:
false
,
deploymentData
,
...
...
@@ -79,7 +61,7 @@ describe('Graph', () => {
it
(
'
sends an event to the eventhub when it has finished resizing
'
,
(
done
)
=>
{
const
component
=
createComponent
({
graphData
:
singleRowMetrics
[
0
],
graphData
:
convertedMetrics
[
1
],
classType
:
'
col-md-6
'
,
updateAspectRatio
:
false
,
deploymentData
,
...
...
@@ -95,7 +77,7 @@ describe('Graph', () => {
it
(
'
has a title for the y-axis and the chart legend that comes from the backend
'
,
()
=>
{
const
component
=
createComponent
({
graphData
:
singleRowMetrics
[
0
],
graphData
:
convertedMetrics
[
1
],
classType
:
'
col-md-6
'
,
updateAspectRatio
:
false
,
deploymentData
,
...
...
This diff is collapsed.
Click to expand it.
spec/javascripts/monitoring/mock_data.js
View file @
f041c389
This diff is collapsed.
Click to expand it.
spec/javascripts/monitoring/monitoring_paths_spec.js
0 → 100644
View file @
f041c389
import
Vue
from
'
vue
'
;
import
MonitoringPaths
from
'
~/monitoring/components/monitoring_paths.vue
'
;
import
createTimeSeries
from
'
~/monitoring/utils/multiple_time_series
'
;
import
{
singleRowMetricsMultipleSeries
,
convertDatesMultipleSeries
}
from
'
./mock_data
'
;
const
createComponent
=
(
propsData
)
=>
{
const
Component
=
Vue
.
extend
(
MonitoringPaths
);
return
new
Component
({
propsData
,
}).
$mount
();
};
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
const
timeSeries
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
[
0
].
result
,
428
,
272
,
120
);
describe
(
'
Monitoring Paths
'
,
()
=>
{
it
(
'
renders two paths to represent a line and the area underneath it
'
,
()
=>
{
const
component
=
createComponent
({
generatedLinePath
:
timeSeries
[
0
].
linePath
,
generatedAreaPath
:
timeSeries
[
0
].
areaPath
,
lineColor
:
'
#ccc
'
,
areaColor
:
'
#fff
'
,
});
const
metricArea
=
component
.
$el
.
querySelector
(
'
.metric-area
'
);
const
metricLine
=
component
.
$el
.
querySelector
(
'
.metric-line
'
);
expect
(
metricArea
.
getAttribute
(
'
fill
'
)).
toBe
(
'
#fff
'
);
expect
(
metricArea
.
getAttribute
(
'
d
'
)).
toBe
(
timeSeries
[
0
].
areaPath
);
expect
(
metricLine
.
getAttribute
(
'
stroke
'
)).
toBe
(
'
#ccc
'
);
expect
(
metricLine
.
getAttribute
(
'
d
'
)).
toBe
(
timeSeries
[
0
].
linePath
);
});
});
This diff is collapsed.
Click to expand it.
spec/javascripts/monitoring/utils/multiple_time_series_spec.js
0 → 100644
View file @
f041c389
import
createTimeSeries
from
'
~/monitoring/utils/multiple_time_series
'
;
import
{
convertDatesMultipleSeries
,
singleRowMetricsMultipleSeries
}
from
'
../mock_data
'
;
const
convertedMetrics
=
convertDatesMultipleSeries
(
singleRowMetricsMultipleSeries
);
const
timeSeries
=
createTimeSeries
(
convertedMetrics
[
0
].
queries
[
0
].
result
,
428
,
272
,
120
);
describe
(
'
Multiple time series
'
,
()
=>
{
it
(
'
createTimeSeries returned array contains an object for each element
'
,
()
=>
{
expect
(
typeof
timeSeries
[
0
].
linePath
).
toEqual
(
'
string
'
);
expect
(
typeof
timeSeries
[
0
].
areaPath
).
toEqual
(
'
string
'
);
expect
(
typeof
timeSeries
[
0
].
timeSeriesScaleX
).
toEqual
(
'
function
'
);
expect
(
typeof
timeSeries
[
0
].
areaColor
).
toEqual
(
'
string
'
);
expect
(
typeof
timeSeries
[
0
].
lineColor
).
toEqual
(
'
string
'
);
expect
(
timeSeries
[
0
].
values
instanceof
Array
).
toEqual
(
true
);
});
it
(
'
createTimeSeries returns an array
'
,
()
=>
{
expect
(
timeSeries
instanceof
Array
).
toEqual
(
true
);
expect
(
timeSeries
.
length
).
toEqual
(
2
);
});
});
This diff is collapsed.
Click to expand it.
spec/lib/gitlab/import_export/safe_model_attributes.yml
View file @
f041c389
...
...
@@ -278,6 +278,7 @@ CommitStatus:
-
auto_canceled_by_id
-
retried
-
protected
-
failure_reason
Ci::Variable:
-
id
-
project_id
...
...
This diff is collapsed.
Click to expand it.
spec/models/ci/build_spec.rb
View file @
f041c389
...
...
@@ -1492,10 +1492,12 @@ describe Ci::Build do
context
'when build is for triggers'
do
let
(
:trigger
)
{
create
(
:ci_trigger
,
project:
project
)
}
let
(
:trigger_request
)
{
create
(
:ci_trigger_request_with_variables
,
pipeline:
pipeline
,
trigger:
trigger
)
}
let
(
:trigger_request
)
{
create
(
:ci_trigger_request
,
pipeline:
pipeline
,
trigger:
trigger
)
}
let
(
:user_trigger_variable
)
do
{
key:
:TRIGGER_KEY_1
,
value:
'TRIGGER_VALUE_1'
,
public:
false
}
{
key:
'TRIGGER_KEY_1'
,
value:
'TRIGGER_VALUE_1'
,
public:
false
}
end
let
(
:predefined_trigger_variable
)
do
{
key:
'CI_PIPELINE_TRIGGERED'
,
value:
'true'
,
public:
true
}
end
...
...
@@ -1504,8 +1506,26 @@ describe Ci::Build do
build
.
trigger_request
=
trigger_request
end
it
{
is_expected
.
to
include
(
user_trigger_variable
)
}
it
{
is_expected
.
to
include
(
predefined_trigger_variable
)
}
shared_examples
'returns variables for triggers'
do
it
{
is_expected
.
to
include
(
user_trigger_variable
)
}
it
{
is_expected
.
to
include
(
predefined_trigger_variable
)
}
end
context
'when variables are stored in trigger_request'
do
before
do
trigger_request
.
update_attribute
(
:variables
,
{
'TRIGGER_KEY_1'
=>
'TRIGGER_VALUE_1'
}
)
end
it_behaves_like
'returns variables for triggers'
end
context
'when variables are stored in pipeline_variables'
do
before
do
create
(
:ci_pipeline_variable
,
pipeline:
pipeline
,
key:
'TRIGGER_KEY_1'
,
value:
'TRIGGER_VALUE_1'
)
end
it_behaves_like
'returns variables for triggers'
end
end
context
'when pipeline has a variable'
do
...
...
This diff is collapsed.
Click to expand it.
spec/models/ci/trigger_request_spec.rb
0 → 100644
View file @
f041c389
require
'spec_helper'
describe
Ci
::
TriggerRequest
do
describe
'validation'
do
it
'be invalid if saving a variable'
do
trigger
=
build
(
:ci_trigger_request
,
variables:
{
TRIGGER_KEY_1
:
'TRIGGER_VALUE_1'
}
)
expect
(
trigger
).
not_to
be_valid
end
it
'be valid if not saving a variable'
do
trigger
=
build
(
:ci_trigger_request
)
expect
(
trigger
).
to
be_valid
end
end
end
This diff is collapsed.
Click to expand it.
spec/models/commit_status_spec.rb
View file @
f041c389
...
...
@@ -443,4 +443,25 @@ describe CommitStatus do
end
end
end
describe
'set failure_reason when drop'
do
let
(
:commit_status
)
{
create
(
:commit_status
,
:created
)
}
subject
do
commit_status
.
drop!
(
reason
)
commit_status
end
context
'when failure_reason is nil'
do
let
(
:reason
)
{
}
it
{
is_expected
.
to
be_unknown_failure
}
end
context
'when failure_reason is script_failure'
do
let
(
:reason
)
{
:script_failure
}
it
{
is_expected
.
to
be_script_failure
}
end
end
end
This diff is collapsed.
Click to expand it.
spec/presenters/ci/build_presenter_spec.rb
View file @
f041c389
...
...
@@ -100,4 +100,38 @@ describe Ci::BuildPresenter do
end
end
end
describe
'#trigger_variables'
do
let
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
trigger_request:
trigger_request
)
}
let
(
:trigger
)
{
create
(
:ci_trigger
,
project:
project
)
}
let
(
:trigger_request
)
{
create
(
:ci_trigger_request
,
pipeline:
pipeline
,
trigger:
trigger
)
}
context
'when variable is stored in ci_pipeline_variables'
do
let!
(
:pipeline_variable
)
{
create
(
:ci_pipeline_variable
,
pipeline:
pipeline
)
}
context
'when pipeline is triggered by trigger API'
do
it
'returns variables'
do
expect
(
presenter
.
trigger_variables
).
to
eq
([
pipeline_variable
.
to_runner_variable
])
end
end
context
'when pipeline is not triggered by trigger API'
do
let
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
)
}
it
'does not return variables'
do
expect
(
presenter
.
trigger_variables
).
to
eq
([])
end
end
end
context
'when variable is stored in ci_trigger_requests.variables'
do
before
do
trigger_request
.
update_attribute
(
:variables
,
{
'TRIGGER_KEY_1'
=>
'TRIGGER_VALUE_1'
}
)
end
it
'returns variables'
do
expect
(
presenter
.
trigger_variables
).
to
eq
(
trigger_request
.
user_variables
)
end
end
end
end
This diff is collapsed.
Click to expand it.
spec/requests/api/commit_statuses_spec.rb
View file @
f041c389
...
...
@@ -142,6 +142,9 @@ describe API::CommitStatuses do
expect
(
json_response
[
'ref'
]).
not_to
be_empty
expect
(
json_response
[
'target_url'
]).
to
be_nil
expect
(
json_response
[
'description'
]).
to
be_nil
if
status
==
'failed'
expect
(
CommitStatus
.
find
(
json_response
[
'id'
])).
to
be_api_failure
end
end
end
end
...
...
This diff is collapsed.
Click to expand it.
spec/requests/api/pipeline_schedules_spec.rb
View file @
f041c389
...
...
@@ -3,7 +3,7 @@ require 'spec_helper'
describe
API
::
PipelineSchedules
do
set
(
:developer
)
{
create
(
:user
)
}
set
(
:user
)
{
create
(
:user
)
}
set
(
:project
)
{
create
(
:project
,
:repository
)
}
set
(
:project
)
{
create
(
:project
,
:repository
,
public_builds:
false
)
}
before
do
project
.
add_developer
(
developer
)
...
...
@@ -110,6 +110,18 @@ describe API::PipelineSchedules do
end
end
context
'authenticated user with insufficient permissions'
do
before
do
project
.
add_guest
(
user
)
end
it
'does not return pipeline_schedules list'
do
get
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
,
user
)
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'unauthenticated user'
do
it
'does not return pipeline_schedules list'
do
get
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
)
...
...
@@ -299,4 +311,150 @@ describe API::PipelineSchedules do
end
end
end
describe
'POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables'
do
let
(
:params
)
{
attributes_for
(
:ci_pipeline_schedule_variable
)
}
set
(
:pipeline_schedule
)
do
create
(
:ci_pipeline_schedule
,
project:
project
,
owner:
developer
)
end
context
'authenticated user with valid permissions'
do
context
'with required parameters'
do
it
'creates pipeline_schedule_variable'
do
expect
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables"
,
developer
),
params
end
.
to
change
{
pipeline_schedule
.
variables
.
count
}.
by
(
1
)
expect
(
response
).
to
have_http_status
(
:created
)
expect
(
response
).
to
match_response_schema
(
'pipeline_schedule_variable'
)
expect
(
json_response
[
'key'
]).
to
eq
(
params
[
:key
])
expect
(
json_response
[
'value'
]).
to
eq
(
params
[
:value
])
end
end
context
'without required parameters'
do
it
'does not create pipeline_schedule_variable'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables"
,
developer
)
expect
(
response
).
to
have_http_status
(
:bad_request
)
end
end
context
'when key has validation error'
do
it
'does not create pipeline_schedule_variable'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables"
,
developer
),
params
.
merge
(
'key'
=>
'!?!?'
)
expect
(
response
).
to
have_http_status
(
:bad_request
)
expect
(
json_response
[
'message'
]).
to
have_key
(
'key'
)
end
end
end
context
'authenticated user with invalid permissions'
do
it
'does not create pipeline_schedule_variable'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables"
,
user
),
params
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'unauthenticated user'
do
it
'does not create pipeline_schedule_variable'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables"
),
params
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
end
describe
'PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key'
do
set
(
:pipeline_schedule
)
do
create
(
:ci_pipeline_schedule
,
project:
project
,
owner:
developer
)
end
let
(
:pipeline_schedule_variable
)
do
create
(
:ci_pipeline_schedule_variable
,
pipeline_schedule:
pipeline_schedule
)
end
context
'authenticated user with valid permissions'
do
it
'updates pipeline_schedule_variable'
do
put
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables/
#{
pipeline_schedule_variable
.
key
}
"
,
developer
),
value:
'updated_value'
expect
(
response
).
to
have_http_status
(
:ok
)
expect
(
response
).
to
match_response_schema
(
'pipeline_schedule_variable'
)
expect
(
json_response
[
'value'
]).
to
eq
(
'updated_value'
)
end
end
context
'authenticated user with invalid permissions'
do
it
'does not update pipeline_schedule_variable'
do
put
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables/
#{
pipeline_schedule_variable
.
key
}
"
,
user
)
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'unauthenticated user'
do
it
'does not update pipeline_schedule_variable'
do
put
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables/
#{
pipeline_schedule_variable
.
key
}
"
)
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
end
describe
'DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key'
do
let
(
:master
)
{
create
(
:user
)
}
set
(
:pipeline_schedule
)
do
create
(
:ci_pipeline_schedule
,
project:
project
,
owner:
developer
)
end
let!
(
:pipeline_schedule_variable
)
do
create
(
:ci_pipeline_schedule_variable
,
pipeline_schedule:
pipeline_schedule
)
end
before
do
project
.
add_master
(
master
)
end
context
'authenticated user with valid permissions'
do
it
'deletes pipeline_schedule_variable'
do
expect
do
delete
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables/
#{
pipeline_schedule_variable
.
key
}
"
,
master
)
end
.
to
change
{
Ci
::
PipelineScheduleVariable
.
count
}.
by
(
-
1
)
expect
(
response
).
to
have_http_status
(
:accepted
)
expect
(
response
).
to
match_response_schema
(
'pipeline_schedule_variable'
)
end
it
'responds with 404 Not Found if requesting non-existing pipeline_schedule_variable'
do
delete
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables/____"
,
master
)
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'authenticated user with invalid permissions'
do
let!
(
:pipeline_schedule
)
{
create
(
:ci_pipeline_schedule
,
project:
project
,
owner:
master
)
}
it
'does not delete pipeline_schedule_variable'
do
delete
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables/
#{
pipeline_schedule_variable
.
key
}
"
,
developer
)
expect
(
response
).
to
have_http_status
(
:forbidden
)
end
end
context
'unauthenticated user'
do
it
'does not delete pipeline_schedule_variable'
do
delete
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/variables/
#{
pipeline_schedule_variable
.
key
}
"
)
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
end
end
This diff is collapsed.
Click to expand it.
spec/requests/api/runner_spec.rb
View file @
f041c389
...
...
@@ -557,17 +557,36 @@ describe API::Runner do
{
'key'
=>
'TRIGGER_KEY_1'
,
'value'
=>
'TRIGGER_VALUE_1'
,
'public'
=>
false
}]
end
let
(
:trigger
)
{
create
(
:ci_trigger
,
project:
project
)
}
let!
(
:trigger_request
)
{
create
(
:ci_trigger_request
,
pipeline:
pipeline
,
builds:
[
job
],
trigger:
trigger
)
}
before
do
trigger
=
create
(
:ci_trigger
,
project:
project
)
create
(
:ci_trigger_request_with_variables
,
pipeline:
pipeline
,
builds:
[
job
],
trigger:
trigger
)
project
.
variables
<<
Ci
::
Variable
.
new
(
key:
'SECRET_KEY'
,
value:
'secret_value'
)
end
it
'returns variables for triggers'
do
request_job
shared_examples
'expected variables behavior'
do
it
'returns variables for triggers'
do
request_job
expect
(
response
).
to
have_http_status
(
201
)
expect
(
json_response
[
'variables'
]).
to
include
(
*
expected_variables
)
expect
(
response
).
to
have_http_status
(
201
)
expect
(
json_response
[
'variables'
]).
to
include
(
*
expected_variables
)
end
end
context
'when variables are stored in trigger_request'
do
before
do
trigger_request
.
update_attribute
(
:variables
,
{
TRIGGER_KEY_1
:
'TRIGGER_VALUE_1'
}
)
end
it_behaves_like
'expected variables behavior'
end
context
'when variables are stored in pipeline_variables'
do
before
do
create
(
:ci_pipeline_variable
,
pipeline:
pipeline
,
key: :TRIGGER_KEY_1
,
value:
'TRIGGER_VALUE_1'
)
end
it_behaves_like
'expected variables behavior'
end
end
...
...
@@ -626,13 +645,34 @@ describe API::Runner do
it
'mark job as succeeded'
do
update_job
(
state:
'success'
)
expect
(
job
.
reload
.
status
).
to
eq
'success'
job
.
reload
expect
(
job
).
to
be_success
end
it
'mark job as failed'
do
update_job
(
state:
'failed'
)
expect
(
job
.
reload
.
status
).
to
eq
'failed'
job
.
reload
expect
(
job
).
to
be_failed
expect
(
job
).
to
be_unknown_failure
end
context
'when failure_reason is script_failure'
do
before
do
update_job
(
state:
'failed'
,
failure_reason:
'script_failure'
)
job
.
reload
end
it
{
expect
(
job
).
to
be_script_failure
}
end
context
'when failure_reason is runner_system_failure'
do
before
do
update_job
(
state:
'failed'
,
failure_reason:
'runner_system_failure'
)
job
.
reload
end
it
{
expect
(
job
).
to
be_runner_system_failure
}
end
end
...
...
This diff is collapsed.
Click to expand it.
spec/requests/api/v3/triggers_spec.rb
View file @
f041c389
...
...
@@ -37,7 +37,7 @@ describe API::V3::Triggers do
it
'returns unauthorized if token is for different project'
do
post
v3_api
(
"/projects/
#{
project2
.
id
}
/trigger/builds"
),
options
.
merge
(
ref:
'master'
)
expect
(
response
).
to
have_http_status
(
40
1
)
expect
(
response
).
to
have_http_status
(
40
4
)
end
end
...
...
@@ -80,7 +80,8 @@ describe API::V3::Triggers do
post
v3_api
(
"/projects/
#{
project
.
id
}
/trigger/builds"
),
options
.
merge
(
variables:
variables
,
ref:
'master'
)
expect
(
response
).
to
have_http_status
(
201
)
pipeline
.
builds
.
reload
expect
(
pipeline
.
builds
.
first
.
trigger_request
.
variables
).
to
eq
(
variables
)
expect
(
pipeline
.
variables
.
map
{
|
v
|
{
v
.
key
=>
v
.
value
}
}.
first
).
to
eq
(
variables
)
expect
(
json_response
[
'variables'
]).
to
eq
(
variables
)
end
end
end
...
...
This diff is collapsed.
Click to expand it.
spec/services/ci/create_trigger_request_service_spec.rb
deleted
100644 → 0
View file @
a27c0013
require
'spec_helper'
describe
Ci
::
CreateTriggerRequestService
do
let
(
:service
)
{
described_class
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:trigger
)
{
create
(
:ci_trigger
,
project:
project
,
owner:
owner
)
}
let
(
:owner
)
{
create
(
:user
)
}
before
do
stub_ci_pipeline_to_return_yaml_file
project
.
add_developer
(
owner
)
end
describe
'#execute'
do
context
'valid params'
do
subject
{
service
.
execute
(
project
,
trigger
,
'master'
)
}
context
'without owner'
do
it
{
expect
(
subject
.
trigger_request
).
to
be_kind_of
(
Ci
::
TriggerRequest
)
}
it
{
expect
(
subject
.
trigger_request
.
builds
.
first
).
to
be_kind_of
(
Ci
::
Build
)
}
it
{
expect
(
subject
.
pipeline
).
to
be_kind_of
(
Ci
::
Pipeline
)
}
it
{
expect
(
subject
.
pipeline
).
to
be_trigger
}
end
context
'with owner'
do
it
{
expect
(
subject
.
trigger_request
).
to
be_kind_of
(
Ci
::
TriggerRequest
)
}
it
{
expect
(
subject
.
trigger_request
.
builds
.
first
).
to
be_kind_of
(
Ci
::
Build
)
}
it
{
expect
(
subject
.
trigger_request
.
builds
.
first
.
user
).
to
eq
(
owner
)
}
it
{
expect
(
subject
.
pipeline
).
to
be_kind_of
(
Ci
::
Pipeline
)
}
it
{
expect
(
subject
.
pipeline
).
to
be_trigger
}
it
{
expect
(
subject
.
pipeline
.
user
).
to
eq
(
owner
)
}
end
end
context
'no commit for ref'
do
subject
{
service
.
execute
(
project
,
trigger
,
'other-branch'
)
}
it
{
expect
(
subject
.
pipeline
).
not_to
be_persisted
}
end
context
'no builds created'
do
subject
{
service
.
execute
(
project
,
trigger
,
'master'
)
}
before
do
stub_ci_pipeline_yaml_file
(
'script: { only: [develop], script: hello World }'
)
end
it
{
expect
(
subject
.
pipeline
).
not_to
be_persisted
}
end
end
end
This diff is collapsed.
Click to expand it.
spec/services/ci/retry_build_service_spec.rb
View file @
f041c389
...
...
@@ -22,7 +22,7 @@ describe Ci::RetryBuildService do
%i[type lock_version target_url base_tags
commit_id deployments erased_by_id last_deployment project_id
runner_id tag_taggings taggings tags trigger_request_id
user_id auto_canceled_by_id retried]
.
freeze
user_id auto_canceled_by_id retried
failure_reason
]
.
freeze
shared_examples
'build duplication'
do
let
(
:stage
)
do
...
...
This diff is collapsed.
Click to expand it.
spec/services/projects/update_pages_service_spec.rb
View file @
f041c389
...
...
@@ -116,6 +116,7 @@ describe Projects::UpdatePagesService do
expect
(
deploy_status
.
description
)
.
to
match
(
/artifacts for pages are too large/
)
expect
(
deploy_status
).
to
be_script_failure
end
end
...
...
This diff is collapsed.
Click to expand it.
spec/views/projects/jobs/show.html.haml_spec.rb
View file @
f041c389
...
...
@@ -195,20 +195,4 @@ describe 'projects/jobs/show' do
text:
/\A\n
#{
Regexp
.
escape
(
commit_title
)
}
\n\Z/
)
end
end
describe
'shows trigger variables in sidebar'
do
let
(
:trigger_request
)
{
create
(
:ci_trigger_request_with_variables
,
pipeline:
pipeline
)
}
before
do
build
.
trigger_request
=
trigger_request
render
end
it
'shows trigger variables in separate lines'
do
expect
(
rendered
).
to
have_css
(
'.js-build-variable'
,
visible:
false
,
text:
'TRIGGER_KEY_1'
)
expect
(
rendered
).
to
have_css
(
'.js-build-variable'
,
visible:
false
,
text:
'TRIGGER_KEY_2'
)
expect
(
rendered
).
to
have_css
(
'.js-build-value'
,
visible:
false
,
text:
'TRIGGER_VALUE_1'
)
expect
(
rendered
).
to
have_css
(
'.js-build-value'
,
visible:
false
,
text:
'TRIGGER_VALUE_2'
)
end
end
end
This diff is collapsed.
Click to expand it.
spec/workers/stuck_ci_jobs_worker_spec.rb
View file @
f041c389
...
...
@@ -6,27 +6,31 @@ describe StuckCiJobsWorker do
let
(
:worker
)
{
described_class
.
new
}
let
(
:exclusive_lease_uuid
)
{
SecureRandom
.
uuid
}
subject
do
job
.
reload
job
.
status
end
before
do
job
.
update!
(
status:
status
,
updated_at:
updated_at
)
allow_any_instance_of
(
Gitlab
::
ExclusiveLease
).
to
receive
(
:try_obtain
).
and_return
(
exclusive_lease_uuid
)
end
shared_examples
'job is dropped'
do
it
'changes status'
do
before
do
worker
.
perform
is_expected
.
to
eq
(
'failed'
)
job
.
reload
end
it
"changes status"
do
expect
(
job
).
to
be_failed
expect
(
job
).
to
be_stuck_or_timeout_failure
end
end
shared_examples
'job is unchanged'
do
it
"doesn't change status"
do
before
do
worker
.
perform
is_expected
.
to
eq
(
status
)
job
.
reload
end
it
"doesn't change status"
do
expect
(
job
.
status
).
to
eq
(
status
)
end
end
...
...
This diff is collapsed.
Click to expand it.
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