From a743b6000c7d09f642726e0aad9913bd18603cec Mon Sep 17 00:00:00 2001 From: wtclaude Date: Wed, 22 Jul 2026 13:59:14 -0500 Subject: [PATCH] =?UTF-8?q?docs(android):=20record=20SonarQube=20coverage?= =?UTF-8?q?=20wiring=20and=20issue=20triage=20(=C2=A712.1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add §12.1 documenting the Android-app SonarQube setup: the coverage gate failed at 0% because the source-only scan received no JaCoCo report (a reporting gap, not a testing gap). Records the JaCoCo wiring (jacoco plugin + report task, sonar.coverage.jacoco.xmlReportPaths, pure-UI coverage exclusions, a Gradle step in sonarqube.yml) and the 2026-07-22 triage: 3 smells fixed in code, 12 marked Won't Fix (snake_case DTO fields that mirror the wire contract; idiomatic Compose/nav complexity). Pairs with RunicGateway/Android-app chore/sonar-coverage-and-cleanup. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr --- android/PLAN.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/android/PLAN.md b/android/PLAN.md index c7537d8..6a37123 100644 --- a/android/PLAN.md +++ b/android/PLAN.md @@ -995,6 +995,29 @@ repos use), on a bare `ubuntu:latest` container. signing identity stable from the first release (Play later requires consistency). - Semantic `versionName` + monotonic `versionCode`; tag releases. +### 12.1 Code quality — SonarQube (`Runic-Gateway-Android-app`) + +Analysis runs post-merge and non-blocking (`.gitea/workflows/sonarqube.yml`); the gate is +informational. The project is clean (0 bugs / 0 vulns / 0 hotspots, Maintainability **A**); the only +gate failure is **coverage = 0% on new code**, which is a *reporting* gap, not a testing gap — the +25-file JVM unit suite exists, but the source-only Sonar scan never received a JaCoCo report. + +**Coverage wiring (the fix):** +- Apply the `jacoco` plugin in `app/build.gradle.kts` + a `jacocoTestReport` task fed by + `testDebugUnitTest`, emitting XML. Exclude generated/DI/Compose scaffolding + (`**/*_Hilt*`, `**/*_Factory*`, `**/di/**`, `**/*ComposableSingletons*`, `R`/`BuildConfig`). +- `sonar-project.properties`: set `sonar.coverage.jacoco.xmlReportPaths` to the report, and + `sonar.coverage.exclusions` for pure-`@Composable` UI (JVM unit tests can't execute composable + bodies without Robolectric, so counting those lines would unfairly sink new-code coverage). +- `sonarqube.yml` must now run a real Gradle build before the scan (JDK 17 + Android SDK, mirroring + `pr-checks.yml`): `./gradlew testDebugUnitTest jacocoTestReport` → then the scan step. + +**Issue triage (2026-07-22):** of 15 code smells, **3 fixed in code** — remove an unused import +(`AdminContentScreen.kt`), remove an unused `page` param (`AdminSupportScreen.RespondDialog`), and +decompose `LoginViewModel` (cognitive complexity 20). The remaining **12 marked *Won't Fix*** via the +Sonar API with rationale: 5 snake_case DTO fields (intentionally mirror the JSON wire contract) and 7 +Compose/nav cognitive-complexity + hoisted-callback param-count smells (idiomatic for Jetpack Compose). + ## 13. Open questions (revisit as we go) **Decided (recorded here for context):** single shard per install (§3); native auth is -- 2.49.1