Guardrail: connected tests refuse to run without an emulator ANDROID_SERIAL
Post-incident: an unscoped connectedDebugAndroidTest fanned out to every adb device including the personal phone, where the debug test APK's signature mismatch was resolved by UNINSTALLING the release app — wiping its data. The v1->v2 Room migration was initially blamed but is innocent (three emulator replays preserved data; dumpsys firstInstallTime == lastUpdateTime proved the phone got a fresh install, not an upgrade). connected* tasks now fail fast unless ANDROID_SERIAL names an emulator. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
8157922efd
commit
5346b6a879
2 changed files with 24 additions and 0 deletions
|
|
@ -90,5 +90,9 @@ All gradlew calls need `JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64` — system
|
|||
- Verify alarms: `adb shell dumpsys alarm | grep meddetsamme` — `window=0` means exact
|
||||
- The phone (Pixel 7 Pro) has a RELEASE-signed install: `adb install` of debug builds is
|
||||
rejected on signature; use release builds for the phone, emulator for debug.
|
||||
- **INCIDENT RULE (2026-06-10, data was lost): never run a device-touching command
|
||||
unscoped.** Every `adb` call gets `-s <serial>`; connected tests get
|
||||
`ANDROID_SERIAL=emulator-<n>`. The build fails connected* tasks without an emulator
|
||||
serial — that guard stays. The phone is never a test target.
|
||||
|
||||
See @README.md for architecture detail.
|
||||
|
|
|
|||
|
|
@ -71,6 +71,26 @@ android {
|
|||
sourceSets.getByName("androidTest").assets.srcDir("$projectDir/schemas")
|
||||
}
|
||||
|
||||
// Guardrail (added after a real incident): an unscoped connected test run fans
|
||||
// out to EVERY adb device. On 2026-06-10 that meant the personal phone, where
|
||||
// the debug test APK's signature mismatch got "resolved" by uninstalling the
|
||||
// release app — destroying its data. Connected tests now refuse to run unless
|
||||
// ANDROID_SERIAL pins them to a specific (emulator) device.
|
||||
tasks.matching { it.name.startsWith("connected") }.configureEach {
|
||||
doFirst {
|
||||
val serial = System.getenv("ANDROID_SERIAL")
|
||||
check(!serial.isNullOrBlank()) {
|
||||
"Refusing to run connected tests without ANDROID_SERIAL — an unscoped run " +
|
||||
"targets every adb device, including the phone. " +
|
||||
"Use: ANDROID_SERIAL=emulator-5554 ./gradlew ${this@configureEach.name}"
|
||||
}
|
||||
check(serial.startsWith("emulator-")) {
|
||||
"ANDROID_SERIAL=$serial is not an emulator — connected tests must never " +
|
||||
"target a physical device."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Release builds refresh the bundled FEST dataset when it's >30 days old.
|
||||
// The script fast-exits when fresh and keeps the old file on download failure,
|
||||
// so offline/CI release builds never break on this.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue