Quality gates, profiles and issues
The idea: judge new code
Legacy code is what it is. A quality gate that fails on old problems gets switched off within a week. Qualor’s default gate therefore looks only at new code, meaning the lines a change adds or modifies. It asks three questions:
- Did the change add any issue?
- Is the new code covered by tests?
- Is the new code duplicated?
The overall numbers stay visible in the UI, and you can add conditions on them too.
New code
New code is always “the lines changed between a baseline and the analysed revision”. The baseline depends on what is analysed:
| Analysis of | Baseline |
|---|---|
| a merge request / pull request | merge-base(revision, target branch) |
| another branch | merge-base(revision, reference branch), by default the main branch |
| the main branch | the project’s new-code definition, below |
New-code definitions for the main branch (newCodeDefinition of the project, set through the API):
| Definition | Baseline |
|---|---|
{ "type": "days", "value": 30 } (default) |
the oldest analysis of the last 30 days |
{ "type": "previous_version" } |
the latest analysis with another project.version, for example ${CI_COMMIT_TAG} |
{ "type": "analysis", "analysisId": "…" } |
a fixed analysis |
An issue is new when its line lies in new code. So a newly enabled rule that flags old lines does not suddenly fail merge requests.
The baseline comes from git, so CI jobs need the full history (GIT_DEPTH: 0, fetch-depth: 0).
If the baseline cannot be found, new-code conditions end in error, and Qualor fails the gate rather
than guess.
The built-in gate: “Qualor way”
| Condition | Fails when |
|---|---|
new_issues |
> 0 |
new_coverage |
< 80 % |
new_duplicated_lines_density |
> 3 % |
It is the default for every organisation, and it is read-only. To change it, Quality gates → copy,
edit the copy, and make it the default, or assign it to single projects (qualityGateId).
Rules of evaluation:
- On merge requests and branches, only
new_*conditions count. - Small changes: below 20 new lines, the coverage and duplication conditions on new code are ignored. So a 5-line fix is not blocked by a coverage percentage.
- A value that cannot be computed, such as coverage when no coverage report was imported, is shown as no value. It does not fail the gate.
- Changing a gate does not re-judge past analyses. Changing an issue’s status does re-judge the branch’s latest analysis at once.
Metrics you can use in conditions
| Group | Metrics (add new_ for the new-code version) |
|---|---|
| Issues | issues, blocker_issues, high_issues, medium_issues, low_issues, info_issues, security_issues, reliability_issues, maintainability_issues |
| Ratings (1 = A … 5 = E) | security_rating, reliability_rating (from the worst severity among open issues of that quality) |
| Coverage | coverage, line_coverage, branch_coverage, lines_to_cover, uncovered_lines, conditions_to_cover, uncovered_conditions |
| Duplication | duplicated_lines, duplicated_blocks, duplicated_lines_density |
| Size and complexity (overall only) | files, lines, ncloc, comment_lines, functions, classes, statements, complexity, cognitive_complexity, accepted_issues, false_positive_issues |
| New-code size | new_lines |
A condition is metric, gt or lt, and a threshold, for example new_security_rating gt 1. A gate
has at most one condition per metric.
Common additions:
new_security_issues gt 0: no new vulnerabilities, secrets or vulnerable dependencies, even when you relaxnew_issues.new_blocker_issues gt 0andnew_high_issues gt 0instead ofnew_issues gt 0, for a softer start on a noisy codebase.security_rating gt 3on the main branch: an overall floor.
Quality profiles: which rules count
A quality profile decides which analyzer rules become issues, and at which severity. There is one
profile per language (typescript, javascript, java, csharp) plus * for everything else:
secrets, dependencies, OpenGrep, external SARIF, and files without a language. The built-in profiles
are called “Qualor way”.
- Quality profiles → copy a built-in profile, then turn rules on or off, override a severity, and make the copy the default.
- A profile may inherit from a parent of the same language (up to 3 levels), and changes only the rules it names.
- Unknown rules, meaning rules a profile does not mention, follow the profile’s
unknownRulessetting:activate(the default) orignore. Withactivate, a new ESLint plugin rule shows up without anyone editing the profile. Findings the profile drops are counted in the analysis warnings. - A profile change applies from the next analysis.
The analyzers’ own configuration still decides what runs: your ESLint config, PMD ruleset,
.editorconfig, .gitleaks.toml. The profile filters and re-grades what the analyzers report.
Qualor keeps the team’s configuration in the repository, where reviewers see it.
Rules lists every rule the organisation has met, with its engine, language, quality and default severity.
Severities and qualities
| Severity | Meaning |
|---|---|
| blocker | must fix before merging: a real vulnerability, a leaked secret, a certain crash |
| high | very likely a bug or a security problem |
| medium | a probable problem, or a significant maintainability issue |
| low | a minor issue |
| info | information only |
Each rule also has a quality: security, reliability or maintainability.
Issue statuses
| Status | Set by | Meaning |
|---|---|---|
| open | system / user | an active problem |
| resolved | user | “fixed”. If the next analysis still finds it, it reopens |
| won’t fix | user, comment required | accepted as is. It stays so across analyses |
| false positive | user, comment required | the analyzer is wrong. It stays so across analyses |
| closed | system | no longer detected. If it comes back within 30 days, its earlier won’t fix or false positive is restored |
Won’t fix and false positive issues do not count in the gate. Changing a status re-evaluates the branch’s latest gate result and updates the merge request comment, the commit status or the check run, without a new scan. Every change is recorded in the issue’s changelog.
Issues keep their identity when code moves. The fingerprint is the rule, the path and the surrounding code, and it tolerates line shifts. When two analyzers report the same finding, only one issue is shown.
Merge requests and branches inherit the statuses of the target branch. A false positive marked on
main stays a false positive in every merge request.