Qodana CI quality gate: full scan, baseline, or Cloud mode
Decide whether Qodana full scan, baseline, or Cloud mode should fail CI on new Java/Kotlin static-analysis issues, with config examples and verification steps.
25 Nov 2025, 08:52 UTC

Decision: fail CI on new issues, not existing ones
You are adding Qodana to a Java/Kotlin repository that already carries hundreds of inspection findings. If you configure the CI step to fail on the total issue count, every merge request blocks until someone cleans up legacy code. The practical takeaway is to gate on new issues only: record the current findings in a baseline file, then fail the build when Qodana reports new ERROR or WARNING issues beyond that baseline. Full scan fits greenfield projects; Qodana Cloud adds pull-request annotations and trend dashboards but requires a JetBrains Cloud account and outbound network access.
Constraints to set before choosing
- Language and runtime: Java or Kotlin, so the Qodana JVM linter image applies.
- CI environment: self-hosted runner or GitHub/GitLab CI with Docker available.
- Network: air-gapped runners must pre-pull and mirror the Qodana image; Cloud mode needs outbound access to JetBrains Cloud.
- Team expectation: do you need in-pull-request comments, or is a failing CI step enough?
Compare the three supported modes
| Mode | Fails CI on | Best for | External account | Main risk |
|---|---|---|---|---|
| Full scan | Total issues above threshold | New or small codebases | No | Blocks on legacy issues |
| Baseline | New issues only | Legacy repos adopting Qodana | No | Path changes invalidate baseline matching |
| Qodana Cloud | New issues plus pull-request annotations | Teams wanting trend dashboards | JetBrains Cloud | Requires network and account |
Trade-offs
Full scan
A full scan compares every file against the inspection profile and fails when total issues exceed the threshold. It is simple to configure but impractical on a legacy Java/Kotlin codebase with an existing backlog, because the gate stays red until the backlog is fixed.
Baseline
A baseline file records existing issues so subsequent runs report only new issues. This is the supported way to introduce Qodana on a legacy codebase without blocking on pre-existing findings. The gate can then target new ERROR and WARNING counts while ignoring informational severities such as TYPO and WEAK WARNING.
Qodana Cloud
Qodana Cloud adds pull-request annotations and trend dashboards on top of CLI results. It requires a JetBrains Cloud account and network access from CI. If your CI is air-gapped or you prefer self-hosted tooling, the CLI with a baseline is the more practical choice.
Implementation: baseline quality gate for Java/Kotlin
Create a qodana.yaml in the repository root. The exact schema varies by Qodana version, so verify the keys against your installed image before committing.
# Example structure; confirm keys for your Qodana version.
linter: jetbrains/qodana-jvm
baseline:
enabled: true
file: .qodana/baseline.json
include:
- ERROR
- WARNING
quality-gates:
new-issues:
threshold: 0
severities:
- ERROR
- WARNING
Run Qodana in Docker from the CI job or a local workstation. Required permissions: the user must be able to run Docker containers (docker group membership or equivalent).
docker run --rm \
-v '<project-root>:/data/project' \
-v qodana-cache:/data/.qodana \
'<qodana-image>:<tag>' \
--report-dir /data/project/qodana-report
Placeholders: replace <project-root> with the absolute path to the Java/Kotlin project, <qodana-image> with the Qodana JVM image, and <tag> with the pinned image tag. Expected checks: the container exits with code 0 when no new issues exceed the gate, and a non-zero exit code when new ERROR or WARNING issues appear. The qodana-report directory should contain HTML, SARIF, or JSON output depending on the report format requested.
Risks: Qodana Docker images are large, so the first run pulls several gigabytes. Air-gapped CI must pre-pull and mirror the correct image tag. Baseline matching is sensitive to path normalization; moving source directories or changing the Docker workdir can make every existing issue appear as new.
Validation: prove the gate blocks only new issues
- Commit
qodana.yamland generate the initial baseline, then commit.qodana/baseline.json. The CI step should pass because no new issues exist beyond the baseline. - Introduce one intentional new violation in a Java or Kotlin file, such as an unused import that the enabled profile flags.
- Re-run the Qodana step. The build should fail, and the report should list the intentional violation as a new issue while excluding pre-existing baseline issues.
- Revert the intentional violation and confirm the step passes again.
- To validate SARIF upload, point your CI SARIF step at
qodana-report/qodana.sarif.jsonand confirm the repository security tab displays the expected alerts.
Limitations
- Not all IntelliJ inspections are available in Qodana CLI, and some require the Ultimate edition or Cloud backend; check the bundled inspection profile before relying on a custom profile.
- Changing severity thresholds or adding inspections can suddenly fail CI. Introduce gates in warn-only mode first, if your version supports it, then tighten the threshold.
- Severity levels include ERROR, WARNING, TYPO, and WEAK WARNING; gates typically target ERROR and WARNING to avoid noise from informational inspections.
Check the result
Open the HTML report in qodana-report and compare the new-issues count against the gate threshold. Inspect qodana.sarif.json if you upload to a code-scanning dashboard. Run docker run --mirror '<qodana-image>:<tag>' --help to confirm the Qodana version and supported inspections before finalizing severity gates.
If the gate breaks CI
Committing qodana.yaml and the baseline changes repository state. To roll back, revert that commit and remove the baseline file, or switch the gate to warn-only mode while the team reduces the backlog. Then re-baseline after the intended issues are fixed.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.