feat(search): Unicode-aware case-insensitive search via casefold columns #234
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: preflight
|
||||
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.
|
||||
description: Run LibreMail's fast CI gate locally (assembleDebug + testDebugUnitTest + compileDebugAndroidTestKotlin + lintDebug + ktlintCheck + detekt) plus the latest-API-level emulator E2E before pushing or opening a PR. Mirrors the merge gate and runs the highest-API E2E via its Gradle Managed Device; the full multi-API matrix stays CI-only. Use before treating a change as done.
|
||||
---
|
||||
|
||||
# /preflight
|
||||
@@ -13,6 +13,12 @@ Run the same fast checks CI enforces on every PR, in order, and report the outco
|
||||
with a JDK/AGP version mismatch, check `java -version` / `JAVA_HOME` and point it at a 17–21
|
||||
JDK (e.g. Android Studio's bundled JBR) before retrying.
|
||||
- PowerShell: invoke the wrapper as `.\gradlew`. Git Bash / the Bash tool: `./gradlew`.
|
||||
- The final E2E step boots an emulator through a Gradle Managed Device, so the host needs
|
||||
hardware acceleration (WHPX on Windows, KVM on Linux, HVF on macOS). Gradle downloads the
|
||||
system image and boots/tears down the AVD itself — no manual emulator setup — but the first
|
||||
run is slow while the image downloads. If the host has no accelerated emulator and the
|
||||
managed device cannot boot, report the E2E step as not run rather than treating the gate as
|
||||
green.
|
||||
|
||||
## Steps
|
||||
|
||||
@@ -24,6 +30,7 @@ Run these, stopping at the first failure:
|
||||
./gradlew :app:compileDebugAndroidTestKotlin
|
||||
./gradlew :app:lintDebug
|
||||
./gradlew :app:ktlintCheck :app:detekt
|
||||
./gradlew :app:api36DebugAndroidTest # latest-API emulator E2E (highest level in the matrix)
|
||||
```
|
||||
|
||||
`compileDebugAndroidTestKotlin` compiles the `androidTest` source set — the E2E/instrumented
|
||||
@@ -37,13 +44,24 @@ merge gate even when the build and lint are green. Add `--continue` to any comma
|
||||
`:app:ktlintCheck :app:detekt --continue`) to collect every failure in one pass instead of
|
||||
stopping at the first.
|
||||
|
||||
`api36DebugAndroidTest` is last because it is the slowest: it runs the full instrumented/E2E
|
||||
suite on `api36` — the highest API level in the E2E matrix — via its Gradle Managed Device,
|
||||
which Gradle provisions, boots, and tears down automatically. This one latest-API level is the
|
||||
E2E that preflight runs locally and it must pass; CI fans the same suite out across the whole
|
||||
API matrix (plus the API 37 preview job). Keep `api36DebugAndroidTest` in lockstep with the
|
||||
highest managed device in `app/build.gradle.kts` and the E2E matrix in
|
||||
`.github/workflows/ci.yml` — when a newer API level is added there, run that one instead.
|
||||
|
||||
## Reporting
|
||||
|
||||
- If everything passes, say so plainly (e.g. "preflight green: build, unit tests, lint, ktlint, detekt").
|
||||
- If everything passes, say so plainly (e.g. "preflight green: build, unit tests, lint, ktlint, detekt, api36 E2E").
|
||||
- On failure, surface the actual Gradle error and point at the relevant report:
|
||||
- unit tests → `app/build/reports/tests/testDebugUnitTest/`
|
||||
- lint → `app/build/reports/lint-results-debug.html`
|
||||
- ktlint → `app/build/reports/ktlint/` (per source set, e.g. `ktlintTestSourceSetCheck/`)
|
||||
- detekt → `app/build/reports/detekt/`
|
||||
- Do **not** run emulator/E2E (`connectedDebugAndroidTest`) here — that's CI's job unless the
|
||||
user explicitly asks.
|
||||
- E2E → `app/build/reports/androidTests/managedDevice/` (per-device HTML, e.g. `.../api36/`)
|
||||
- Run only the **latest-API** E2E here (`api36DebugAndroidTest`, the highest level in the
|
||||
matrix); the full multi-API matrix and the API 37 preview job stay CI's job. If the host has
|
||||
no accelerated emulator and the managed device cannot boot, report that E2E could not run
|
||||
rather than treating the gate as green.
|
||||
|
||||
@@ -28,11 +28,15 @@ or via Gradle Managed Devices `./gradlew e2eGroupDebugAndroidTest` (whole matrix
|
||||
|
||||
**Before treating a change as done**, run the fast CI gate: `assembleDebug` +
|
||||
`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.
|
||||
`detekt` + the latest-API emulator E2E `api36DebugAndroidTest` (the `/preflight` skill does
|
||||
all of this). `compileDebugAndroidTestKotlin` compiles the `androidTest` source set that the
|
||||
static part 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. `api36DebugAndroidTest` runs the instrumented/E2E suite on API 36 — the highest
|
||||
API level in the E2E matrix — via its Gradle Managed Device (Gradle boots and tears down the
|
||||
emulator automatically). Running that one latest-API level locally is required; the full
|
||||
multi-API matrix (and the API 37 preview job) stays CI's job.
|
||||
|
||||
## Build-config gotchas
|
||||
|
||||
@@ -61,6 +65,15 @@ JVM unit tests use JUnit4 + `kotlin.test`, **Turbine** for `Flow`, **MockK** for
|
||||
**GreenMail** for a real in-process IMAP/SMTP server, and coroutines-test. `org.json` is
|
||||
pulled in as a real dependency for unit tests because `android.jar`'s version is a no-op stub.
|
||||
|
||||
## Definition of done
|
||||
|
||||
A change is not done until it ships with passing **unit tests** and **E2E/instrumented tests**
|
||||
that exercise the new or changed behaviour. Writing and committing that E2E/instrumented test
|
||||
is a required part of every task — and the test must actually **run and pass**, not merely
|
||||
compile: preflight runs the latest-API-level emulator E2E locally (`api36DebugAndroidTest`, the
|
||||
highest API level in the E2E matrix and its Gradle Managed Device task) and it must be green
|
||||
before the change is done. CI then runs the full multi-API matrix.
|
||||
|
||||
## Repo etiquette
|
||||
|
||||
- Branch off `main`; branch names like `feat-…` / `fix-…`. PRs target `main` and must pass
|
||||
|
||||
Reference in New Issue
Block a user