ADR-0140: SonarQube Cloud analyses every pull request
- Status: accepted
- Date: 2026-09-30
- Deciders: Mahdi Amirabdollahi
Context
Formatting, ESLint, ArchUnit, Spring Modulith and the tests catch a lot, but nothing tracked code smells, likely bugs and coverage over time. A one-off SonarQube Cloud scan of the Java found 1,158 open issues, including a transaction mismatch, a possible NPE and a swallowed interrupt. It never looked at the web code. Issues nobody watches pile up again, so the check has to run on every change and be able to block a merge.
Decision
We will analyse every pull request and every push to main with SonarQube Cloud from CI, and a failing quality gate fails ci-ok.
- CI's
sonarjob runs the SonarScanner for Maven (sonar:sonar, pinned inpluginManagement) withsonar.qualitygate.wait=true. It analysessrc/mainandweb/src, with the merged JaCoCo XML from thecoveragejob and the Vitest lcov from thefrontendjob. maindoes not re-test (ADR-0126), so its analysis reuses the coverage artifacts of the PR run the merge commit came from. That keeps the dashboard and README badges current.- Automatic Analysis is off in SonarQube Cloud; the project is analysed only from CI. The token is the
SONAR_TOKENrepository secret, so fork PRs, which get no secrets, skip the job. - The project uses SonarQube Cloud's default quality gate ("Sonar way").
- Each change resolves its own issues before its PR merges. An issue is fixed in code, or marked false positive in SonarQube Cloud with a comment that says why. A rule that conflicts with a recorded convention is scoped out in
pom.xml(sonar.issue.ignore.multicriteria, rule and path) and listed below with its reason.
Project-level scoping:
sonar.plsql.file.suffixes=.plsql: the Liquibase changesets are PostgreSQL. The PL/SQL analyser is Oracle's and reports Oracle rules against them (VARCHAR2, CHAR).
Consequences
- Smells, bugs and new-code coverage are visible on every PR and gate the merge.
- The
sonarjob adds a few minutes to PRs that touch backend or web code. - The quality gate's new-code coverage condition means new code needs tests to merge. Coverage (ADR-0128) stays informational in the build itself; the gate is where it now counts.
- The project depends on a hosted service. If it is down,
ci-okfails until it is back.
Alternatives considered
- Automatic Analysis. Rejected: it has no coverage and cannot gate
ci-ok. - SonarQube Server, self-hosted. Rejected: a server to run for a public project that SonarQube Cloud analyses for free.
- Error Prone / PMD / SpotBugs in the build. Rejected for now: several tools to configure and keep quiet, no web coverage, and no dashboard across PRs.