Commit 081f573c authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch '343476-track-number-of-security-findings' into 'master'

Track security report findings

See merge request gitlab-org/gitlab!73649
parents 530cfeed a7305e64
......@@ -18,6 +18,7 @@ export const fetchDiff = ({ state, rootState, dispatch }) => {
return fetchDiffData(rootState, state.paths.diffEndpoint, REPORT_TYPE_SAST)
.then((data) => {
dispatch('receiveDiffSuccess', data);
return data;
})
.catch(() => {
dispatch('receiveDiffError');
......
......@@ -18,6 +18,7 @@ export const fetchDiff = ({ state, rootState, dispatch }) => {
return fetchDiffData(rootState, state.paths.diffEndpoint, REPORT_TYPE_SECRET_DETECTION)
.then((data) => {
dispatch('receiveDiffSuccess', data);
return data;
})
.catch(() => {
dispatch('receiveDiffError');
......
......@@ -394,38 +394,38 @@ export default {
if (this.sastComparisonPath && this.hasSastReports) {
this.setSastDiffEndpoint(this.sastComparisonPath);
this.fetchSastDiff();
this.fetchSecurityReport(this.fetchSastDiff, 'sast');
}
if (this.containerScanningComparisonPath && this.hasContainerScanningReports) {
this.setContainerScanningDiffEndpoint(this.containerScanningComparisonPath);
this.fetchContainerScanningDiff();
this.fetchSecurityReport(this.fetchContainerScanningDiff, 'container_scanning');
}
if (this.dastComparisonPath && this.hasDastReports) {
this.setDastDiffEndpoint(this.dastComparisonPath);
this.fetchDastDiff();
this.fetchSecurityReport(this.fetchDastDiff, 'dast');
}
if (this.dependencyScanningComparisonPath && this.hasDependencyScanningReports) {
this.setDependencyScanningDiffEndpoint(this.dependencyScanningComparisonPath);
this.fetchDependencyScanningDiff();
this.fetchSecurityReport(this.fetchDependencyScanningDiff, 'dependency_scanning');
}
if (this.secretDetectionComparisonPath && this.hasSecretDetectionReports) {
this.setSecretDetectionDiffEndpoint(this.secretDetectionComparisonPath);
this.fetchSecretDetectionDiff();
this.fetchSecurityReport(this.fetchSecretDetectionDiff, 'secret_detection');
}
if (this.coverageFuzzingComparisonPath && this.hasCoverageFuzzingReports) {
this.setCoverageFuzzingDiffEndpoint(this.coverageFuzzingComparisonPath);
this.fetchCoverageFuzzingDiff();
this.fetchSecurityReport(this.fetchCoverageFuzzingDiff, 'coverage_fuzzing');
this.fetchPipelineJobs();
}
if (this.apiFuzzingComparisonPath && this.hasApiFuzzingReports) {
this.setApiFuzzingDiffEndpoint(this.apiFuzzingComparisonPath);
this.fetchApiFuzzingDiff();
this.fetchSecurityReport(this.fetchApiFuzzingDiff, 'api_fuzzing');
}
},
methods: {
......@@ -475,6 +475,24 @@ export default {
hasIssuesForReportType(reportType) {
return Boolean(this[reportType]?.newIssues.length || this[reportType]?.resolvedIssues.length);
},
async fetchSecurityReport(fetchFn, toolName) {
try {
const reports = await fetchFn();
const category = 'Vulnerability_Management';
const eventNameFixed = `mr_widget_findings_counts_${toolName}_fixed`;
const eventNameAdded = `mr_widget_findings_counts_${toolName}_added`;
Tracking.event(category, eventNameFixed, {
value: reports?.diff?.fixed?.length || 0,
});
Tracking.event(category, eventNameAdded, {
value: reports?.diff?.added?.length || 0,
});
} catch {
// Do nothing, we dispatch an error message in the action
}
},
},
summarySlots: ['success', 'error', 'loading'],
reportTypes: {
......
......@@ -67,6 +67,7 @@ export const fetchContainerScanningDiff = ({ state, dispatch }) => {
return fetchDiffData(state, state.containerScanning.paths.diffEndpoint, 'container_scanning')
.then((data) => {
dispatch('receiveContainerScanningDiffSuccess', data);
return data;
})
.catch(() => {
dispatch('receiveContainerScanningDiffError');
......@@ -96,6 +97,7 @@ export const fetchDastDiff = ({ state, dispatch }) => {
return fetchDiffData(state, state.dast.paths.diffEndpoint, 'dast')
.then((data) => {
dispatch('receiveDastDiffSuccess', data);
return data;
})
.catch(() => {
dispatch('receiveDastDiffError');
......@@ -124,6 +126,7 @@ export const fetchDependencyScanningDiff = ({ state, dispatch }) => {
return fetchDiffData(state, state.dependencyScanning.paths.diffEndpoint, 'dependency_scanning')
.then((data) => {
dispatch('receiveDependencyScanningDiffSuccess', data);
return data;
})
.catch(() => {
dispatch('receiveDependencyScanningDiffError');
......@@ -160,10 +163,13 @@ export const fetchCoverageFuzzingDiff = ({ state, dispatch }) => {
}),
])
.then((values) => {
dispatch('receiveCoverageFuzzingDiffSuccess', {
const data = {
diff: values[0].data,
enrichData: values[1].data,
});
};
dispatch('receiveCoverageFuzzingDiffSuccess', data);
return data;
})
.catch(() => {
dispatch('receiveCoverageFuzzingDiffError');
......
......@@ -17,6 +17,7 @@ export const fetchDiff = ({ state, rootState, dispatch }) => {
return fetchDiffData(rootState, state.paths.diffEndpoint, 'api_fuzzing')
.then((data) => {
dispatch('receiveDiffSuccess', data);
return data;
})
.catch(() => {
dispatch('receiveDiffError');
......
......@@ -274,6 +274,9 @@ describe('Grouped security reports app', () => {
});
describe('with successful responses', () => {
let trackingSpy;
const { category } = trackMrSecurityReportDetails;
beforeEach(() => {
mock.onGet(CONTAINER_SCANNING_DIFF_ENDPOINT).reply(200, containerScanningDiffSuccessMock);
mock.onGet(DEPENDENCY_SCANNING_DIFF_ENDPOINT).reply(200, dependencyScanningDiffSuccessMock);
......@@ -284,6 +287,7 @@ describe('Grouped security reports app', () => {
mock.onGet(API_FUZZING_DIFF_ENDPOINT).reply(200, apiFuzzingDiffSuccessMock);
createWrapper(allReportProps);
trackingSpy = mockTracking(category, wrapper.element, jest.spyOn);
return Promise.all([
waitForMutation(wrapper.vm.$store, `sast/${sastTypes.RECEIVE_DIFF_SUCCESS}`),
......@@ -299,6 +303,31 @@ describe('Grouped security reports app', () => {
]);
});
afterEach(() => {
unmockTracking();
});
const eventName = (toolName, eventType) =>
`mr_widget_findings_counts_${toolName}_${eventType}`;
it.each`
toolName | report
${'coverage_fuzzing'} | ${coverageFuzzingDiffSuccessMock}
${'sast'} | ${sastDiffSuccessMock}
${'container_scanning'} | ${containerScanningDiffSuccessMock}
${'dast'} | ${dastDiffSuccessMock}
${'dependency_scanning'} | ${dependencyScanningDiffSuccessMock}
${'secret_detection'} | ${secretDetectionDiffSuccessMock}
${'api_fuzzing'} | ${apiFuzzingDiffSuccessMock}
`('track reports for "$toolName', ({ toolName, report }) => {
expect(trackingSpy).toHaveBeenCalledWith(category, eventName(toolName, 'fixed'), {
value: report.fixed.length,
});
expect(trackingSpy).toHaveBeenCalledWith(category, eventName(toolName, 'added'), {
value: report.added.length,
});
});
it('renders reports', () => {
// It's not loading
expect(findSpinner().exists()).toBe(false);
......
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