diff --git a/scripts/deploy_android.sh b/scripts/deploy_android.sh index e613b0c..b177d87 100755 --- a/scripts/deploy_android.sh +++ b/scripts/deploy_android.sh @@ -3,9 +3,10 @@ trap 'echo -e "\n🤷 🚨 šŸ”„ Warning: A command has failed. Exiting the script. Line was ($0:$LINENO): $(sed -n "${LINENO}p" "$0" 2>/dev/null || true) šŸ”„ 🚨 🤷 "; exit 3' ERR set -Eeuo pipefail -: "${ANDROID_APK_SCP_HOST:?ANDROID_APK_SCP_HOST is not set (add it to .env)}" -: "${ANDROID_APK_SCP_USER:?ANDROID_APK_SCP_USER is not set (add it to .env)}" -: "${ANDROID_APK_SCP_PATH:?ANDROID_APK_SCP_PATH is not set (add it to .env)}" +if [ -z "${ANDROID_APK_SCP_HOST:-}" ] || [ -z "${ANDROID_APK_SCP_USER:-}" ] || [ -z "${ANDROID_APK_SCP_PATH:-}" ]; then + echo "ERROR: ANDROID_APK_SCP_HOST, ANDROID_APK_SCP_USER, and ANDROID_APK_SCP_PATH must be set in .env" + exit 1 +fi scp -C build/app/outputs/flutter-apk/app-release.apk "${ANDROID_APK_SCP_USER}@${ANDROID_APK_SCP_HOST}:${ANDROID_APK_SCP_PATH}" diff --git a/stalwart-dev/integration_android_test.sh b/stalwart-dev/integration_android_test.sh index e500ee1..04e53c1 100755 --- a/stalwart-dev/integration_android_test.sh +++ b/stalwart-dev/integration_android_test.sh @@ -45,9 +45,19 @@ ADB=$(command -v adb 2>/dev/null || echo "${ANDROID_HOME:-$HOME/Android/Sdk}/pla # Detect a connected Android emulator; auto-start the sharedinbox_test AVD if none is running. EMULATOR_ID=$("$ADB" devices | awk '/^emulator-[0-9]+[[:space:]]+device$/ {print $1; exit}') if [ -z "$EMULATOR_ID" ]; then + # Check for KVM before starting. + if [ ! -c /dev/kvm ] || [ ! -r /dev/kvm ] || [ ! -w /dev/kvm ]; then + echo "ERROR: KVM (/dev/kvm) not accessible. Software emulation is too slow for these tests." + echo "Run these commands to fix permissions:" + echo " sudo groupadd -r kvm || true" + echo " sudo gpasswd -a \$USER kvm" + echo " # Then log out and back in." + exit 1 + fi + EMULATOR_BIN="${ANDROID_HOME:-$HOME/Android/Sdk}/emulator/emulator" ts "no emulator running — booting AVD sharedinbox_test" - "$EMULATOR_BIN" -avd sharedinbox_test -no-window -no-audio -no-snapshot-save -accel off -no-boot-anim -gpu swiftshader_indirect > /tmp/emulator.log 2>&1 & + "$EMULATOR_BIN" -avd sharedinbox_test -no-window -no-audio -no-snapshot-save > /tmp/emulator.log 2>&1 & EMULATOR_BOOT_PID=$! # Extend cleanup to also kill the emulator we started. cleanup() { @@ -57,21 +67,21 @@ if [ -z "$EMULATOR_ID" ]; then kill "${EMULATOR_BOOT_PID:-}" 2>/dev/null || true } trap cleanup EXIT - # Wait up to 300 s for the emulator to appear as a fully booted device. - for _i in $(seq 1 150); do + # Wait up to 120 s for the emulator to appear as a fully booted device. + for _i in $(seq 1 60); do EMULATOR_ID=$("$ADB" devices | awk '/^emulator-[0-9]+[[:space:]]+device$/ {print $1; exit}') [ -n "$EMULATOR_ID" ] && break sleep 2 done - [ -n "$EMULATOR_ID" ] || { echo "Emulator did not become ready within 300 s"; exit 1; } + [ -n "$EMULATOR_ID" ] || { echo "Emulator did not become ready within 120 s"; exit 1; } # Wait for the Android system to finish booting (sys.boot_completed=1). "$ADB" -s "$EMULATOR_ID" wait-for-device - for _i in $(seq 1 600); do + for _i in $(seq 1 30); do BOOT_DONE=$("$ADB" -s "$EMULATOR_ID" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r') [ "$BOOT_DONE" = "1" ] && break sleep 2 done - [ "${BOOT_DONE:-0}" = "1" ] || { echo "Android boot did not complete within 1200 s"; exit 1; } + [ "${BOOT_DONE:-0}" = "1" ] || { echo "Android boot did not complete within 60 s"; exit 1; } fi ts "using emulator: $EMULATOR_ID" @@ -110,17 +120,18 @@ curl -s --max-time 1 -o /dev/null "${STALWART_URL}/.well-known/jmap" || { cat "$LOGFILE"; echo "Stalwart did not become ready"; exit 1 } -ts "stalwart ready — IMAP=:${STALWART_IMAP_PORT:-?} SMTP=:${STALWART_SMTP_PORT:-?}" +ts "stalwart ready — IMAP=:${STALWART_IMAP_PORT:-?} SMTP=:${STALWART_SMTP_PORT:-?} SIEVE=:${STALWART_SIEVE_PORT:-?}" ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$ROOT" # Platform.environment is empty inside the Android app process, so env vars set # by this script never reach the test code. Instead, use adb reverse to forward -# the fixed "template" ports that the test defaults to (1430 IMAP, 1025 SMTP) +# the fixed "template" ports that the test defaults to (1430 IMAP, 1025 SMTP, 4190 SIEVE) # on the emulator through to the actual random Stalwart ports on the host. "$ADB" -s "$EMULATOR_ID" reverse tcp:1430 tcp:"$STALWART_IMAP_PORT" "$ADB" -s "$EMULATOR_ID" reverse tcp:1025 tcp:"$STALWART_SMTP_PORT" +"$ADB" -s "$EMULATOR_ID" reverse tcp:4190 tcp:"$STALWART_SIEVE_PORT" # Clear any leftover app state from previous runs (stale DB, cached APK process). # Only run if the package is installed — that way any failure is a real error. diff --git a/stalwart-dev/run_android.sh b/stalwart-dev/run_android.sh index f89b8cc..855b970 100755 --- a/stalwart-dev/run_android.sh +++ b/stalwart-dev/run_android.sh @@ -17,22 +17,32 @@ ADB=$(command -v adb 2>/dev/null || echo "${ANDROID_HOME:-$HOME/Android/Sdk}/pla EMULATOR_ID=$("$ADB" devices | awk '/^emulator-[0-9]+[[:space:]]+device$/ {print $1; exit}') if [ -z "$EMULATOR_ID" ]; then + # Check for KVM before starting. + if [ ! -c /dev/kvm ] || [ ! -r /dev/kvm ] || [ ! -w /dev/kvm ]; then + echo "ERROR: KVM (/dev/kvm) not accessible. Software emulation is too slow." + echo "Run these commands to fix permissions:" + echo " sudo groupadd -r kvm || true" + echo " sudo gpasswd -a \$USER kvm" + echo " # Then log out and back in." + exit 1 + fi + EMULATOR_BIN="${ANDROID_HOME:-$HOME/Android/Sdk}/emulator/emulator" echo "No emulator running — booting AVD sharedinbox_test..." - "$EMULATOR_BIN" -avd sharedinbox_test -no-audio -no-snapshot-save -accel off & - for _i in $(seq 1 150); do + "$EMULATOR_BIN" -avd sharedinbox_test -no-audio -no-snapshot-save & + for _i in $(seq 1 60); do EMULATOR_ID=$("$ADB" devices | awk '/^emulator-[0-9]+[[:space:]]+device$/ {print $1; exit}') [ -n "$EMULATOR_ID" ] && break sleep 2 done - [ -n "$EMULATOR_ID" ] || { echo "Emulator did not become ready within 300 s"; exit 1; } + [ -n "$EMULATOR_ID" ] || { echo "Emulator did not become ready within 120 s"; exit 1; } "$ADB" -s "$EMULATOR_ID" wait-for-device - for _i in $(seq 1 450); do + for _i in $(seq 1 30); do BOOT_DONE=$("$ADB" -s "$EMULATOR_ID" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r') [ "$BOOT_DONE" = "1" ] && break sleep 2 done - [ "${BOOT_DONE:-0}" = "1" ] || { echo "Android boot did not complete within 900 s"; exit 1; } + [ "${BOOT_DONE:-0}" = "1" ] || { echo "Android boot did not complete within 60 s"; exit 1; } fi echo "Using emulator: $EMULATOR_ID" diff --git a/stalwart-dev/start b/stalwart-dev/start index b75e56d..88d7bf9 100755 --- a/stalwart-dev/start +++ b/stalwart-dev/start @@ -21,11 +21,11 @@ if [ "${STALWART_RANDOM_PORTS:-0}" = "1" ] || [ "${STALWART_PORT:-0}" = "0" ]; t echo "python3 not in PATH — cannot choose random Stalwart ports" exit 1 } - read -r STALWART_PORT STALWART_IMAP_PORT STALWART_SMTP_PORT < <( + read -r STALWART_PORT STALWART_IMAP_PORT STALWART_SMTP_PORT STALWART_SIEVE_PORT < <( python3 - <<'PY' import socket ports = [] -for _ in range(3): +for _ in range(4): sock = socket.socket() sock.bind(("127.0.0.1", 0)) ports.append(str(sock.getsockname()[1])) @@ -37,15 +37,16 @@ else : "${STALWART_PORT:?STALWART_PORT is not set — run this inside nix develop}" STALWART_IMAP_PORT="${STALWART_IMAP_PORT:-$((STALWART_PORT + 1))}" STALWART_SMTP_PORT="${STALWART_SMTP_PORT:-$((STALWART_PORT + 2))}" + STALWART_SIEVE_PORT="${STALWART_SIEVE_PORT:-$((STALWART_PORT + 3))}" fi -export STALWART_PORT STALWART_IMAP_PORT STALWART_SMTP_PORT +export STALWART_PORT STALWART_IMAP_PORT STALWART_SMTP_PORT STALWART_SIEVE_PORT export STALWART_URL="http://127.0.0.1:${STALWART_PORT}" TMPDIR="${STALWART_TMPDIR:-/tmp/stalwart-dev-${STALWART_PORT}}" mkdir -p "$TMPDIR" -for port in "$STALWART_PORT" "$STALWART_IMAP_PORT" "$STALWART_SMTP_PORT"; do +for port in "$STALWART_PORT" "$STALWART_IMAP_PORT" "$STALWART_SMTP_PORT" "$STALWART_SIEVE_PORT"; do ss -ltnH "sport = :$port" | grep -q . && { echo "Stalwart port $port is already in use" exit 1 @@ -56,10 +57,11 @@ cat >"${TMPDIR}/ports.env" <&2 +echo "Stalwart ports: JMAP=${STALWART_PORT} IMAP=${STALWART_IMAP_PORT} SMTP=${STALWART_SMTP_PORT} SIEVE=${STALWART_SIEVE_PORT}" >&2 echo "Stalwart is running in the foreground. Press Ctrl+C to stop." >&2 echo "Connection info written to ${TMPDIR}/ports.env" >&2 @@ -68,6 +70,7 @@ REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" sed -e "s|127.0.0.1:8080|127.0.0.1:${STALWART_PORT}|" \ -e "s|127.0.0.1:1430|127.0.0.1:${STALWART_IMAP_PORT}|" \ -e "s|127.0.0.1:1025|127.0.0.1:${STALWART_SMTP_PORT}|" \ + -e "s|127.0.0.1:4190|127.0.0.1:${STALWART_SIEVE_PORT}|" \ -e "s|/tmp/stalwart-dev|${TMPDIR}|" \ "${REPO_ROOT}/stalwart-dev/config.toml" >"${TMPDIR}/config.toml"