Run SonarQube/SonarCloud against production code to surface Code Smells, Bugs, and Maintainability ratings - the maintainability lens rather than the security lens. Production-only scope via sonar.exclusions; test code is reviewed separately. Use when a team wants maintainability and technical-debt ratings gating PRs, or when an existing SonarQube project reports numbers nobody has tied to a quality gate.
71
89%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
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.
| 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.
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.tsWhy 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.
# 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=mainThe scanner uploads to the configured server; results stream to the project 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.
# 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-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) |
Reason: + Approved-by: +
Re-review-date: + expires:).