SonarQube local and cloud with the same profile and gate¶
Context and Problem Statement¶
SonarQube is to run locally before the push (ADR 0038) and, in the public state, rate pull requests in SonarQube Cloud. Both sides must apply the same rules and the same gate, otherwise the cloud finds after the push what passed locally. Two gaps are known: the Community Build does not analyze Dart (https://docs.sonarsource.com/sonarqube-community-build/analyzing-source-code/languages/overview/, retrieved 2026-10-10) [verified], and the free cloud plan for private repositories allows no custom profiles and gates; the OSS plan for public repositories allows them (https://docs.sonarsource.com/sonarqube-cloud/administering-sonarcloud/managing-subscription/subscription-plans.md, retrieved 2026-10-10) [verified].
Decision Drivers¶
- The same rules and the same gate locally and in the cloud, checked by a machine.
- No outflow of private code to a service before switching to public.
- Dart coverage despite the missing analyzer in the Community Build.
- Profile changes reviewable in the repository.
Considered Options¶
- Both: local Community Build and SonarQube Cloud, profile and gate as files in the repository, applied and compared by a tool
- Only SonarQube Cloud
- Only a local Community Build
- No SonarQube; only language-specific linters
Decision Outcome¶
Chosen option: "Both, with files in the repository", because only this way the same rules provably apply locally and in the cloud.
- Profile "Bothy way" per language inherits from the built-in profile (
quality/sonar/profiles.json, parent profile "Sonar way") and additionally activates only the rules fromquality/sonar/quality-profile-<language>.xml. At the start these lists are empty: additional rules come one at a time with a reason in the pull request. - Gate "Bothy way" (
quality/sonar/quality-gate.json) with the four conditions of the built-in gate (no new findings, all new hotspots reviewed, coverage and duplication in new code). It uses only metrics that exist in both modes of SonarQube (https://docs.sonarsource.com/sonarqube-community-build/user-guide/code-metrics/metrics-definition, retrieved 2026-10-10) [verified]. tools/sonarqube/quality_sync.py applyapplies both,checkcompares. Equality locally and in the cloud follows from both passing against the same files.- Dart: locally
flutter analyzeandcustom_lintas a separate gate, in the cloud additionally SonarQube. - In the private state only the local Community Build; SonarQube Cloud is connected when switching to public (docs/quality/public-switch.md).
Consequences¶
- Good, because a rule change is a reviewable diff and both sides follow verifiably.
- Good, because no private code goes to the cloud.
- Bad, because the Community Build is released monthly and the cloud is updated continuously; the built-in parent profile can differ. What is compared is therefore the addition on top of the parent profile, not the full rule set.
- Bad, because built-in profile names can change: the vendor's public SonarQube server
lists "Sonar way core", "Sonar way extended" and "Sonar way
comprehensive" for Go (web API
api/qualityprofiles/search?language=goon https://next.sonarqube.com/sonarqube, retrieved 2026-10-10) [verified]. If the parent profile is missing,applyaborts with a message instead of silently choosing another. SonarQube Cloud has no "Sonar way" either: it offers "Sonar way core", "Sonar way extended" and "Sonar way comprehensive", the last one as the default, for every language ofprofiles.json(api/qualityprofiles/search?organization=<organization>on https://sonarcloud.io, retrieved 2026-10-13) [verified]. On the cloud the profiles therefore inherit fromcloud_parent("Sonar way comprehensive", the default the cloud analysis used before), so applying them removes no rule there; the parent profiles differ between local and cloud, the compared addition on top of them stays the same.
Confirmation¶
tools/sonarqube/tests/test_quality_sync.pychecks applying, idempotency, the repair of deviating conditions and the detection of additional rules against a test server.make sonar-config-checkagainst the local server and against SonarQube Cloud is part of the going-public checklist and of every SonarQube update.tools/docs/tests/test_config_values.pykeeps the thresholds of the gate equal to the named values in chapter 23.
Pros and Cons of the Options¶
Both, with files in the repository¶
- Good, because of verifiable equality and a local check before the push.
- Bad, because a local server with a database is operated (Docker-compatible runtime, memory).
Only SonarQube Cloud¶
- Good, because there is no local server.
- Bad, because findings come only after the push and private code leaves the premises.
- Bad, because custom profiles and gates are not possible in the private state.
Only a local Community Build¶
- Good, because everything stays local.
- Bad, because there is no Dart analysis and no rating of fork contributions.
No SonarQube¶
- Good, because there are fewer tools.
- Bad, because duplication, coverage of new code and security hotspots then have no shared gate.
More Information¶
Step by step: docs/quality/sonarqube-local.md.