diff options
author | Jeremy Davis <jeremy.davis@sonarsource.com> | 2023-01-10 14:35:17 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-01-12 20:02:51 +0000 |
commit | 10e6b8ee65ecc77738bfab13fd3be135e8e4ab85 (patch) | |
tree | 1fddd0a11d4a19010296a1562f9de6c0b88156d5 /server/sonar-web/src/main/js | |
parent | 118a3ed166799831e097748f2ce8e113298ad14e (diff) | |
download | sonarqube-10e6b8ee65ecc77738bfab13fd3be135e8e4ab85.tar.gz sonarqube-10e6b8ee65ecc77738bfab13fd3be135e8e4ab85.zip |
SONAR-17816 Warn user about non-cayc-compliant QG on the project overview
Diffstat (limited to 'server/sonar-web/src/main/js')
6 files changed, 66 insertions, 201 deletions
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanelSection.tsx b/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanelSection.tsx index d67432add26..ac9bc243030 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanelSection.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanelSection.tsx @@ -21,18 +21,16 @@ import * as React from 'react'; import { ButtonPlain } from '../../../components/controls/buttons'; import ChevronDownIcon from '../../../components/icons/ChevronDownIcon'; import ChevronRightIcon from '../../../components/icons/ChevronRightIcon'; -import { Alert } from '../../../components/ui/Alert'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { isDiffMetric } from '../../../helpers/measures'; import { BranchLike } from '../../../types/branch-like'; -import { ComponentQualifier } from '../../../types/component'; +import { isApplication } from '../../../types/component'; import { QualityGateStatus, QualityGateStatusConditionEnhanced, } from '../../../types/quality-gates'; import { Component } from '../../../types/types'; import QualityGateConditions from '../components/QualityGateConditions'; -import { CAYC_METRICS } from '../utils'; import CleanAsYouCodeWarning from './CleanAsYouCodeWarning'; export interface QualityGatePanelSectionProps { @@ -41,22 +39,21 @@ export interface QualityGatePanelSectionProps { qgStatus: QualityGateStatus; } -function splitConditions(conditions: QualityGateStatusConditionEnhanced[]) { - const caycConditions = []; +function splitConditions( + conditions: QualityGateStatusConditionEnhanced[] +): [QualityGateStatusConditionEnhanced[], QualityGateStatusConditionEnhanced[]] { const newCodeFailedConditions = []; const overallFailedConditions = []; for (const condition of conditions) { - if (CAYC_METRICS.includes(condition.metric)) { - caycConditions.push(condition); - } else if (isDiffMetric(condition.metric)) { + if (isDiffMetric(condition.metric)) { newCodeFailedConditions.push(condition); } else { overallFailedConditions.push(condition); } } - return [caycConditions, newCodeFailedConditions, overallFailedConditions]; + return [newCodeFailedConditions, overallFailedConditions]; } function displayConditions(conditions: number) { @@ -84,24 +81,15 @@ export function QualityGatePanelSection(props: QualityGatePanelSectionProps) { return null; } - const [caycConditions, newCodeFailedConditions, overallFailedConditions] = splitConditions( + const [newCodeFailedConditions, overallFailedConditions] = splitConditions( qgStatus.failedConditions ); - /* - * Show Clean as You Code if: - * - The QG is not CAYC-compliant - * - There are *any* failing conditions, we either show: - * - the cayc-specific failures - * - that cayc is passing and only other conditions are failing - */ - const showCayc = !qgStatus.isCaycCompliant || qgStatus.failedConditions.length > 0; + const showName = isApplication(component.qualifier); - const showSuccessfulCayc = caycConditions.length === 0 && qgStatus.isCaycCompliant; - - const hasOtherConditions = newCodeFailedConditions.length + overallFailedConditions.length > 0; - - const showName = component.qualifier === ComponentQualifier.Application; + const showSectionTitles = + !qgStatus.isCaycCompliant || + (overallFailedConditions.length > 0 && newCodeFailedConditions.length > 0); const toggleLabel = collapsed ? translateWithParameters('overview.quality_gate.show_project_conditions_x', qgStatus.name) @@ -131,69 +119,45 @@ export function QualityGatePanelSection(props: QualityGatePanelSectionProps) { {!collapsed && ( <> - {showCayc && ( - <> - <div className="display-flex-center overview-quality-gate-conditions-section-title"> - <h4 className="padded">{translate('quality_gates.conditions.cayc')}</h4> - {displayConditions(caycConditions.length)} - </div> - - {!qgStatus.isCaycCompliant && ( - <div className="big-padded bordered-bottom overview-quality-gate-conditions-list"> - <CleanAsYouCodeWarning /> - </div> - )} - - {showSuccessfulCayc && ( - <div className="big-padded bordered-bottom overview-quality-gate-conditions-list"> - <Alert variant="success" className="no-margin-bottom"> - {translate('overview.quality_gate.conditions.cayc.passed')} - </Alert> - </div> - )} + {!qgStatus.isCaycCompliant && ( + <div className="big-padded bordered-bottom overview-quality-gate-conditions-list"> + <CleanAsYouCodeWarning /> + </div> + )} - {caycConditions.length > 0 && ( - <QualityGateConditions - component={qgStatus} - branchLike={qgStatus.branchLike} - failedConditions={caycConditions} - /> + {newCodeFailedConditions.length > 0 && ( + <> + {showSectionTitles && ( + <h4 className="big-padded overview-quality-gate-conditions-section-title"> + {translateWithParameters( + 'quality_gates.conditions.new_code_x', + newCodeFailedConditions.length.toString() + )} + </h4> )} + <QualityGateConditions + component={qgStatus} + branchLike={qgStatus.branchLike} + failedConditions={newCodeFailedConditions} + /> </> )} - {hasOtherConditions && ( + {overallFailedConditions.length > 0 && ( <> - <div className="display-flex-center overview-quality-gate-conditions-section-title"> - <h4 className="padded">{translate('quality_gates.conditions.other_conditions')}</h4> - {displayConditions(newCodeFailedConditions.length + overallFailedConditions.length)} - </div> - - {newCodeFailedConditions.length > 0 && ( - <> - <h5 className="big-padded overview-quality-gate-conditions-subsection-title"> - {translate('quality_gates.conditions.new_code')} - </h5> - <QualityGateConditions - component={qgStatus} - branchLike={qgStatus.branchLike} - failedConditions={newCodeFailedConditions} - /> - </> - )} - - {overallFailedConditions.length > 0 && ( - <> - <h5 className="big-padded overview-quality-gate-conditions-subsection-title"> - {translate('quality_gates.conditions.overall_code')} - </h5> - <QualityGateConditions - component={qgStatus} - branchLike={qgStatus.branchLike} - failedConditions={overallFailedConditions} - /> - </> + {showSectionTitles && ( + <h4 className="big-padded overview-quality-gate-conditions-section-title"> + {translateWithParameters( + 'quality_gates.conditions.overall_code_x', + overallFailedConditions.length.toString() + )} + </h4> )} + <QualityGateConditions + component={qgStatus} + branchLike={qgStatus.branchLike} + failedConditions={overallFailedConditions} + /> </> )} </> diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-test.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-test.tsx index be4171f53e2..7b0e14a91f4 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-test.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-test.tsx @@ -34,7 +34,6 @@ import { mockQualityGateProjectStatus } from '../../../../helpers/mocks/quality- import { mockLoggedInUser, mockPeriod } from '../../../../helpers/testMocks'; import { renderComponent } from '../../../../helpers/testReactTestingUtils'; import { ComponentQualifier } from '../../../../types/component'; -import { MetricKey } from '../../../../types/metrics'; import { GraphType } from '../../../../types/project-activity'; import { Measure, Metric } from '../../../../types/types'; import BranchOverview, { BRANCH_OVERVIEW_ACTIVITY_GRAPH, NO_CI_DETECTED } from '../BranchOverview'; @@ -231,32 +230,6 @@ describe('project overview', () => { expect(await screen.findByText('metric.level.ERROR')).toBeInTheDocument(); expect(screen.getByText('overview.X_conditions_failed.2')).toBeInTheDocument(); - - expect( - screen.queryByText('overview.quality_gate.conditions.cayc.passed') - ).not.toBeInTheDocument(); - }); - - it('should show a failed QG with passing CAYC conditions', async () => { - jest.mocked(getQualityGateProjectStatus).mockResolvedValueOnce( - mockQualityGateProjectStatus({ - status: 'ERROR', - conditions: [ - { - actualValue: '12', - comparator: 'GT', - errorThreshold: '10', - metricKey: MetricKey.new_bugs, - periodIndex: 1, - status: 'ERROR', - }, - ], - }) - ); - renderBranchOverview(); - - expect(await screen.findByText('metric.level.ERROR')).toBeInTheDocument(); - expect(screen.getByText('overview.quality_gate.conditions.cayc.passed')).toBeInTheDocument(); }); it('should correctly show a project as empty', async () => { diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/QualityGatePanelSection-test.tsx b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/QualityGatePanelSection-test.tsx index 251e2730e72..6d151b5bff1 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/QualityGatePanelSection-test.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/QualityGatePanelSection-test.tsx @@ -55,6 +55,7 @@ function shallowRender(props: Partial<QualityGatePanelSectionProps> = {}) { mockQualityGateStatusConditionEnhanced({ metric: MetricKey.new_bugs }), ], status: 'ERROR', + isCaycCompliant: false, })} {...props} /> diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/QualityGatePanelSection-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/QualityGatePanelSection-test.tsx.snap index c49d5435550..dd37526a134 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/QualityGatePanelSection-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/QualityGatePanelSection-test.tsx.snap @@ -5,43 +5,15 @@ exports[`should render correctly 1`] = ` className="overview-quality-gate-conditions" > <div - className="display-flex-center overview-quality-gate-conditions-section-title" - > - <h4 - className="padded" - > - quality_gates.conditions.cayc - </h4> - </div> - <div className="big-padded bordered-bottom overview-quality-gate-conditions-list" > - <Alert - className="no-margin-bottom" - variant="success" - > - overview.quality_gate.conditions.cayc.passed - </Alert> - </div> - <div - className="display-flex-center overview-quality-gate-conditions-section-title" - > - <h4 - className="padded" - > - quality_gates.conditions.other_conditions - </h4> - <span - className="text-muted big-spacer-left" - > - overview.X_conditions_failed.2 - </span> + <CleanAsYouCodeWarning /> </div> - <h5 - className="big-padded overview-quality-gate-conditions-subsection-title" + <h4 + className="big-padded overview-quality-gate-conditions-section-title" > - quality_gates.conditions.new_code - </h5> + quality_gates.conditions.new_code_x.1 + </h4> <Memo(QualityGateConditions) component={ { @@ -94,7 +66,7 @@ exports[`should render correctly 1`] = ` }, ], "ignoredConditions": false, - "isCaycCompliant": true, + "isCaycCompliant": false, "key": "foo", "name": "Foo", "status": "ERROR", @@ -128,11 +100,11 @@ exports[`should render correctly 1`] = ` ] } /> - <h5 - className="big-padded overview-quality-gate-conditions-subsection-title" + <h4 + className="big-padded overview-quality-gate-conditions-section-title" > - quality_gates.conditions.overall_code - </h5> + quality_gates.conditions.overall_code_x.1 + </h4> <Memo(QualityGateConditions) component={ { @@ -185,7 +157,7 @@ exports[`should render correctly 1`] = ` }, ], "ignoredConditions": false, - "isCaycCompliant": true, + "isCaycCompliant": false, "key": "foo", "name": "Foo", "status": "ERROR", @@ -249,43 +221,15 @@ exports[`should render correctly 2`] = ` </div> </ButtonPlain> <div - className="display-flex-center overview-quality-gate-conditions-section-title" - > - <h4 - className="padded" - > - quality_gates.conditions.cayc - </h4> - </div> - <div className="big-padded bordered-bottom overview-quality-gate-conditions-list" > - <Alert - className="no-margin-bottom" - variant="success" - > - overview.quality_gate.conditions.cayc.passed - </Alert> - </div> - <div - className="display-flex-center overview-quality-gate-conditions-section-title" - > - <h4 - className="padded" - > - quality_gates.conditions.other_conditions - </h4> - <span - className="text-muted big-spacer-left" - > - overview.X_conditions_failed.2 - </span> + <CleanAsYouCodeWarning /> </div> - <h5 - className="big-padded overview-quality-gate-conditions-subsection-title" + <h4 + className="big-padded overview-quality-gate-conditions-section-title" > - quality_gates.conditions.new_code - </h5> + quality_gates.conditions.new_code_x.1 + </h4> <Memo(QualityGateConditions) component={ { @@ -338,7 +282,7 @@ exports[`should render correctly 2`] = ` }, ], "ignoredConditions": false, - "isCaycCompliant": true, + "isCaycCompliant": false, "key": "foo", "name": "Foo", "status": "ERROR", @@ -372,11 +316,11 @@ exports[`should render correctly 2`] = ` ] } /> - <h5 - className="big-padded overview-quality-gate-conditions-subsection-title" + <h4 + className="big-padded overview-quality-gate-conditions-section-title" > - quality_gates.conditions.overall_code - </h5> + quality_gates.conditions.overall_code_x.1 + </h4> <Memo(QualityGateConditions) component={ { @@ -429,7 +373,7 @@ exports[`should render correctly 2`] = ` }, ], "ignoredConditions": false, - "isCaycCompliant": true, + "isCaycCompliant": false, "key": "foo", "name": "Foo", "status": "ERROR", diff --git a/server/sonar-web/src/main/js/apps/overview/styles.css b/server/sonar-web/src/main/js/apps/overview/styles.css index 17327125a32..d06f711df32 100644 --- a/server/sonar-web/src/main/js/apps/overview/styles.css +++ b/server/sonar-web/src/main/js/apps/overview/styles.css @@ -131,13 +131,6 @@ background: var(--barBorderColor); } -.overview-quality-gate-conditions-subsection-title { - background-color: white; - border-bottom: 1px solid var(--barBorderColor); - margin: 0; - font-size: var(--baseFontSize); -} - .overview-quality-gate-conditions-list-collapse { margin: calc(2 * var(--gridSize)) 0; } diff --git a/server/sonar-web/src/main/js/apps/overview/utils.ts b/server/sonar-web/src/main/js/apps/overview/utils.ts index 332a91fefc6..e42daa22931 100644 --- a/server/sonar-web/src/main/js/apps/overview/utils.ts +++ b/server/sonar-web/src/main/js/apps/overview/utils.ts @@ -112,16 +112,6 @@ export enum MeasurementType { Duplication = 'DUPLICATION', } -/* - * Metrics part of Clean As You Code - */ -export const CAYC_METRICS: string[] = [ - MetricKey.new_maintainability_rating, - MetricKey.new_reliability_rating, - MetricKey.new_security_hotspots_reviewed, - MetricKey.new_security_rating, -]; - const MEASUREMENTS_MAP = { [MeasurementType.Coverage]: { metric: MetricKey.coverage, |