From b8078093b1b348f5017c687885b605bb0ae0dc12 Mon Sep 17 00:00:00 2001 From: Greg Pstrucha <875316+Gricha@users.noreply.github.com> Date: Wed, 7 Jan 2026 20:30:06 -0800 Subject: [PATCH 1/4] Add Android e2e tests workflow to measure CI time Tests full e2e with backend (like web tests) to compare with iOS. Includes: - KVM hardware acceleration - Gradle/AVD caching - Full backend startup with Docker - Maestro tests on Android emulator Co-Authored-By: Claude Opus 4.5 --- .github/workflows/mobile-android-e2e.yml | 185 +++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 .github/workflows/mobile-android-e2e.yml diff --git a/.github/workflows/mobile-android-e2e.yml b/.github/workflows/mobile-android-e2e.yml new file mode 100644 index 00000000..ef8ad292 --- /dev/null +++ b/.github/workflows/mobile-android-e2e.yml @@ -0,0 +1,185 @@ +name: Mobile Android E2E Tests + +on: + push: + branches: [main] + paths: + - 'mobile/**' + - '.github/workflows/mobile-android-e2e.yml' + pull_request: + branches: [main] + paths: + - 'mobile/**' + - '.github/workflows/mobile-android-e2e.yml' + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + maestro-android: + runs-on: ubuntu-latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v4 + + - name: Enable KVM + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Cache bun dependencies + uses: actions/cache@v4 + with: + path: | + ~/.bun/install/cache + node_modules + mobile/node_modules + key: ${{ runner.os }}-bun-mobile-android-${{ hashFiles('mobile/bun.lock', 'bun.lock') }} + restore-keys: | + ${{ runner.os }}-bun-mobile-android- + + - name: Install root dependencies + run: bun install + + - name: Install mobile dependencies + working-directory: mobile + run: bun install + + - name: Generate Android native code + working-directory: mobile + run: bunx expo prebuild --platform android --clean + + - name: Cache Gradle + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('mobile/android/**/*.gradle*', 'mobile/android/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Build Android APK + working-directory: mobile/android + run: ./gradlew assembleRelease --no-daemon + + - name: Install Maestro + run: | + curl -Ls "https://get.maestro.mobile.dev" | bash + echo "$HOME/.maestro/bin" >> $GITHUB_PATH + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build workspace image (with cache) + uses: docker/build-push-action@v6 + with: + context: ./perry + load: true + tags: perry:latest + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-test + + - name: Build CLI + run: bun run build + + - name: Start agent + run: | + bun run src/index.ts agent run --port 7391 & + sleep 5 + curl -s http://localhost:7391/health || (echo "Agent failed to start" && exit 1) + + - name: Create test workspace + run: | + bun run src/index.ts start test + bun run src/index.ts list + + - name: Cache AVD + uses: actions/cache@v4 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-api-34-${{ runner.os }} + + - name: Create AVD and generate snapshot + if: steps.avd-cache.outputs.cache-hit != 'true' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 34 + target: google_apis + arch: x86_64 + force-avd-creation: false + emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: true + script: echo "Generated AVD snapshot for caching" + + - name: Run Maestro tests on Android + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 34 + target: google_apis + arch: x86_64 + force-avd-creation: false + emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: true + script: | + # Install APK + adb install mobile/android/app/build/outputs/apk/release/app-release.apk + + # Wait for app to be ready + sleep 5 + + # Take debug screenshot + adb exec-out screencap -p > /tmp/android-before-test.png || true + + # Run Maestro tests (exclude chat tests for now to compare with iOS) + $HOME/.maestro/bin/maestro test mobile/.maestro/flows/ --exclude-tags=chat --format junit --output mobile/maestro-android-report.xml + env: + MAESTRO_DRIVER_STARTUP_TIMEOUT: 120000 + + - name: Upload debug screenshot + uses: actions/upload-artifact@v4 + if: failure() + with: + name: android-debug-screenshot + path: /tmp/android-before-test.png + retention-days: 7 + + - name: Upload Maestro report + uses: actions/upload-artifact@v4 + if: always() + with: + name: maestro-android-report + path: mobile/maestro-android-report.xml + retention-days: 7 + + - name: Upload Maestro screenshots + uses: actions/upload-artifact@v4 + if: failure() + with: + name: maestro-android-screenshots + path: ~/.maestro/tests/ + retention-days: 7 From ea8f6e5c443c73d389b2e17488362683166c500b Mon Sep 17 00:00:00 2001 From: Greg Pstrucha <875316+Gricha@users.noreply.github.com> Date: Wed, 7 Jan 2026 20:45:47 -0800 Subject: [PATCH 2/4] Fix: install web dependencies for CLI build --- .github/workflows/mobile-android-e2e.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/mobile-android-e2e.yml b/.github/workflows/mobile-android-e2e.yml index ef8ad292..a98bd81d 100644 --- a/.github/workflows/mobile-android-e2e.yml +++ b/.github/workflows/mobile-android-e2e.yml @@ -49,13 +49,18 @@ jobs: ~/.bun/install/cache node_modules mobile/node_modules - key: ${{ runner.os }}-bun-mobile-android-${{ hashFiles('mobile/bun.lock', 'bun.lock') }} + web/node_modules + key: ${{ runner.os }}-bun-mobile-android-${{ hashFiles('mobile/bun.lock', 'bun.lock', 'web/bun.lock') }} restore-keys: | ${{ runner.os }}-bun-mobile-android- - name: Install root dependencies run: bun install + - name: Install web dependencies + working-directory: web + run: bun install + - name: Install mobile dependencies working-directory: mobile run: bun install From 84afbb592f0f6852468d513a55b112734e14b37f Mon Sep 17 00:00:00 2001 From: Greg Pstrucha <875316+Gricha@users.noreply.github.com> Date: Wed, 7 Jan 2026 21:04:56 -0800 Subject: [PATCH 3/4] Skip backend for now - measure base Android e2e time --- .github/workflows/mobile-android-e2e.yml | 32 ------------------------ 1 file changed, 32 deletions(-) diff --git a/.github/workflows/mobile-android-e2e.yml b/.github/workflows/mobile-android-e2e.yml index a98bd81d..efe3f07b 100644 --- a/.github/workflows/mobile-android-e2e.yml +++ b/.github/workflows/mobile-android-e2e.yml @@ -88,38 +88,6 @@ jobs: curl -Ls "https://get.maestro.mobile.dev" | bash echo "$HOME/.maestro/bin" >> $GITHUB_PATH - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build workspace image (with cache) - uses: docker/build-push-action@v6 - with: - context: ./perry - load: true - tags: perry:latest - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-test - - - name: Build CLI - run: bun run build - - - name: Start agent - run: | - bun run src/index.ts agent run --port 7391 & - sleep 5 - curl -s http://localhost:7391/health || (echo "Agent failed to start" && exit 1) - - - name: Create test workspace - run: | - bun run src/index.ts start test - bun run src/index.ts list - - name: Cache AVD uses: actions/cache@v4 id: avd-cache From aa4b762ddfda37ea866505afd792586d2d42ea9a Mon Sep 17 00:00:00 2001 From: Greg Pstrucha <875316+Gricha@users.noreply.github.com> Date: Wed, 7 Jan 2026 21:33:06 -0800 Subject: [PATCH 4/4] Use API 31 (lighter) and increase emulator boot timeout --- .github/workflows/mobile-android-e2e.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/mobile-android-e2e.yml b/.github/workflows/mobile-android-e2e.yml index efe3f07b..6fed4fd9 100644 --- a/.github/workflows/mobile-android-e2e.yml +++ b/.github/workflows/mobile-android-e2e.yml @@ -95,28 +95,28 @@ jobs: path: | ~/.android/avd/* ~/.android/adb* - key: avd-api-34-${{ runner.os }} + key: avd-api-31-${{ runner.os }} - name: Create AVD and generate snapshot if: steps.avd-cache.outputs.cache-hit != 'true' uses: reactivecircus/android-emulator-runner@v2 with: - api-level: 34 - target: google_apis + api-level: 31 arch: x86_64 force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + emulator-boot-timeout: 600 disable-animations: true script: echo "Generated AVD snapshot for caching" - name: Run Maestro tests on Android uses: reactivecircus/android-emulator-runner@v2 with: - api-level: 34 - target: google_apis + api-level: 31 arch: x86_64 force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + emulator-boot-timeout: 600 disable-animations: true script: | # Install APK