From 3728efb55ed2f47a27c31883408a62c1d41d3bfe Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Fri, 3 Jul 2026 09:27:12 -0500 Subject: [PATCH] chore(preflight): compile androidTest source set in the fast gate assembleDebug, testDebugUnitTest, and lintDebug never compile the androidTest source set, so a change that breaks it (e.g. an instrumented test calling a UI API that just changed signature) passed preflight locally yet only failed once CI ran. Add :app:compileDebugAndroidTestKotlin to the fast gate to catch that class of breakage before pushing, and update CLAUDE.md's summary of the gate to match. Co-Authored-By: Claude Opus 4.8 --- .claude/skills/preflight/SKILL.md | 8 +++++++- CLAUDE.md | 10 ++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.claude/skills/preflight/SKILL.md b/.claude/skills/preflight/SKILL.md index 6bd417a..71d580b 100644 --- a/.claude/skills/preflight/SKILL.md +++ b/.claude/skills/preflight/SKILL.md @@ -1,6 +1,6 @@ --- name: preflight -description: Run LibreMail's fast CI gate locally (assembleDebug + testDebugUnitTest + lintDebug + ktlintCheck + detekt) before pushing or opening a PR. Mirrors the merge gate; does NOT run emulator E2E. Use before treating a change as done. +description: Run LibreMail's fast CI gate locally (assembleDebug + testDebugUnitTest + compileDebugAndroidTestKotlin + lintDebug + ktlintCheck + detekt) before pushing or opening a PR. Mirrors the merge gate; does NOT run emulator E2E. Use before treating a change as done. --- # /preflight @@ -21,10 +21,16 @@ Run these, stopping at the first failure: ```bash ./gradlew :app:assembleDebug ./gradlew :app:testDebugUnitTest +./gradlew :app:compileDebugAndroidTestKotlin ./gradlew :app:lintDebug ./gradlew :app:ktlintCheck :app:detekt ``` +`compileDebugAndroidTestKotlin` compiles the `androidTest` source set — the E2E/instrumented +tests — without needing an emulator. `assembleDebug`, `testDebugUnitTest`, and `lintDebug` never +compile that source set, so a change that breaks it (e.g. an instrumented test calling a UI API +that just changed signature) passes the rest of this gate locally yet fails CI. + `ktlintCheck` + `detekt` are exactly what CI's **Static analysis** job runs — they cover the `test`/`androidTest` source sets that `lintDebug` does not, so a style violation there fails the merge gate even when the build and lint are green. Add `--continue` to any command (e.g. diff --git a/CLAUDE.md b/CLAUDE.md index 8c0bcf7..18a3db8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,10 +26,12 @@ or via Gradle Managed Devices `./gradlew e2eGroupDebugAndroidTest` (whole matrix `app/build.gradle.kts` must stay in lockstep with the E2E matrix in `.github/workflows/ci.yml`. **Before treating a change as done**, run the fast CI gate: `assembleDebug` + -`testDebugUnitTest` + `lintDebug` + `ktlintCheck` + `detekt` (the `/preflight` skill does -this). `ktlintCheck`/`detekt` cover the `test`/`androidTest` source sets that `lintDebug` -skips, so they catch style violations that would otherwise fail CI's Static analysis gate. -Emulator E2E is left to CI unless asked. +`testDebugUnitTest` + `compileDebugAndroidTestKotlin` + `lintDebug` + `ktlintCheck` + +`detekt` (the `/preflight` skill does this). `compileDebugAndroidTestKotlin` compiles the +`androidTest` source set that the rest of the gate skips, catching E2E/instrumented-test +compile errors before they surface only in CI. `ktlintCheck`/`detekt` cover the +`test`/`androidTest` source sets that `lintDebug` skips, so they catch style violations that +would otherwise fail CI's Static analysis gate. Emulator E2E is left to CI unless asked. ## Build-config gotchas -- 2.47.3