sonarqube-maintainability-gate
SonarQube classifies issues across three software qualities - Reliability,
Maintainability, Security - and four Clean Code attributes
(Consistent, Intentional, Adaptable, Responsible) per the SonarSource
docs (see Issues introduction). qa-security-scanning's sonarqube-rules skill
covers the Security lens; this skill covers the Reliability +
Maintainability lens for production code.
When to use
- A pull request touches production code and you want
Bug/Code-Smell metrics scoped to the diff (not test files).
- Pre-merge Quality Gate enforcement on the Sonar Way default
(no new issues; new-code coverage ≥80%; new-code duplication ≤3% - per Sonar Way QG).
- Legacy codebase entering Sonar adoption - focus on new code only
to avoid baseline-debt theater.
Step 1 - Install scanner
| Stack | Scanner |
|---|
| Maven | sonar-maven-plugin (mvn sonar:sonar) |
| Gradle | org.sonarqube plugin (./gradlew sonar) |
| .NET | dotnet-sonarscanner |
| Anything else | sonar-scanner CLI |
See the SonarQube docs sitemap for per-build-tool installation.
Step 2 - Scope to production code
Add to sonar-project.properties:
sonar.projectKey=acme.platform
sonar.sources=src
sonar.tests=tests,src/**/*.test.ts
sonar.exclusions=**/*.generated.*,**/migrations/**,**/vendor/**
sonar.test.inclusions=**/*.test.ts,**/*.spec.ts,tests/**
sonar.coverage.exclusions=**/*.generated.*,**/main.ts
Why separate sonar.tests vs sonar.sources: test code has different
quality expectations (long names, deliberate duplication for clarity,
Arrange-Act-Assert patterns). Lumping them into one scope produces
noise. Test code is reviewed separately.
Step 3 - Run scan
# Local development scan against a SonarQube server
sonar-scanner \
-Dsonar.host.url=https://sonar.internal \
-Dsonar.token=$SONAR_TOKEN
# CI scan with PR analysis (branch + PR decoration)
sonar-scanner \
-Dsonar.pullrequest.key=$PR_NUMBER \
-Dsonar.pullrequest.branch=$PR_BRANCH \
-Dsonar.pullrequest.base=main
The scanner uploads to the configured server; results stream to the
project dashboard.
Step 4 - Read the dashboard
| Metric | What it means | Sonar Way default |
|---|
| New Bugs | Reliability issues introduced in PR | 0 |
| New Code Smells | Maintainability issues introduced in PR | 0 |
| New Coverage | % new lines covered by tests | ≥ 80% |
| New Duplication | % new lines duplicated | ≤ 3% |
| Maintainability Rating (new code) | A - E based on debt ratio | A |
| Reliability Rating (new code) | A - E based on bug density | A |
Per Sonar Way QG: any condition fail blocks merge.
Step 5 - Quality Gate as CI gate
# GitHub Actions
- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@v3
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: SonarQube Quality Gate Check
uses: SonarSource/sonarqube-quality-gate-action@v1
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
The quality-gate-action polls the server until the gate result lands
and fails the build if it's RED.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|
Scan whole repo without sonar.tests separation | Test conventions flagged as smells; team disables Sonar | Split sonar.sources / sonar.tests (Step 2) |
| Apply gate to overall code, not new code | Legacy debt blocks all PRs forever | Use new-code-period gate (Sonar Way default) |
Mix this with the sonarqube-rules security settings | Two skills mutating same sonar-project.properties | This skill owns Reliability+Maintainability; sonarqube-rules owns the Security profile |
| Lower gate to merge pre-existing failures | Gate becomes meaningless | Use "Wont Fix" / "Accepted" issue resolution + scope-exclusion comment instead |
| Run after merge only | No PR decoration; hard to review | Run on PR with sonar.pullrequest.* flags (Step 3) |
Limitations
- Sonar Way thresholds are tuned for greenfield + healthy codebases.
Brownfield rollout: keep gate but mark all pre-existing as "Accepted"
with re-review date + waiver template (
Reason: + Approved-by: +
Re-review-date: + expires:).
- Self-hosted SonarQube (Community) does not include MQR severity
granularity; SonarCloud + Enterprise do.
References