Add support for Security Hotspots that are provided by SonarQube and SonarCloud
This commit is contained in:
@@ -30,6 +30,7 @@ export interface FindingSummary {
|
||||
projectUrl: string;
|
||||
getIssuesUrl: SonarUrlProcessorFunc;
|
||||
getComponentMeasuresUrl: SonarUrlProcessorFunc;
|
||||
getSecurityHotspotsUrl: () => string;
|
||||
}
|
||||
|
||||
export const sonarQubeApiRef = createApiRef<SonarQubeApi>({
|
||||
|
||||
@@ -46,7 +46,7 @@ describe('SonarQubeClient', () => {
|
||||
server.use(
|
||||
rest.get(`${mockBaseUrl}/sonarqube/measures/search`, (req, res, ctx) => {
|
||||
expect(req.url.searchParams.toString()).toBe(
|
||||
'projectKeys=our-service&metricKeys=alert_status%2Cbugs%2Creliability_rating%2Cvulnerabilities%2Csecurity_rating%2Ccode_smells%2Csqale_rating%2Ccoverage%2Cduplicated_lines_density',
|
||||
'projectKeys=our-service&metricKeys=alert_status%2Cbugs%2Creliability_rating%2Cvulnerabilities%2Csecurity_rating%2Csecurity_hotspots_reviewed%2Csecurity_review_rating%2Ccode_smells%2Csqale_rating%2Ccoverage%2Cduplicated_lines_density',
|
||||
);
|
||||
return res(
|
||||
ctx.json({
|
||||
@@ -81,6 +81,16 @@ describe('SonarQubeClient', () => {
|
||||
value: '1.0',
|
||||
component: 'our-service',
|
||||
},
|
||||
{
|
||||
metric: 'security_hotspots_reviewed',
|
||||
value: '100',
|
||||
component: 'our-service',
|
||||
},
|
||||
{
|
||||
metric: 'security_review_rating',
|
||||
value: '1.0',
|
||||
component: 'our-service',
|
||||
},
|
||||
{
|
||||
metric: 'code_smells',
|
||||
value: '100',
|
||||
@@ -123,6 +133,8 @@ describe('SonarQubeClient', () => {
|
||||
reliability_rating: '3.0',
|
||||
vulnerabilities: '4',
|
||||
security_rating: '1.0',
|
||||
security_hotspots_reviewed: '100',
|
||||
security_review_rating: '1.0',
|
||||
code_smells: '100',
|
||||
sqale_rating: '2.0',
|
||||
coverage: '55.5',
|
||||
@@ -158,6 +170,8 @@ describe('SonarQubeClient', () => {
|
||||
reliability_rating: '3.0',
|
||||
vulnerabilities: '4',
|
||||
security_rating: '1.0',
|
||||
security_hotspots_reviewed: '100',
|
||||
security_review_rating: '1.0',
|
||||
code_smells: '100',
|
||||
sqale_rating: '2.0',
|
||||
coverage: '55.5',
|
||||
|
||||
@@ -63,6 +63,8 @@ export class SonarQubeClient implements SonarQubeApi {
|
||||
reliability_rating: undefined,
|
||||
vulnerabilities: undefined,
|
||||
security_rating: undefined,
|
||||
security_hotspots_reviewed: undefined,
|
||||
security_review_rating: undefined,
|
||||
code_smells: undefined,
|
||||
sqale_rating: undefined,
|
||||
coverage: undefined,
|
||||
@@ -92,10 +94,12 @@ export class SonarQubeClient implements SonarQubeApi {
|
||||
`${
|
||||
this.baseUrl
|
||||
}project/issues?id=${componentKey}&types=${identifier.toUpperCase()}&resolved=false`,
|
||||
getComponentMeasuresUrl: (identifier: string) =>
|
||||
getComponentMeasuresUrl: identifier =>
|
||||
`${
|
||||
this.baseUrl
|
||||
}component_measures?id=${componentKey}&metric=${identifier.toLowerCase()}&resolved=false&view=list`,
|
||||
getSecurityHotspotsUrl: () =>
|
||||
`${this.baseUrl}project/security_hotspots?id=${componentKey}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@ export type MetricKey =
|
||||
| 'code_smells'
|
||||
| 'sqale_rating'
|
||||
|
||||
// security hotspots
|
||||
| 'security_hotspots_reviewed'
|
||||
| 'security_review_rating'
|
||||
|
||||
// coverage
|
||||
| 'coverage'
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ const useStyles = makeStyles(theme => {
|
||||
return {
|
||||
root: {
|
||||
margin: theme.spacing(1, 0),
|
||||
minWidth: '140px',
|
||||
},
|
||||
upper: {
|
||||
display: 'flex',
|
||||
|
||||
@@ -26,6 +26,7 @@ import { Chip, Grid } from '@material-ui/core';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import BugReport from '@material-ui/icons/BugReport';
|
||||
import LockOpen from '@material-ui/icons/LockOpen';
|
||||
import Security from '@material-ui/icons/Security';
|
||||
import SentimentVeryDissatisfied from '@material-ui/icons/SentimentVeryDissatisfied';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
@@ -205,6 +206,25 @@ export const SonarQubeCard = ({
|
||||
leftSlot={<Value value={value.metrics.code_smells} />}
|
||||
rightSlot={<Rating rating={value.metrics.sqale_rating} />}
|
||||
/>
|
||||
{value.metrics.security_review_rating && (
|
||||
<RatingCard
|
||||
titleIcon={<Security />}
|
||||
title="Hotspots Reviewed"
|
||||
link={value.getSecurityHotspotsUrl()}
|
||||
leftSlot={
|
||||
<Value
|
||||
value={
|
||||
value.metrics.security_hotspots_reviewed
|
||||
? `${value.metrics.security_hotspots_reviewed}%`
|
||||
: '—'
|
||||
}
|
||||
/>
|
||||
}
|
||||
rightSlot={
|
||||
<Rating rating={value.metrics.security_review_rating} />
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<div style={{ width: '100%' }} />
|
||||
<RatingCard
|
||||
link={value.getComponentMeasuresUrl('COVERAGE')}
|
||||
|
||||
Reference in New Issue
Block a user