fix(folio): refuse to install and fuzz a device nobody named

adb falls through to the local server when ADB_SERVER_SOCKET is unset, and
claims the only device attached there. That could be a personal handset, and a
run installs the app, clears its state and fuzzes it. Every recipe that touches
a device now resolves the target through _require-device, which only picks on
its own when a single local emulator is all adb sees.
This commit is contained in:
pj committed 2026-08-18 20:47:24 +05:30
1 parent 3a79f9f0e7
commit 8abe2c1ca0
1 file changed
+57 -15
+57 -15
View File
@@ -79,6 +79,51 @@ _ensure-device:
echo "emulator did not finish booting in time (see /tmp/folio-emulator.log)" >&2
exit 1
# Print the serial every device-affecting recipe must act on, or refuse. A run
# installs the app, clears its state and fuzzes it, so the target is never
# inferred from "whatever adb resolved to": the one case it picks on its own is
# a single emulator on the local adb server, which is cheap to rebuild.
_require-device:
#!/usr/bin/env bash
set -euo pipefail
adb="$(just _android-home)/platform-tools/adb"
listing="$("$adb" devices)"
online="$(echo "$listing" | awk 'NR>1 && $2=="device"{print $1}')"
count="$(printf '%s' "$online" | grep -c . || true)"
refuse() {
cat >&2 <<EOF
folio: $1
$listing
Set ANDROID_DEVICE to the serial to use, and ADB_SERVER_SOCKET when that adb
server runs on another host. Either can live in examples/folio/.env:
ANDROID_DEVICE=emulator-5554 just test
ADB_SERVER_SOCKET=tcp:10.0.0.5:5037 ANDROID_DEVICE=emulator-5554 just test
EOF
exit 1
}
if [[ -n "{{android_device}}" ]]; then
if printf '%s\n' "$online" | grep -qxF "{{android_device}}"; then
echo "{{android_device}}"
exit 0
fi
refuse "ANDROID_DEVICE={{android_device}} is not an online device."
fi
if [[ "$count" -eq 0 ]]; then
refuse "no device is online."
fi
if [[ -z "${ADB_SERVER_SOCKET:-}" && "$count" -eq 1 && "$online" =~ ^emulator-[0-9]+$ ]]; then
echo "$online"
exit 0
fi
refuse "refusing to install on and fuzz a device nobody named. A run installs
the app, clears its state and drives it, so the only target it picks on its
own is a single emulator on the local adb server."
# Run folio's own unit tests. Named test-unit because `test` is the fuzz run.
test-unit:
#!/usr/bin/env bash
@@ -101,9 +146,9 @@ install: _ensure-device
#!/usr/bin/env bash
set -euo pipefail
export ANDROID_HOME="$(just _android-home)"
serial="$(just _require-device)"
export ANDROID_SERIAL="$serial"
./gradlew :app:androidApp:assembleDebug
# ANDROID_SERIAL routes the install to the chosen device when several attach.
[[ -n "{{android_device}}" ]] && export ANDROID_SERIAL="{{android_device}}"
"$ANDROID_HOME/platform-tools/adb" install -r "{{apk}}"
# Remove the folio APK from the connected device.
@@ -111,7 +156,8 @@ uninstall:
#!/usr/bin/env bash
set -euo pipefail
export ANDROID_HOME="$(just _android-home)"
[[ -n "{{android_device}}" ]] && export ANDROID_SERIAL="{{android_device}}"
serial="$(just _require-device)"
export ANDROID_SERIAL="$serial"
"$ANDROID_HOME/platform-tools/adb" uninstall app.folio
# Remove gradle + iOS build directories.
@@ -176,17 +222,15 @@ ios-device:
test: install
#!/usr/bin/env bash
set -euo pipefail
avd_flag=()
serial="$(just _require-device)"
device_flag=(--device "$serial")
if [[ -n "{{avd}}" ]]; then
avd_flag=(--avd "{{avd}}")
fi
if [[ -n "{{android_device}}" ]]; then
avd_flag+=(--device "{{android_device}}")
device_flag+=(--avd "{{avd}}")
fi
"{{sanderling}}" test \
--spec "{{justfile_directory()}}/sanderling/spec.ts" \
--bundle-id app.folio \
"${avd_flag[@]}" \
"${device_flag[@]}" \
--android-app-path "{{apk}}" \
--duration "{{duration}}" \
--seed "{{seed}}" \
@@ -198,18 +242,16 @@ test: install
test-llm: install
#!/usr/bin/env bash
set -euo pipefail
avd_flag=()
serial="$(just _require-device)"
device_flag=(--device "$serial")
if [[ -n "{{avd}}" ]]; then
avd_flag=(--avd "{{avd}}")
fi
if [[ -n "{{android_device}}" ]]; then
avd_flag+=(--device "{{android_device}}")
device_flag+=(--avd "{{avd}}")
fi
"{{sanderling}}" test \
--spec "{{justfile_directory()}}/sanderling/spec.ts" \
--bundle-id app.folio \
--generator llm \
"${avd_flag[@]}" \
"${device_flag[@]}" \
--android-app-path "{{apk}}" \
--duration "{{duration}}" \
--seed "{{seed}}" \