Commit 5d662ff4 authored by Lukas 'Eipi' Eipert's avatar Lukas 'Eipi' Eipert Committed by Bob Van Landuyt

Delete old pipelines security report

With our completed migration of Security reports from the Frontend to
the Backend https://gitlab.com/groups/gitlab-org/-/epics/1425, we now
can delete the outdated pipelines security report.
parent c10e3d61
......@@ -2,8 +2,6 @@ import Vue from 'vue';
import { GlEmptyState } from '@gitlab/ui';
import createDashboardStore from 'ee/security_dashboard/store';
import SecurityDashboardApp from 'ee/security_dashboard/components/app.vue';
import SecurityReportApp from 'ee/vue_shared/security_reports/split_security_reports_app.vue';
import createStore from 'ee/vue_shared/security_reports/store';
import { s__ } from '~/locale';
import Translate from '~/vue_shared/translate';
......@@ -53,71 +51,10 @@ const initSecurityDashboardApp = el => {
});
};
const initSplitSecurityReportsApp = el => {
const datasetOptions = el.dataset;
const {
headBlobPath,
sourceBranch,
sastHeadPath,
sastHelpPath,
dependencyScanningHeadPath,
dependencyScanningHelpPath,
vulnerabilityFeedbackPath,
vulnerabilityFeedbackHelpPath,
createVulnerabilityFeedbackIssuePath,
createVulnerabilityFeedbackMergeRequestPath,
createVulnerabilityFeedbackDismissalPath,
dastHeadPath,
sastContainerHeadPath,
dastHelpPath,
sastContainerHelpPath,
} = datasetOptions;
const pipelineId = parseInt(datasetOptions.pipelineId, 10);
const store = createStore();
return new Vue({
el,
store,
components: {
SecurityReportApp,
},
render(createElement) {
return createElement('security-report-app', {
props: {
headBlobPath,
sourceBranch,
sastHeadPath,
sastHelpPath,
dependencyScanningHeadPath,
dependencyScanningHelpPath,
vulnerabilityFeedbackPath,
vulnerabilityFeedbackHelpPath,
createVulnerabilityFeedbackIssuePath,
createVulnerabilityFeedbackMergeRequestPath,
createVulnerabilityFeedbackDismissalPath,
pipelineId,
dastHeadPath,
sastContainerHeadPath,
dastHelpPath,
sastContainerHelpPath,
canCreateIssue: Boolean(createVulnerabilityFeedbackIssuePath),
canCreateMergeRequest: Boolean(createVulnerabilityFeedbackMergeRequestPath),
canDismissVulnerability: Boolean(createVulnerabilityFeedbackDismissalPath),
},
});
},
});
};
export default () => {
const securityTab = document.getElementById('js-security-report-app');
if (securityTab) {
if (gon.features && gon.features.pipelineReportApi) {
initSecurityDashboardApp(securityTab);
} else {
initSplitSecurityReportsApp(securityTab);
}
initSecurityDashboardApp(securityTab);
}
};
<script>
import { mapActions, mapState } from 'vuex';
import { componentNames } from 'ee/reports/components/issue_body';
import { s__, sprintf, n__ } from '~/locale';
import createFlash from '~/flash';
import ReportSection from '~/reports/components/report_section.vue';
import IssueModal from './components/modal.vue';
import mixin from './mixins/security_report_mixin';
import reportsMixin from './mixins/reports_mixin';
import messages from './store/messages';
export default {
components: {
ReportSection,
IssueModal,
},
messages,
mixins: [mixin, reportsMixin],
props: {
alwaysOpen: {
type: Boolean,
required: false,
default: false,
},
headBlobPath: {
type: String,
required: true,
},
sourceBranch: {
type: String,
required: false,
default: null,
},
sastHeadPath: {
type: String,
required: false,
default: null,
},
dastHeadPath: {
type: String,
required: false,
default: null,
},
sastContainerHeadPath: {
type: String,
required: false,
default: null,
},
dependencyScanningHeadPath: {
type: String,
required: false,
default: null,
},
sastHelpPath: {
type: String,
required: false,
default: null,
},
sastContainerHelpPath: {
type: String,
required: false,
default: '',
},
dastHelpPath: {
type: String,
required: false,
default: '',
},
dependencyScanningHelpPath: {
type: String,
required: false,
default: null,
},
vulnerabilityFeedbackPath: {
type: String,
required: false,
default: '',
},
vulnerabilityFeedbackHelpPath: {
type: String,
required: false,
default: '',
},
createVulnerabilityFeedbackIssuePath: {
type: String,
required: false,
default: '',
},
createVulnerabilityFeedbackMergeRequestPath: {
type: String,
required: false,
default: '',
},
createVulnerabilityFeedbackDismissalPath: {
type: String,
required: false,
default: '',
},
pipelineId: {
type: Number,
required: false,
default: null,
},
canCreateIssue: {
type: Boolean,
required: true,
},
canCreateMergeRequest: {
type: Boolean,
required: true,
},
canDismissVulnerability: {
type: Boolean,
required: true,
},
},
componentNames,
computed: {
...mapState([
'sast',
'dependencyScanning',
'sastContainer',
'dast',
'modal',
'canCreateIssuePermission',
'canCreateFeedbackPermission',
]),
sastText() {
return this.summaryTextBuilder(messages.SAST, this.sast.newIssues.length);
},
dependencyScanningText() {
return this.summaryTextBuilder(
messages.DEPENDENCY_SCANNING,
this.dependencyScanning.newIssues.length,
);
},
sastContainerText() {
return this.summaryTextBuilder(
messages.CONTAINER_SCANNING,
this.sastContainer.newIssues.length,
);
},
dastText() {
return this.summaryTextBuilder(messages.DAST, this.dast.newIssues.length);
},
issuesCount() {
return (
this.dast.newIssues.length +
this.dependencyScanning.newIssues.length +
this.sastContainer.newIssues.length +
this.sast.newIssues.length
);
},
},
created() {
// update the store with the received props
this.setHeadBlobPath(this.headBlobPath);
this.setSourceBranch(this.sourceBranch);
this.setVulnerabilityFeedbackPath(this.vulnerabilityFeedbackPath);
this.setVulnerabilityFeedbackHelpPath(this.vulnerabilityFeedbackHelpPath);
this.setCreateVulnerabilityFeedbackIssuePath(this.createVulnerabilityFeedbackIssuePath);
this.setCreateVulnerabilityFeedbackMergeRequestPath(
this.createVulnerabilityFeedbackMergeRequestPath,
);
this.setCreateVulnerabilityFeedbackDismissalPath(this.createVulnerabilityFeedbackDismissalPath);
this.setPipelineId(this.pipelineId);
this.setCanCreateIssuePermission(this.canCreateIssue);
this.setCanCreateFeedbackPermission(this.canCreateFeedback);
if (this.sastHeadPath) {
this.setSastHeadPath(this.sastHeadPath);
this.fetchSastReports().catch(() =>
createFlash(s__('ciReport|There was an error loading SAST report')),
);
}
if (this.dependencyScanningHeadPath) {
this.setDependencyScanningHeadPath(this.dependencyScanningHeadPath);
this.fetchDependencyScanningReports().catch(() =>
createFlash(s__('ciReport|There was an error loading dependency scanning report')),
);
}
if (this.sastContainerHeadPath) {
this.setSastContainerHeadPath(this.sastContainerHeadPath);
this.fetchSastContainerReports().catch(() =>
createFlash(s__('ciReport|There was an error loading container scanning report')),
);
}
if (this.dastHeadPath) {
this.setDastHeadPath(this.dastHeadPath);
this.fetchDastReports().catch(() =>
createFlash(s__('ciReport|There was an error loading DAST report')),
);
}
},
methods: {
...mapActions([
'setHeadBlobPath',
'setSourceBranch',
'setDependencyScanningHeadPath',
'setSastContainerHeadPath',
'setDastHeadPath',
'fetchDependencyScanningReports',
'fetchSastContainerReports',
'fetchDastReports',
'setVulnerabilityFeedbackPath',
'setVulnerabilityFeedbackHelpPath',
'setCreateVulnerabilityFeedbackIssuePath',
'setCreateVulnerabilityFeedbackMergeRequestPath',
'setCreateVulnerabilityFeedbackDismissalPath',
'setPipelineId',
'setCanCreateIssuePermission',
'setCanCreateFeedbackPermission',
'dismissVulnerability',
'revertDismissVulnerability',
'createNewIssue',
'createMergeRequest',
'openDismissalCommentBox',
'closeDismissalCommentBox',
'downloadPatch',
'addDismissalComment',
'deleteDismissalComment',
'showDismissalDeleteButtons',
'hideDismissalDeleteButtons',
]),
...mapActions('sast', {
setSastHeadPath: 'setHeadPath',
fetchSastReports: 'fetchReports',
}),
summaryTextBuilder(reportType, issuesCount = 0) {
if (issuesCount === 0) {
return sprintf(s__('ciReport|%{reportType} detected no vulnerabilities'), {
reportType,
});
}
return sprintf(
n__(
'ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability',
'ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities',
issuesCount,
),
{ reportType, vulnerabilityCount: issuesCount },
);
},
},
};
</script>
<template>
<div>
<report-section
v-if="sastHeadPath"
:always-open="alwaysOpen"
:component="$options.componentNames.SastIssueBody"
:status="checkReportStatus(sast.isLoading, sast.hasError)"
:loading-text="$options.messages.SAST_IS_LOADING"
:error-text="$options.messages.SAST_HAS_ERROR"
:success-text="sastText"
:unresolved-issues="sast.newIssues"
:has-issues="sast.newIssues.length > 0"
:popover-options="sastPopover"
class="js-sast-widget split-report-section"
/>
<report-section
v-if="dependencyScanningHeadPath"
:always-open="alwaysOpen"
:component="$options.componentNames.SastIssueBody"
:status="checkReportStatus(dependencyScanning.isLoading, dependencyScanning.hasError)"
:loading-text="$options.messages.DEPENDENCY_SCANNING_IS_LOADING"
:error-text="$options.messages.DEPENDENCY_SCANNING_HAS_ERROR"
:success-text="dependencyScanningText"
:unresolved-issues="dependencyScanning.newIssues"
:has-issues="dependencyScanning.newIssues.length > 0"
:popover-options="dependencyScanningPopover"
class="js-dss-widget split-report-section"
data-qa-selector="dependency_scanning_report"
/>
<report-section
v-if="sastContainerHeadPath"
:always-open="alwaysOpen"
:component="$options.componentNames.SastContainerIssueBody"
:status="checkReportStatus(sastContainer.isLoading, sastContainer.hasError)"
:loading-text="$options.messages.CONTAINER_SCANNING_IS_LOADING"
:error-text="$options.messages.CONTAINER_SCANNING_HAS_ERROR"
:success-text="sastContainerText"
:unresolved-issues="sastContainer.newIssues"
:has-issues="sastContainer.newIssues.length > 0"
:popover-options="sastContainerPopover"
class="js-dependency-scanning-widget split-report-section"
data-qa-selector="container_scanning_report"
/>
<report-section
v-if="dastHeadPath"
:always-open="alwaysOpen"
:component="$options.componentNames.DastIssueBody"
:status="checkReportStatus(dast.isLoading, dast.hasError)"
:loading-text="$options.messages.DAST_IS_LOADING"
:error-text="$options.messages.DAST_HAS_ERROR"
:success-text="dastText"
:unresolved-issues="dast.newIssues"
:has-issues="dast.newIssues.length > 0"
:popover-options="dastPopover"
class="js-dast-widget split-report-section"
/>
<issue-modal
:modal="modal"
:vulnerability-feedback-help-path="vulnerabilityFeedbackHelpPath"
:can-create-issue="canCreateIssue"
:can-create-merge-request="canCreateMergeRequest"
:can-dismiss-vulnerability="canDismissVulnerability"
@closeDismissalCommentBox="closeDismissalCommentBox()"
@createNewIssue="createNewIssue"
@createMergeRequest="createMergeRequest"
@dismissVulnerability="dismissVulnerability"
@openDismissalCommentBox="openDismissalCommentBox()"
@revertDismissVulnerability="revertDismissVulnerability"
@downloadPatch="downloadPatch"
@addDismissalComment="addDismissalComment({ comment: $event })"
@editVulnerabilityDismissalComment="openDismissalCommentBox()"
@deleteDismissalComment="deleteDismissalComment"
@showDismissalDeleteButtons="showDismissalDeleteButtons"
@hideDismissalDeleteButtons="hideDismissalDeleteButtons"
/>
</div>
</template>
......@@ -12,7 +12,6 @@ module EE
# because the user can freely navigate between them *without*
# triggering a page load.
before_action only: [:show, :builds, :failures, :security, :licenses] do
push_frontend_feature_flag(:pipeline_report_api, default_enabled: true)
push_frontend_feature_flag(:parsed_license_report, default_enabled: true)
end
end
......
- pipeline = local_assigns.fetch(:pipeline)
- project = local_assigns.fetch(:project)
- sast_endpoint = pipeline.downloadable_path_for_report_type(:sast)
- dependency_scanning_endpoint = pipeline.downloadable_path_for_report_type(:dependency_scanning)
- dast_endpoint = pipeline.downloadable_path_for_report_type(:dast)
- sast_container_endpoint = pipeline.downloadable_path_for_report_type(:container_scanning)
- blob_path = project_blob_path(project, pipeline.sha)
- license_management_settings_path = can?(current_user, :admin_software_license_policy, project) ? license_management_settings_path(project) : nil
- licenses_api_path = licenses_project_pipeline_path(project, pipeline) if project.feature_available?(:license_management)
- vulnerabilities_endpoint_path = expose_path(api_v4_projects_vulnerability_findings_path(id: project.id, params: { pipeline_id: pipeline.id, scope: 'dismissed' }))
- if pipeline.expose_security_dashboard?
#js-tab-security.build-security.tab-pane
- if Feature.enabled?(:pipeline_report_api, default_enabled: true)
#js-security-report-app{ data: { dashboard_documentation: help_page_path('user/application_security/security_dashboard/index'),
empty_state_svg_path: image_path('illustrations/security-dashboard-empty-state.svg'),
pipeline_id: pipeline.id,
project_id: project.id,
vulnerabilities_endpoint: vulnerabilities_endpoint_path,
vulnerability_feedback_help_path: help_page_path('user/application_security/index') } }
- else
#js-security-report-app{ data: { head_blob_path: blob_path,
sast_head_path: sast_endpoint,
dependency_scanning_head_path: dependency_scanning_endpoint,
dast_head_path: dast_endpoint,
sast_container_head_path: sast_container_endpoint,
pipeline_id: pipeline.id,
source_branch: pipeline.ref,
vulnerability_feedback_path: project_vulnerability_feedback_index_path(project),
vulnerability_feedback_help_path: help_page_path('user/application_security/index'),
sast_help_path: help_page_path('user/application_security/sast/index'),
dependency_scanning_help_path: help_page_path('user/application_security/dependency_scanning/index'),
dast_help_path: help_page_path('user/application_security/dast/index'),
sast_container_help_path: help_page_path('user/application_security/container_scanning/index'),
create_vulnerability_feedback_issue_path: create_vulnerability_feedback_issue_path(project),
create_vulnerability_feedback_merge_request_path: create_vulnerability_feedback_merge_request_path(project),
create_vulnerability_feedback_dismissal_path: create_vulnerability_feedback_dismissal_path(project) } }
#js-security-report-app{ data: { dashboard_documentation: help_page_path('user/application_security/security_dashboard/index'),
empty_state_svg_path: image_path('illustrations/security-dashboard-empty-state.svg'),
pipeline_id: pipeline.id,
project_id: project.id,
vulnerabilities_endpoint: vulnerabilities_endpoint_path,
vulnerability_feedback_help_path: help_page_path('user/application_security/index') } }
- if pipeline.expose_license_scanning_data?
#js-tab-licenses.tab-pane
......
---
title: Remove old pipeline security report view in favor of the Security Dashboard
merge_request: 22152
author:
type: removed
......@@ -101,37 +101,16 @@ describe 'Pipeline', :js do
context 'with a sast artifact' do
before do
create(:ee_ci_build, :sast, pipeline: pipeline)
visit security_project_pipeline_path(project, pipeline)
end
context 'when feature flag is enabled' do
before do
visit security_project_pipeline_path(project, pipeline)
end
it 'shows jobs tab pane as active' do
expect(page).to have_content('Security')
expect(page).to have_css('#js-tab-security')
end
it 'shows security dashboard' do
expect(page).to have_css('.js-security-dashboard-table')
end
it 'shows jobs tab pane as active' do
expect(page).to have_content('Security')
expect(page).to have_css('#js-tab-security')
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(pipeline_report_api: false)
visit security_project_pipeline_path(project, pipeline)
end
it 'shows jobs tab pane as active' do
expect(page).to have_content('Security')
expect(page).to have_css('#js-tab-security')
end
it 'shows security report section' do
expect(page).to have_content('SAST is loading')
end
it 'shows security dashboard' do
expect(page).to have_css('.js-security-dashboard-table')
end
end
......
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import component from 'ee/vue_shared/security_reports/split_security_reports_app.vue';
import createStore from 'ee/vue_shared/security_reports/store';
import state from 'ee/vue_shared/security_reports/store/state';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
import { sastIssues, dast, dockerReport } from './mock_data';
describe('Split security reports app', () => {
const Component = Vue.extend(component);
let vm;
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
vm.$store.replaceState(state());
vm.$destroy();
mock.restore();
});
describe('while loading', () => {
beforeEach(() => {
mock.onGet('sast_head.json').reply(200, sastIssues);
mock.onGet('dss_head.json').reply(200, sastIssues);
mock.onGet('dast_head.json').reply(200, dast);
mock.onGet('sast_container_head.json').reply(200, dockerReport);
mock.onGet('vulnerability_feedback_path.json').reply(200, []);
vm = mountComponentWithStore(Component, {
store: createStore(),
props: {
headBlobPath: 'path',
sastHeadPath: 'sast_head.json',
dependencyScanningHeadPath: 'dss_head.json',
dastHeadPath: 'dast_head.json',
sastContainerHeadPath: 'sast_container_head.json',
sastHelpPath: 'path',
dependencyScanningHelpPath: 'path',
vulnerabilityFeedbackPath: 'vulnerability_feedback_path.json',
vulnerabilityFeedbackHelpPath: 'path',
dastHelpPath: 'path',
sastContainerHelpPath: 'path',
pipelineId: 123,
canCreateIssue: true,
canCreateMergeRequest: true,
canDismissVulnerability: true,
},
});
});
it('renders loading summary text + spinner', done => {
expect(vm.$el.querySelector('.gl-spinner')).not.toBeNull();
expect(vm.$el.textContent).toContain('SAST is loading');
expect(vm.$el.textContent).toContain('Dependency scanning is loading');
expect(vm.$el.textContent).toContain('Container scanning is loading');
expect(vm.$el.textContent).toContain('DAST is loading');
setTimeout(() => {
done();
}, 0);
});
});
describe('with all reports', () => {
beforeEach(() => {
mock.onGet('sast_head.json').reply(200, sastIssues);
mock.onGet('dss_head.json').reply(200, sastIssues);
mock.onGet('dast_head.json').reply(200, dast);
mock.onGet('sast_container_head.json').reply(200, dockerReport);
mock.onGet('vulnerability_feedback_path.json').reply(200, []);
vm = mountComponentWithStore(Component, {
store: createStore(),
props: {
headBlobPath: 'path',
sastHeadPath: 'sast_head.json',
dependencyScanningHeadPath: 'dss_head.json',
dastHeadPath: 'dast_head.json',
sastContainerHeadPath: 'sast_container_head.json',
sastHelpPath: 'path',
dependencyScanningHelpPath: 'path',
vulnerabilityFeedbackPath: 'vulnerability_feedback_path.json',
vulnerabilityFeedbackHelpPath: 'path',
dastHelpPath: 'path',
sastContainerHelpPath: 'path',
pipelineId: 123,
canCreateIssue: true,
canCreateMergeRequest: true,
canDismissVulnerability: true,
},
});
});
it('renders reports', done => {
setTimeout(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.textContent).toContain('SAST detected 3 vulnerabilities');
expect(vm.$el.textContent).toContain('Dependency scanning detected 3 vulnerabilities');
// Renders container scanning result
expect(vm.$el.textContent).toContain('Container scanning detected 2 vulnerabilities');
// Renders DAST result
expect(vm.$el.textContent).toContain('DAST detected 2 vulnerabilities');
expect(vm.$el.textContent).not.toContain('for the source branch only');
done();
}, 0);
});
it('renders all reports collapsed by default', done => {
setTimeout(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.querySelector('.js-collapse-btn').textContent.trim()).toEqual('Expand');
const reports = vm.$el.querySelectorAll('.js-report-section-container');
reports.forEach(report => {
expect(report).toHaveCss({ display: 'none' });
});
done();
}, 0);
});
it('renders all reports expanded with the option always-open', done => {
vm.alwaysOpen = true;
setTimeout(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.querySelector('.js-collapse-btn')).toBeNull();
const reports = vm.$el.querySelectorAll('.js-report-section-container');
reports.forEach(report => {
expect(report).not.toHaveCss({ display: 'none' });
});
done();
}, 0);
});
});
describe('with error', () => {
beforeEach(() => {
mock.onGet('sast_head.json').reply(500);
mock.onGet('dss_head.json').reply(500);
mock.onGet('dast_head.json').reply(500);
mock.onGet('sast_container_head.json').reply(500);
mock.onGet('vulnerability_feedback_path.json').reply(500, []);
vm = mountComponentWithStore(Component, {
store: createStore(),
props: {
headBlobPath: 'path',
sastHeadPath: 'sast_head.json',
dependencyScanningHeadPath: 'dss_head.json',
dastHeadPath: 'dast_head.json',
sastContainerHeadPath: 'sast_container_head.json',
sastHelpPath: 'path',
dependencyScanningHelpPath: 'path',
vulnerabilityFeedbackPath: 'vulnerability_feedback_path.json',
vulnerabilityFeedbackHelpPath: 'path',
dastHelpPath: 'path',
sastContainerHelpPath: 'path',
pipelineId: 123,
canCreateIssue: true,
canCreateMergeRequest: true,
canDismissVulnerability: true,
},
});
});
it('renders error state', done => {
setTimeout(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.textContent).toContain('SAST: Loading resulted in an error');
expect(vm.$el.textContent).toContain('Dependency scanning: Loading resulted in an error');
expect(vm.$el.textContent).toContain('Container scanning: Loading resulted in an error');
expect(vm.$el.textContent).toContain('DAST: Loading resulted in an error');
done();
}, 0);
});
});
});
......@@ -21322,14 +21322,6 @@ msgstr ""
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
msgstr[0] ""
msgstr[1] ""
msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
msgid "ciReport|%{reportType} is loading"
msgstr ""
......@@ -21489,18 +21481,6 @@ msgstr ""
msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
msgstr ""
msgid "ciReport|There was an error loading DAST report"
msgstr ""
msgid "ciReport|There was an error loading SAST report"
msgstr ""
msgid "ciReport|There was an error loading container scanning report"
msgstr ""
msgid "ciReport|There was an error loading dependency scanning report"
msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment