Selaa lähdekoodia

SONAR-17816 Warn user about non-cayc-compliant QG on the project overview

tags/9.9.0.65466
Jeremy Davis 1 vuosi sitten
vanhempi
commit
10e6b8ee65

+ 43
- 79
server/sonar-web/src/main/js/apps/overview/branches/QualityGatePanelSection.tsx Näytä tiedosto

@@ -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}
/>
</>
)}
</>

+ 0
- 27
server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-test.tsx Näytä tiedosto

@@ -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 () => {

+ 1
- 0
server/sonar-web/src/main/js/apps/overview/branches/__tests__/QualityGatePanelSection-test.tsx Näytä tiedosto

@@ -55,6 +55,7 @@ function shallowRender(props: Partial<QualityGatePanelSectionProps> = {}) {
mockQualityGateStatusConditionEnhanced({ metric: MetricKey.new_bugs }),
],
status: 'ERROR',
isCaycCompliant: false,
})}
{...props}
/>

+ 22
- 78
server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/QualityGatePanelSection-test.tsx.snap Näytä tiedosto

@@ -4,44 +4,16 @@ exports[`should render correctly 1`] = `
<div
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",
@@ -248,44 +220,16 @@ exports[`should render correctly 2`] = `
</h3>
</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",

+ 0
- 7
server/sonar-web/src/main/js/apps/overview/styles.css Näytä tiedosto

@@ -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;
}

+ 0
- 10
server/sonar-web/src/main/js/apps/overview/utils.ts Näytä tiedosto

@@ -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,

+ 5
- 6
sonar-core/src/main/resources/org/sonar/l10n/core.properties Näytä tiedosto

@@ -1809,14 +1809,14 @@ quality_gates.condition_deleted=Successfully deleted condition
quality_gates.delete_condition.confirm.message=Are you sure you want to delete the "{0}" condition?
quality_gates.conditions.fails_when=Quality Gate fails when
quality_gates.conditions.metric=Metric
quality_gates.conditions.cayc=Clean as You Code
quality_gates.conditions.other_conditions=Other conditions
quality_gates.conditions.new_code=On New Code
quality_gates.conditions.new_code.long=Conditions on New Code
quality_gates.conditions.new_code.description=Conditions on New Code apply to all branches and to Pull Requests.
quality_gates.conditions.new_code_x={0} condition(s) failed on new code
quality_gates.conditions.overall_code=On Overall Code
quality_gates.conditions.overall_code.long=Conditions on Overall Code
quality_gates.conditions.overall_code.description=Conditions on Overall Code apply to branches only.
quality_gates.conditions.overall_code_x={0} condition(s) failed on overall code
quality_gates.conditions.operator=Operator
quality_gates.conditions.warning=Warning
quality_gates.conditions.warning.tooltip=Warning status is deprecated and will disappear with the next update of the Quality Gate.
@@ -1870,7 +1870,7 @@ quality_gates.cayc.lock_edit=Lock for editing
quality_gates.cayc.tooltip.ok.condition=This condition is compliant with Clean as You Code.
quality_gates.cayc.tooltip.weak.condition=This condition is too permissive. Increase its value to follow Clean as You Code.
quality_gates.cayc.tooltip.missing.condition=This condition is missing. Add it to follow Clean as You Code.
quality_gates.cayc.tooltip.weak.quality_gate=Some Clean as You Code conditions are missing or are too permissive.
quality_gates.cayc.tooltip.weak.quality_gate=This Quality Gate does not follow the Clean as You Code methodology.
quality_gates.cayc.badge.tooltip.learn_more=Learn more: Clean as You Code
quality_gates.cayc_condition.delete_warning=This condition is part of Clean as You Code. If you delete it you will not benefit from the power of Clean As You Code anymore.
quality_gates.cayc_condition.edit_warning=This condition is part of Clean as You Code. If you decrease its value you will not benefit from the power of Clean As You Code anymore.
@@ -3268,10 +3268,9 @@ overview.you_should_define_quality_gate=You should define a quality gate on this
overview.quality_gate.ignored_conditions=Some Quality Gate conditions on New Code were ignored because of the small number of New Lines
overview.quality_gate.ignored_conditions.tooltip=At the start of a new code period, if very few lines have been added or modified, it might be difficult to reach the desired level of code coverage or duplications. To prevent Quality Gate failure when there's little that can be done about it, Quality Gate conditions about duplications in new code and coverage on new code are ignored until the number of new lines is at least 20. An administrator can disable this in the general settings.
overview.quality_gate.conditions_on_new_code=Only conditions on new code that are defined in the Quality Gate are checked. See the {link} associated to the project for details.
overview.quality_gate.conditions.cayc.warning=Some Clean as You Code conditions are missing or are too permissive.
overview.quality_gate.conditions.cayc.warning=This Quality Gate does not comply with Clean as You Code
overview.quality_gate.conditions.cayc.details=Clean as You Code conditions ensure that only Clean Code passes the gate.
overview.quality_gate.conditions.cayc.link=What is Clean as You Code
overview.quality_gate.conditions.cayc.passed=All conditions passed
overview.quality_gate.conditions.cayc.link=Learn more: Clean as You Code
overview.quality_gate.show_project_conditions_x=Show failed conditions for project {0}
overview.quality_gate.hide_project_conditions_x=Hide failed conditions for project {0}
overview.quality_profiles=Quality Profiles used

Loading…
Peruuta
Tallenna