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 {
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) {
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)
{!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}
+ />
</>
)}
</>
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';
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 () => {
mockQualityGateStatusConditionEnhanced({ metric: MetricKey.new_bugs }),
],
status: 'ERROR',
+ isCaycCompliant: false,
})}
{...props}
/>
<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={
{
},
],
"ignoredConditions": false,
- "isCaycCompliant": true,
+ "isCaycCompliant": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
]
}
/>
- <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={
{
},
],
"ignoredConditions": false,
- "isCaycCompliant": true,
+ "isCaycCompliant": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
</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={
{
},
],
"ignoredConditions": false,
- "isCaycCompliant": true,
+ "isCaycCompliant": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
]
}
/>
- <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={
{
},
],
"ignoredConditions": false,
- "isCaycCompliant": true,
+ "isCaycCompliant": false,
"key": "foo",
"name": "Foo",
"status": "ERROR",
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;
}
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,
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.
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.
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