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
7a6b566c
Commit
7a6b566c
authored
Mar 21, 2018
by
Filipa Lacerda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Render dependency scanning report on CI view and MR widget
parent
5833ba11
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
289 additions
and
63 deletions
+289
-63
app/assets/javascripts/pipelines/pipeline_details_bundle.js
app/assets/javascripts/pipelines/pipeline_details_bundle.js
+35
-5
app/assets/javascripts/pipelines/pipeline_details_mediator.js
...assets/javascripts/pipelines/pipeline_details_mediator.js
+8
-0
app/assets/javascripts/pipelines/stores/pipeline_store.js
app/assets/javascripts/pipelines/stores/pipeline_store.js
+7
-0
app/views/projects/pipelines/_info.html.haml
app/views/projects/pipelines/_info.html.haml
+2
-1
app/views/projects/pipelines/_with_tabs.html.haml
app/views/projects/pipelines/_with_tabs.html.haml
+6
-3
ee/app/assets/javascripts/pipelines/components/security_reports/sast_report_summary_widget.vue
...omponents/security_reports/sast_report_summary_widget.vue
+8
-14
ee/app/assets/javascripts/pipelines/components/security_reports/security_report_app.vue
...lines/components/security_reports/security_report_app.vue
+28
-1
ee/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
...javascripts/vue_merge_request_widget/mr_widget_options.js
+131
-38
ee/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
...cripts/vue_merge_request_widget/stores/mr_widget_store.js
+17
-0
ee/app/assets/javascripts/vue_shared/security_reports/components/report_section.vue
...vue_shared/security_reports/components/report_section.vue
+1
-1
ee/app/assets/javascripts/vue_shared/security_reports/helpers/state.js
.../javascripts/vue_shared/security_reports/helpers/state.js
+7
-0
ee/app/assets/javascripts/vue_shared/security_reports/mixins/security_report_mixin.js
...e_shared/security_reports/mixins/security_report_mixin.js
+34
-0
ee/app/assets/stylesheets/pages/security_reports.scss
ee/app/assets/stylesheets/pages/security_reports.scss
+5
-0
No files found.
app/assets/javascripts/pipelines/pipeline_details_bundle.js
View file @
7a6b566c
...
...
@@ -81,24 +81,51 @@ export default () => {
const
securityTab
=
document
.
getElementById
(
'
js-security-report-app
'
);
const
sastSummary
=
document
.
querySelector
(
'
.js-sast-summary
'
);
const
updateBadgeCount
=
(
count
)
=>
{
const
badge
=
document
.
querySelector
(
'
.js-sast-counter
'
);
if
(
badge
.
textContent
!==
''
)
{
badge
.
textContent
=
parseInt
(
badge
.
textContent
,
10
)
+
count
;
}
else
{
badge
.
textContent
=
count
;
}
badge
.
classList
.
remove
(
'
hidden
'
);
};
// They are being rendered under the same condition
if
(
securityTab
&&
sastSummary
)
{
const
datasetOptions
=
securityTab
.
dataset
;
const
endpoint
=
datasetOptions
.
endpoint
;
const
blobPath
=
datasetOptions
.
blobPath
;
const
dependencyScanningEndpoint
=
datasetOptions
.
dependencyScanningEndpoint
;
mediator
.
fetchSastReport
(
endpoint
,
blobPath
)
if
(
endpoint
)
{
mediator
.
fetchSastReport
(
endpoint
,
blobPath
)
.
then
(()
=>
{
// update the badge
if
(
mediator
.
store
.
state
.
securityReports
.
sast
.
newIssues
.
length
)
{
const
badge
=
document
.
querySelector
(
'
.js-sast-counter
'
);
badge
.
textContent
=
mediator
.
store
.
state
.
securityReports
.
sast
.
newIssues
.
length
;
badge
.
classList
.
remove
(
'
hidden
'
);
updateBadgeCount
(
mediator
.
store
.
state
.
securityReports
.
sast
.
newIssues
.
length
);
}
})
.
catch
(()
=>
{
Flash
(
__
(
'
Something went wrong while fetching SAST.
'
));
});
}
if
(
dependencyScanningEndpoint
)
{
mediator
.
fetchDependencyScanningReport
(
dependencyScanningEndpoint
)
.
then
(()
=>
{
// update the badge
if
(
mediator
.
store
.
state
.
securityReports
.
dependencyScanning
.
newIssues
.
length
)
{
updateBadgeCount
(
mediator
.
store
.
state
.
securityReports
.
dependencyScanning
.
newIssues
.
length
,
);
}
})
.
catch
(()
=>
{
Flash
(
__
(
'
Something went wrong while fetching Dependency Scanning.
'
));
});
}
// Widget summary
// eslint-disable-next-line no-new
...
...
@@ -115,7 +142,8 @@ export default () => {
render
(
createElement
)
{
return
createElement
(
'
sast-summary-widget
'
,
{
props
:
{
unresolvedIssues
:
this
.
mediator
.
store
.
state
.
securityReports
.
sast
.
newIssues
,
unresolvedIssues
:
this
.
mediator
.
store
.
state
.
securityReports
.
sast
.
newIssues
.
length
+
this
.
mediator
.
store
.
state
.
securityReports
.
dependencyScanning
.
newIssues
.
length
,
},
});
},
...
...
@@ -137,6 +165,8 @@ export default () => {
return
createElement
(
'
security-report-app
'
,
{
props
:
{
securityReports
:
this
.
mediator
.
store
.
state
.
securityReports
,
hasDependencyScanning
:
dependencyScanningEndpoint
!==
undefined
,
hasSast
:
endpoint
!==
undefined
,
},
});
},
...
...
app/assets/javascripts/pipelines/pipeline_details_mediator.js
View file @
7a6b566c
...
...
@@ -67,4 +67,12 @@ export default class pipelinesMediator {
this
.
store
.
storeSastReport
(
data
,
blobPath
);
});
}
fetchDependencyScanningReport
(
endpoint
,
blobPath
)
{
return
PipelineService
.
getSecurityReport
(
endpoint
)
.
then
(
response
=>
response
.
json
())
.
then
((
data
)
=>
{
this
.
store
.
storeDependencyScanningReport
(
data
,
blobPath
);
});
}
}
app/assets/javascripts/pipelines/stores/pipeline_store.js
View file @
7a6b566c
...
...
@@ -26,4 +26,11 @@ export default class PipelineStore {
setSastReport
({
head
:
data
,
headBlobPath
:
blobPath
}),
);
}
storeDependencyScanningReport
(
data
,
blobPath
)
{
Object
.
assign
(
this
.
state
.
securityReports
.
dependencyScanning
,
setSastReport
({
head
:
data
,
headBlobPath
:
blobPath
}),
);
}
}
app/views/projects/pipelines/_info.html.haml
View file @
7a6b566c
#js-pipeline-header-vue
.pipeline-header-container
-
sast_artifact
=
@pipeline
.
sast_artifact
-
dependecy_artifact
=
@pipeline
.
dependency_scanning_artifact
-
if
@commit
.
present?
.commit-box
...
...
@@ -35,5 +36,5 @@
=
link_to
@pipeline
.
sha
,
project_commit_path
(
@project
,
@pipeline
.
sha
),
class:
"commit-sha commit-hash-full"
=
clipboard_button
(
text:
@pipeline
.
sha
,
title:
"Copy commit SHA to clipboard"
)
-
if
sast_artifact
-
if
sast_artifact
||
dependecy_artifact
.js-sast-summary
app/views/projects/pipelines/_with_tabs.html.haml
View file @
7a6b566c
-
failed_builds
=
@pipeline
.
statuses
.
latest
.
failed
-
expose_sast_data
=
@pipeline
.
expose_sast_data?
-
expose_dependency_data
=
@pipeline
.
expose_dependency_scanning_data?
-
blob_path
=
project_blob_path
(
@project
,
@pipeline
.
sha
)
.tabs-holder
...
...
@@ -16,7 +17,7 @@
=
link_to
failures_project_pipeline_path
(
@project
,
@pipeline
),
data:
{
target:
'#js-tab-failures'
,
action:
'failures'
,
toggle:
'tab'
},
class:
'failures-tab'
do
=
_
(
"Failed Jobs"
)
%span
.badge.js-failures-counter
=
failed_builds
.
count
-
if
expose_sast_data
-
if
expose_sast_data
||
expose_dependency_data
%li
.js-security-tab-link
=
link_to
security_project_pipeline_path
(
@project
,
@pipeline
),
data:
{
target:
'#js-tab-security'
,
action:
'security'
,
toggle:
'tab'
},
class:
'security-tab'
do
=
_
(
"Security report"
)
...
...
@@ -60,6 +61,8 @@
%span
.build-name
=
link_to
build
.
name
,
pipeline_job_url
(
pipeline
,
build
)
%pre
.build-log
=
build_summary
(
build
,
skip:
index
>=
10
)
-
if
expose_sast_data
-
if
expose_sast_data
||
expose_dependency_data
#js-tab-security
.build-security.tab-pane
#js-security-report-app
{
data:
{
endpoint:
sast_artifact_url
(
@pipeline
),
blob_path:
blob_path
}
}
#js-security-report-app
{
data:
{
endpoint:
expose_sast_data
?
sast_artifact_url
(
@pipeline
)
:
nil
,
blob_path:
blob_path
,
dependency_scanning_endpoint:
expose_dependency_data
?
dependency_scanning_artifact_url
(
@pipeline
)
:
nil
}
}
ee/app/assets/javascripts/pipelines/components/security_reports/sast_report_summary_widget.vue
View file @
7a6b566c
<
script
>
import
$
from
'
jquery
'
;
import
{
n__
,
s__
}
from
'
~/locale
'
;
import
c
iIcon
from
'
~/vue_shared/components/ci_icon.vue
'
;
import
C
iIcon
from
'
~/vue_shared/components/ci_icon.vue
'
;
export
default
{
name
:
'
SastSummaryReport
'
,
components
:
{
c
iIcon
,
C
iIcon
,
},
props
:
{
unresolvedIssues
:
{
type
:
Array
,
type
:
Number
,
required
:
false
,
default
:
()
=>
([])
,
default
:
0
,
},
},
computed
:
{
sastText
()
{
if
(
this
.
unresolvedIssues
.
length
)
{
return
s__
(
'
ciReport|SAST degraded on
'
);
}
return
s__
(
'
ciReport|SAST detected
'
);
},
sastLink
()
{
if
(
this
.
unresolvedIssues
.
length
)
{
if
(
this
.
unresolvedIssues
>
0
)
{
return
n__
(
'
%d security vulnerability
'
,
'
%d security vulnerabilities
'
,
this
.
unresolvedIssues
.
length
,
this
.
unresolvedIssues
,
);
}
return
s__
(
'
ciReport|no security vulnerabilities
'
);
},
statusIcon
()
{
if
(
this
.
unresolvedIssues
.
length
)
{
if
(
this
.
unresolvedIssues
>
0
)
{
return
{
group
:
'
warning
'
,
icon
:
'
status_warning
'
,
...
...
@@ -65,7 +59,7 @@
<span
class=
"prepend-left-10 flex flex-align-self-center"
>
{{
s
astText
}}
{{
s
__
(
'
ciReport|Security reports detected
'
)
}}
<button
type=
"button"
class=
"btn-link btn-blank prepend-left-5"
...
...
ee/app/assets/javascripts/pipelines/components/security_reports/security_report_app.vue
View file @
7a6b566c
...
...
@@ -17,12 +17,23 @@
type
:
Object
,
required
:
true
,
},
hasDependencyScanning
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
hasSast
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
};
</
script
>
<
template
>
<div
class=
"pipeline-tab-content"
>
<report-section
v-if=
"hasSast"
class=
"js-sast-widget"
:type=
"$options.sast"
:status=
"checkReportStatus(securityReports.sast.isLoading, securityReports.sast.hasError)"
...
...
@@ -32,7 +43,23 @@
:unresolved-issues=
"securityReports.sast.newIssues"
:resolved-issues=
"securityReports.sast.resolvedIssues"
:all-issues=
"securityReports.sast.allIssues"
:is-collapsible=
"false"
/>
<report-section
v-if=
"hasDependencyScanning"
class=
"js-dependency-scanning-widget"
:class=
"
{ 'prepend-top-20': hasSast }"
:type="$options.sast"
:status="checkReportStatus(
securityReports.dependencyScanning.isLoading,
securityReports.dependencyScanning.hasError
)"
:loading-text="translateText('dependency scanning').loading"
:error-text="translateText('dependency scanning').error"
:success-text="depedencyScanningText(securityReports.dependencyScanning.newIssues, securityReports.dependencyScanning.resolvedIssues)"
:unresolved-issues="securityReports.dependencyScanning.newIssues"
:resolved-issues="securityReports.dependencyScanning.resolvedIssues"
:all-issues="securityReports.dependencyScanning.allIssues"
/>
</div>
</
template
>
ee/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
View file @
7a6b566c
...
...
@@ -17,9 +17,7 @@ export default {
'
mr-widget-geo-secondary-node
'
:
GeoSecondaryNode
,
ReportSection
,
},
mixins
:
[
securityMixin
,
],
mixins
:
[
securityMixin
],
dast
:
DAST
,
sast
:
SAST
,
sastContainer
:
SAST_CONTAINER
,
...
...
@@ -30,11 +28,13 @@ export default {
isLoadingSecurity
:
false
,
isLoadingDocker
:
false
,
isLoadingDast
:
false
,
isLoadingDependencyScanning
:
false
,
loadingCodequalityFailed
:
false
,
loadingPerformanceFailed
:
false
,
loadingSecurityFailed
:
false
,
loadingDockerFailed
:
false
,
loadingDastFailed
:
false
,
loadingDependencyScanningFailed
:
false
,
};
},
computed
:
{
...
...
@@ -53,10 +53,13 @@ export default {
return
this
.
mr
.
sast
&&
this
.
mr
.
sast
.
head_path
;
},
shouldRenderDockerReport
()
{
return
this
.
mr
.
sastContainer
;
return
this
.
mr
.
sastContainer
&&
this
.
mr
.
sastContainer
.
head_path
;
},
shouldRenderDastReport
()
{
return
this
.
mr
.
dast
;
return
this
.
mr
.
dast
&&
this
.
mr
.
dast
.
head_path
;
},
shouldRenderDependencyReport
()
{
return
this
.
mr
.
dependencyScanning
&&
this
.
mr
.
dependencyScanning
.
head_path
;
},
codequalityText
()
{
const
{
newIssues
,
resolvedIssues
}
=
this
.
mr
.
codeclimateMetrics
;
...
...
@@ -68,11 +71,13 @@ export default {
text
.
push
(
s__
(
'
ciReport|Code quality
'
));
if
(
resolvedIssues
.
length
)
{
text
.
push
(
n__
(
'
improved on %d point
'
,
'
improved on %d points
'
,
resolvedIssues
.
length
,
));
text
.
push
(
n__
(
'
improved on %d point
'
,
'
improved on %d points
'
,
resolvedIssues
.
length
,
),
);
}
if
(
newIssues
.
length
>
0
&&
resolvedIssues
.
length
>
0
)
{
...
...
@@ -80,11 +85,13 @@ export default {
}
if
(
newIssues
.
length
)
{
text
.
push
(
n__
(
'
degraded on %d point
'
,
'
degraded on %d points
'
,
newIssues
.
length
,
));
text
.
push
(
n__
(
'
degraded on %d point
'
,
'
degraded on %d points
'
,
newIssues
.
length
,
),
);
}
}
...
...
@@ -101,11 +108,13 @@ export default {
text
.
push
(
s__
(
'
ciReport|Performance metrics
'
));
if
(
improved
.
length
)
{
text
.
push
(
n__
(
'
improved on %d point
'
,
'
improved on %d points
'
,
improved
.
length
,
));
text
.
push
(
n__
(
'
improved on %d point
'
,
'
improved on %d points
'
,
improved
.
length
,
),
);
}
if
(
improved
.
length
>
0
&&
degraded
.
length
>
0
)
{
...
...
@@ -113,11 +122,13 @@ export default {
}
if
(
degraded
.
length
)
{
text
.
push
(
n__
(
'
degraded on %d point
'
,
'
degraded on %d points
'
,
degraded
.
length
,
));
text
.
push
(
n__
(
'
degraded on %d point
'
,
'
degraded on %d points
'
,
degraded
.
length
,
),
);
}
}
...
...
@@ -129,6 +140,11 @@ export default {
return
this
.
sastText
(
newIssues
,
resolvedIssues
,
allIssues
);
},
dependencyScanningText
()
{
const
{
newIssues
,
resolvedIssues
,
allIssues
}
=
this
.
mr
.
dependencyScanningReport
;
return
this
.
depedencyScanningText
(
newIssues
,
resolvedIssues
,
allIssues
);
},
dockerText
()
{
const
{
vulnerabilities
,
approved
,
unapproved
}
=
this
.
mr
.
dockerReport
;
return
this
.
sastContainerText
(
vulnerabilities
,
approved
,
unapproved
);
...
...
@@ -139,24 +155,43 @@ export default {
},
codequalityStatus
()
{
return
this
.
checkReportStatus
(
this
.
isLoadingCodequality
,
this
.
loadingCodequalityFailed
);
return
this
.
checkReportStatus
(
this
.
isLoadingCodequality
,
this
.
loadingCodequalityFailed
,
);
},
performanceStatus
()
{
return
this
.
checkReportStatus
(
this
.
isLoadingPerformance
,
this
.
loadingPerformanceFailed
);
return
this
.
checkReportStatus
(
this
.
isLoadingPerformance
,
this
.
loadingPerformanceFailed
,
);
},
securityStatus
()
{
return
this
.
checkReportStatus
(
this
.
isLoadingSecurity
,
this
.
loadingSecurityFailed
);
return
this
.
checkReportStatus
(
this
.
isLoadingSecurity
,
this
.
loadingSecurityFailed
,
);
},
dockerStatus
()
{
return
this
.
checkReportStatus
(
this
.
isLoadingDocker
,
this
.
loadingDockerFailed
);
return
this
.
checkReportStatus
(
this
.
isLoadingDocker
,
this
.
loadingDockerFailed
,
);
},
dastStatus
()
{
return
this
.
checkReportStatus
(
this
.
isLoadingDast
,
this
.
loadingDastFailed
);
},
dependencyScanningStatus
()
{
return
this
.
checkReportStatus
(
this
.
isLoadingDependencyScanning
,
this
.
loadingDependencyScanningFailed
,
);
},
},
methods
:
{
fetchCodeQuality
()
{
...
...
@@ -168,7 +203,7 @@ export default {
this
.
service
.
fetchReport
(
head_path
),
this
.
service
.
fetchReport
(
base_path
),
])
.
then
(
(
values
)
=>
{
.
then
(
values
=>
{
this
.
mr
.
compareCodeclimateMetrics
(
values
[
0
],
values
[
1
],
...
...
@@ -192,7 +227,7 @@ export default {
this
.
service
.
fetchReport
(
head_path
),
this
.
service
.
fetchReport
(
base_path
),
])
.
then
(
(
values
)
=>
{
.
then
(
values
=>
{
this
.
mr
.
comparePerformanceMetrics
(
values
[
0
],
values
[
1
]);
this
.
isLoadingPerformance
=
false
;
})
...
...
@@ -216,7 +251,7 @@ export default {
this
.
service
.
fetchReport
(
sast
.
head_path
),
this
.
service
.
fetchReport
(
sast
.
base_path
),
])
.
then
(
(
values
)
=>
{
.
then
(
values
=>
{
this
.
handleSecuritySuccess
({
head
:
values
[
0
],
headBlobPath
:
this
.
mr
.
headBlobPath
,
...
...
@@ -226,8 +261,9 @@ export default {
})
.
catch
(()
=>
this
.
handleSecurityError
());
}
else
if
(
sast
.
head_path
)
{
this
.
service
.
fetchReport
(
sast
.
head_path
)
.
then
((
data
)
=>
{
this
.
service
.
fetchReport
(
sast
.
head_path
)
.
then
(
data
=>
{
this
.
handleSecuritySuccess
({
head
:
data
,
headBlobPath
:
this
.
mr
.
headBlobPath
,
...
...
@@ -237,6 +273,45 @@ export default {
}
},
fetchDependencyScanning
()
{
const
{
dependencyScanning
}
=
this
.
mr
;
this
.
isLoadingDependencyScanning
=
true
;
if
(
dependencyScanning
.
base_path
&&
dependencyScanning
.
head_path
)
{
Promise
.
all
([
this
.
service
.
fetchReport
(
dependencyScanning
.
head_path
),
this
.
service
.
fetchReport
(
dependencyScanning
.
base_path
),
])
.
then
(
values
=>
{
this
.
mr
.
setDependencyScanningReport
({
head
:
values
[
0
],
headBlobPath
:
this
.
mr
.
headBlobPath
,
base
:
values
[
1
],
baseBlobPath
:
this
.
mr
.
baseBlobPath
,
});
this
.
isLoadingDependencyScanning
=
false
;
})
.
catch
(()
=>
{
this
.
isLoadingDependencyScanning
=
false
;
this
.
loadingDependencyScanningFailed
=
true
;
});
}
else
if
(
dependencyScanning
.
head_path
)
{
this
.
service
.
fetchReport
(
dependencyScanning
.
head_path
)
.
then
(
data
=>
{
this
.
mr
.
setDependencyScanningReport
({
head
:
data
,
headBlobPath
:
this
.
mr
.
headBlobPath
,
});
})
.
catch
(()
=>
{
this
.
isLoadingDependencyScanning
=
false
;
this
.
loadingDependencyScanningFailed
=
true
;
});
}
},
handleSecuritySuccess
(
data
)
{
this
.
mr
.
setSecurityReport
(
data
);
this
.
isLoadingSecurity
=
false
;
...
...
@@ -251,8 +326,9 @@ export default {
const
{
head_path
}
=
this
.
mr
.
sastContainer
;
this
.
isLoadingDocker
=
true
;
this
.
service
.
fetchReport
(
head_path
)
.
then
((
data
)
=>
{
this
.
service
.
fetchReport
(
head_path
)
.
then
(
data
=>
{
this
.
mr
.
setDockerReport
(
data
);
this
.
isLoadingDocker
=
false
;
})
...
...
@@ -265,8 +341,9 @@ export default {
fetchDastReport
()
{
this
.
isLoadingDast
=
true
;
this
.
service
.
fetchReport
(
this
.
mr
.
dast
.
head_path
)
.
then
((
data
)
=>
{
this
.
service
.
fetchReport
(
this
.
mr
.
dast
.
head_path
)
.
then
(
data
=>
{
this
.
mr
.
setDastReport
(
data
);
this
.
isLoadingDast
=
false
;
})
...
...
@@ -296,6 +373,10 @@ export default {
if
(
this
.
shouldRenderDastReport
)
{
this
.
fetchDastReport
();
}
if
(
this
.
shouldRenderDependencyReport
)
{
this
.
fetchDependencyScanning
();
}
},
template
:
`
<div class="mr-state-widget prepend-top-default">
...
...
@@ -351,6 +432,18 @@ export default {
:resolved-issues="mr.securityReport.resolvedIssues"
:all-issues="mr.securityReport.allIssues"
/>
<report-section
class="js-dependency-scanning-widget"
v-if="shouldRenderDependencyReport"
:type="$options.sast"
:status="dependencyScanningStatus"
:loading-text="translateText('dependency scanning').loading"
:error-text="translateText('dependency scanning').error"
:success-text="dependencyScanningText"
:unresolved-issues="mr.dependencyScanningReport.newIssues"
:resolved-issues="mr.dependencyScanningReport.resolvedIssues"
:all-issues="mr.dependencyScanningReport.allIssues"
/>
<report-section
class="js-docker-widget"
v-if="shouldRenderDockerReport"
...
...
ee/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
View file @
7a6b566c
...
...
@@ -20,6 +20,7 @@ export default class MergeRequestStore extends CEMergeRequestStore {
this
.
initSecurityReport
(
data
);
this
.
initDockerReport
(
data
);
this
.
initDastReport
(
data
);
this
.
initDependencyScanningReport
(
data
);
}
setData
(
data
)
{
...
...
@@ -95,6 +96,15 @@ export default class MergeRequestStore extends CEMergeRequestStore {
this
.
dastReport
=
[];
}
initDependencyScanningReport
(
data
)
{
this
.
dependencyScanning
=
data
.
dependencyScanning
;
this
.
dependencyScanningReport
=
{
newIssues
:
[],
resolvedIssues
:
[],
allIssues
:
[],
};
}
setSecurityReport
(
data
)
{
const
report
=
setSastReport
(
data
);
this
.
securityReport
.
newIssues
=
report
.
newIssues
;
...
...
@@ -113,6 +123,13 @@ export default class MergeRequestStore extends CEMergeRequestStore {
this
.
dastReport
=
setDastReport
(
data
);
}
setDependencyScanningReport
(
data
)
{
const
report
=
setSastReport
(
data
);
this
.
dependencyScanningReport
.
newIssues
=
report
.
newIssues
;
this
.
dependencyScanningReport
.
resolvedIssues
=
report
.
resolvedIssues
;
this
.
dependencyScanningReport
.
allIssues
=
report
.
allIssues
;
}
compareCodeclimateMetrics
(
headIssues
,
baseIssues
,
headBlobPath
,
baseBlobPath
)
{
const
parsedHeadIssues
=
parseIssues
(
headIssues
,
headBlobPath
);
const
parsedBaseIssues
=
parseIssues
(
baseIssues
,
baseBlobPath
);
...
...
ee/app/assets/javascripts/vue_shared/security_reports/components/report_section.vue
View file @
7a6b566c
...
...
@@ -155,7 +155,7 @@
class=
"media-body space-children"
>
<span
class=
"js-code-text"
class=
"js-code-text
code-text
"
>
{{
successText
}}
</span>
...
...
ee/app/assets/javascripts/vue_shared/security_reports/helpers/state.js
View file @
7a6b566c
...
...
@@ -16,4 +16,11 @@ export default {
newIssues
:
[],
resolvedIssues
:
[],
},
dependencyScanning
:
{
isLoading
:
false
,
hasError
:
false
,
newIssues
:
[],
resolvedIssues
:
[],
allIssues
:
[],
},
};
ee/app/assets/javascripts/vue_shared/security_reports/mixins/security_report_mixin.js
View file @
7a6b566c
...
...
@@ -36,6 +36,40 @@ export default {
return
text
.
join
(
''
);
},
depedencyScanningText
(
newIssues
=
[],
resolvedIssues
=
[],
allIssues
=
[])
{
const
text
=
[];
if
(
!
newIssues
.
length
&&
!
resolvedIssues
.
length
&&
!
allIssues
.
length
)
{
text
.
push
(
s__
(
'
ciReport|Dependency scanning detected no security vulnerabilities
'
));
}
else
if
(
!
newIssues
.
length
&&
!
resolvedIssues
.
length
&&
allIssues
.
length
)
{
text
.
push
(
s__
(
'
ciReport|Dependency scanning detected no new security vulnerabilities
'
));
}
else
if
(
newIssues
.
length
||
resolvedIssues
.
length
)
{
text
.
push
(
s__
(
'
ciReport|Dependency scanning
'
));
}
if
(
resolvedIssues
.
length
)
{
text
.
push
(
n__
(
'
improved on %d security vulnerability
'
,
'
improved on %d security vulnerabilities
'
,
resolvedIssues
.
length
,
));
}
if
(
newIssues
.
length
>
0
&&
resolvedIssues
.
length
>
0
)
{
text
.
push
(
__
(
'
and
'
));
}
if
(
newIssues
.
length
)
{
text
.
push
(
n__
(
'
degraded on %d security vulnerability
'
,
'
degraded on %d security vulnerabilities
'
,
newIssues
.
length
,
));
}
return
text
.
join
(
''
);
},
translateText
(
type
)
{
return
{
error
:
sprintf
(
s__
(
'
ciReport|Failed to load %{reportName} report
'
),
{
reportName
:
type
}),
...
...
ee/app/assets/stylesheets/pages/security_reports.scss
View file @
7a6b566c
...
...
@@ -2,11 +2,16 @@
.space-children
,
.space-children
>
span
{
display
:
flex
;
align-self
:
center
;
}
.media
{
align-items
:
center
;
}
.code-text
{
width
:
100%
;
}
}
.report-block-container
{
...
...
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