From b6b0e41fd499f3ca9c512aef4b94742186492a3c Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Fri, 17 Jul 2026 15:58:28 +0300 Subject: [PATCH] Embed JS bundle in nightly E2E apps --- .github/scripts/cleanup-nightly-e2e.sh | 1 - .github/scripts/run-nightly-e2e.sh | 13 +----------- .github/workflows/nightly-e2e.yml | 16 +++++++-------- __e2e__/setupApp.yml | 22 -------------------- docs/testing.md | 28 ++++++++++++++------------ eas.json | 7 ++++++- 6 files changed, 30 insertions(+), 57 deletions(-) diff --git a/.github/scripts/cleanup-nightly-e2e.sh b/.github/scripts/cleanup-nightly-e2e.sh index c37974de92..425b5d7f1c 100755 --- a/.github/scripts/cleanup-nightly-e2e.sh +++ b/.github/scripts/cleanup-nightly-e2e.sh @@ -28,7 +28,6 @@ stop_pid_file() { } stop_pid_file "$artifact_dir/logcat.pid" -stop_pid_file "$artifact_dir/metro.pid" stop_pid_file "$artifact_dir/mock-server.pid" stop_pid_file "$artifact_dir/emulator.pid" diff --git a/.github/scripts/run-nightly-e2e.sh b/.github/scripts/run-nightly-e2e.sh index e2f7afee4e..0331ef0553 100755 --- a/.github/scripts/run-nightly-e2e.sh +++ b/.github/scripts/run-nightly-e2e.sh @@ -53,7 +53,7 @@ stop_pid_file() { pid="$(cat "$pid_file")" [[ -n "$pid" ]] || return 0 - # pnpm and Expo both spawn multiple generations of children. + # pnpm can spawn multiple generations of children. stop_process_tree "$pid" } @@ -61,7 +61,6 @@ stop_pid_file() { cleanup() { set +e stop_pid_file "$artifact_dir/logcat.pid" - stop_pid_file "$artifact_dir/metro.pid" stop_pid_file "$artifact_dir/mock-server.pid" if [[ "$platform" == "ios" ]]; then @@ -134,19 +133,9 @@ fi printf '%s\n' "$!" >"$artifact_dir/mock-server.pid" wait_for_port 1986 "the E2E mock-server manager" -phase "Starting Metro" -EXPO_PUBLIC_ENV=e2e \ - NODE_ENV=test \ - RN_SRC_EXT=e2e.ts,e2e.tsx \ - pnpm exec expo start --dev-client --clear --port 8081 \ - >"$artifact_dir/metro.log" 2>&1 & -printf '%s\n' "$!" >"$artifact_dir/metro.pid" -wait_for_port 8081 "Metro" - if [[ "$platform" == "android" ]]; then phase "Configuring Android localhost routing" adb -s "$device_id" reverse tcp:3000 tcp:3000 - adb -s "$device_id" reverse tcp:8081 tcp:8081 fi phase "Running Maestro flows" diff --git a/.github/workflows/nightly-e2e.yml b/.github/workflows/nightly-e2e.yml index d701c42acd..7ac43836a5 100644 --- a/.github/workflows/nightly-e2e.yml +++ b/.github/workflows/nightly-e2e.yml @@ -117,10 +117,10 @@ jobs: xcrun simctl bootstatus "$udid" -b echo "Using $device_name on $runtime_name ($udid)" - - name: Mark iOS development client build phase - run: echo "Building the iOS development client" > artifacts/ios/phase.txt + - name: Mark iOS E2E app build phase + run: echo "Building the iOS E2E app" > artifacts/ios/phase.txt - - name: Build iOS development client + - name: Build iOS E2E app uses: ./.github/actions/eas-local-build with: platform: ios @@ -128,7 +128,7 @@ jobs: output: ${{ runner.temp }}/nightly-e2e-ios.tar.gz log-path: artifacts/ios/build.log - - name: Install iOS development client + - name: Install iOS E2E app run: | build_contents="$RUNNER_TEMP/nightly-e2e-ios-build" mkdir -p "$build_contents" @@ -275,10 +275,10 @@ jobs: adb -s emulator-5554 shell settings put global transition_animation_scale 0 adb -s emulator-5554 shell settings put global animator_duration_scale 0 - - name: Mark Android development client build phase - run: echo "Building the Android development client" > artifacts/android/phase.txt + - name: Mark Android E2E app build phase + run: echo "Building the Android E2E app" > artifacts/android/phase.txt - - name: Build Android development client + - name: Build Android E2E app uses: ./.github/actions/eas-local-build with: platform: android @@ -286,7 +286,7 @@ jobs: output: ${{ runner.temp }}/nightly-e2e-android.apk log-path: artifacts/android/build.log - - name: Install Android development client + - name: Install Android E2E app run: | adb -s emulator-5554 install -r "$RUNNER_TEMP/nightly-e2e-android.apk" \ 2>&1 | tee -a artifacts/android/build.log diff --git a/__e2e__/setupApp.yml b/__e2e__/setupApp.yml index 36794d6197..4b7bb77426 100644 --- a/__e2e__/setupApp.yml +++ b/__e2e__/setupApp.yml @@ -3,28 +3,6 @@ appId: xyz.blueskyweb.app - launchApp: appId: "xyz.blueskyweb.app" clearState: true - arguments: - "-EXDevMenuIsOnboardingFinished": true -- runFlow: - when: - platform: iOS - commands: - - extendedWaitUntil: - visible: "http://localhost:8081" - timeout: 60000 - - tapOn: "http://localhost:8081" -- runFlow: - when: - platform: Android - commands: - - extendedWaitUntil: - visible: "http://10.0.2.2:8081" - timeout: 60000 - - tapOn: "http://10.0.2.2:8081" - - extendedWaitUntil: - visible: "Continue" - timeout: 180000 - - tapOn: "Continue" - extendedWaitUntil: visible: id: e2eProxyHeaderInput diff --git a/docs/testing.md b/docs/testing.md index 4fde458911..0ca058cc65 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -42,21 +42,23 @@ used. iOS runs on `macos-26-xlarge` with Xcode 26.4. Android runs on `Linux-x64-32core`. Both use Java 17 and the Node and pnpm versions declared in `package.json`. The iOS job selects an iPhone 17 simulator running iOS 26.5; Android uses a Pixel 6 AVD with the API 35 Google APIs x86_64 image. -Both development clients use the `e2e` EAS profile and the same reusable local -EAS build action as the release build workflows; the resulting simulator app -and APK are installed directly on the selected devices. +Both standalone E2E apps use the `e2e` EAS profile and the same reusable local +EAS build action as the release build workflows. The profile embeds the E2E JS +bundle during the native build, so CI does not run Metro or the Expo development +client. The resulting simulator app and APK are installed directly on the +selected devices. The mock-server manager listens on host port 1986 and creates test services on -port 3000. Metro listens on 8081. Android reverses ports 3000 and 8081 into the -emulator; port 1986 remains host-side because Maestro JavaScript calls it from -the runner. Android uses the existing Docker Compose PostgreSQL 14 and Redis 7 -services on ports 5433 and 6380. GitHub-hosted macOS cannot run nested Docker -virtualization, so iOS provisions ephemeral native PostgreSQL 14.x and Redis -7.4.7 on those same ports and starts `pnpm --dir dev-env start:external`. +port 3000. Android reverses port 3000 into the emulator; port 1986 remains +host-side because Maestro JavaScript calls it from the runner. Android uses the +existing Docker Compose PostgreSQL 14 and Redis 7 services on ports 5433 and +6380. GitHub-hosted macOS cannot run nested Docker virtualization, so iOS +provisions ephemeral native PostgreSQL 14.x and Redis 7.4.7 on those same ports +and starts `pnpm --dir dev-env start:external`. Each platform uploads a `nightly-e2e--` artifact for 14 days. It contains JUnit at `report.xml`, Maestro screenshots, videos, command metadata -and `maestro.log` under `maestro/`, plus Metro, native build, mock-server, service, +and `maestro.log` under `maestro/`, plus native build, mock-server, service, dependency, and translation logs. The workflow always uploads what was captured, including when setup or the native build fails before Maestro starts. @@ -67,9 +69,9 @@ the failed setup phase, the commit and workflow links, and links to both artifac sets. Successful runs do not post to Slack. Before relying on the schedule, manually dispatch the workflow and verify both -platforms against live Metro and `dev-env`, Android localhost routing, artifact -uploads on success and failure, one Slack message for a forced failure, and no -Slack message for an all-green run. +embedded E2E apps against `dev-env`, Android localhost routing, artifact uploads +on success and failure, one Slack message for a forced failure, and no Slack +message for an all-green run. ## Using Flashlight for Performance Testing 1. Make sure Maestro is installed (optional: only for automated testing) by following the instructions above diff --git a/eas.json b/eas.json index 5bf4e25513..0613d60b70 100644 --- a/eas.json +++ b/eas.json @@ -22,7 +22,12 @@ } }, "e2e": { - "extends": "development", + "extends": "base", + "distribution": "internal", + "ios": { + "simulator": true, + "resourceClass": "large" + }, "android": { "buildType": "apk" },