Setting Up SonarQube for Mobile App Code Quality Analysis
SonarQube is a static code analyzer that works with Swift, Kotlin, Java, TypeScript, and Dart. For mobile projects, this means: detection of potential NPEs before production, control of code duplication across modules, tracking code smells in Kotlin coroutines, enforcing coverage threshold before merging to main.
Setup for Android (Kotlin)
SonarQube plugin integrates into Gradle:
// build.gradle.kts (project level)
plugins {
id("org.sonarqube") version "4.4.1.3373"
}
sonar {
properties {
property("sonar.projectKey", "myapp-android")
property("sonar.host.url", System.getenv("SONAR_HOST_URL") ?: "http://sonarqube:9000")
property("sonar.token", System.getenv("SONAR_TOKEN") ?: "")
property("sonar.sources", "app/src/main/kotlin")
property("sonar.tests", "app/src/test/kotlin,app/src/androidTest/kotlin")
property("sonar.android.lint.report", "app/build/reports/lint-results-debug.xml")
property("sonar.coverage.jacoco.xmlReportPaths",
"app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml")
property("sonar.kotlin.detekt.reportPaths",
"app/build/reports/detekt/detekt.xml")
}
}
Run analysis in CI:
./gradlew \
lintDebug \
testDebugUnitTest \
jacocoTestReport \
detekt \
sonar \
--info
JaCoCo is configured separately for XML coverage report.
Setup for iOS (Swift)
SonarQube analyzes Swift via sonar-scanner CLI with sonar-swift plugin or built-in Swift analyzer (SonarQube 10+):
# sonar-project.properties
sonar.projectKey=myapp-ios
sonar.sources=MyApp/Sources
sonar.exclusions=**/*.generated.swift,Pods/**/*
sonar.swift.coverage.reportPaths=fastlane/test_output/coverage.xml
sonar.swift.swiftlint.reportPaths=fastlane/swiftlint-report.json
In CI:
# Generate coverage
xcodebuild test \
-scheme MyApp \
-destination 'platform=iOS Simulator,name=iPhone 15' \
-enableCodeCoverage YES
# Convert to SonarQube format
slather coverage \
--cobertura-xml \
--output-directory fastlane/test_output \
MyApp.xcodeproj
# Analyze
sonar-scanner \
-Dsonar.token=$SONAR_TOKEN \
-Dsonar.host.url=$SONAR_HOST_URL
Quality Gate in PR
Quality Gate — conditions that block merge if not met. Typical thresholds for mobile project:
| Metric | Condition |
|---|---|
| Coverage on new code | >= 70% |
| Duplications on new code | <= 5% |
| Maintainability Rating | A |
| Reliability Rating | A |
| Security Rating | A |
| Security Hotspots Reviewed | 100% |
GitHub Actions integration via sonarqube-quality-gate-action:
- name: SonarQube Quality Gate check
uses: sonarsource/[email protected]
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
If Quality Gate fails — CI falls, PR can't be merged.
SonarCloud vs Self-hosted SonarQube
SonarCloud — cloud version, no infrastructure, free for open source. Self-hosted SonarQube — needs a server (minimum 2GB RAM, recommended 4GB), PostgreSQL. Community Edition is free but doesn't support branch analysis (only main). Developer Edition — paid, but necessary for PR analysis and Quality Gate on feature branches.
Process
Deploy SonarQube (self-hosted or SonarCloud) → create project → configure Gradle plugin / sonar-project.properties → integrate coverage and lint reports → add CI step → configure Quality Gate → write documentation.
Timeline: 1–3 days. Cost is calculated individually.







