1- name : ' Expo native build (@clerk/expo)'
1+ name : ' Expo native (@clerk/expo)'
22
33on :
44 pull_request :
@@ -17,7 +17,7 @@ permissions:
1717 contents : read
1818
1919concurrency :
20- group : expo-native-build- ${{ github.head_ref || github.ref }}
20+ group : expo-native-${{ github.head_ref || github.ref }}
2121 cancel-in-progress : true
2222
2323env :
3232jobs :
3333 native-build :
3434 if : ${{ github.head_ref != 'changeset-release/main' }}
35- name : Expo ${{ matrix.expo-sdk }} / ${{ matrix.platform }}
35+ name : Expo ${{ matrix.expo-sdk }} Build / ${{ matrix.platform }}
3636 runs-on : ${{ matrix.runner }}
37- timeout-minutes : ${{ matrix.run-e2e == true && 60 || 45 }}
37+ timeout-minutes : 45
3838 strategy :
3939 fail-fast : false
4040 matrix :
@@ -153,6 +153,93 @@ jobs:
153153 working-directory : ${{ env.FIXTURE_DIR }}
154154 run : pnpm build:ios
155155
156+ # tar the .app so its bundle structure survives the artifact round-trip.
157+ - name : Package iOS app for e2e
158+ if : matrix.platform == 'ios' && matrix.run-e2e == true && steps.keys.outputs.pk != ''
159+ working-directory : ${{ env.FIXTURE_DIR }}
160+ run : |
161+ tar -C ios/build/Build/Products/Release-iphonesimulator \
162+ -cf "$RUNNER_TEMP/ClerkExpoNativeBuildFixture.app.tar" \
163+ ClerkExpoNativeBuildFixture.app
164+
165+ - name : Upload iOS fixture app
166+ if : matrix.platform == 'ios' && matrix.run-e2e == true && steps.keys.outputs.pk != ''
167+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
168+ with :
169+ name : expo-fixture-ios
170+ path : ${{ runner.temp }}/ClerkExpoNativeBuildFixture.app.tar
171+ retention-days : 1
172+ if-no-files-found : error
173+
174+ - name : Upload Android fixture app
175+ if : matrix.platform == 'android' && matrix.run-e2e == true && steps.keys.outputs.pk != ''
176+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
177+ with :
178+ name : expo-fixture-android
179+ path : ${{ env.FIXTURE_DIR }}/android/app/build/outputs/apk/release/app-release.apk
180+ retention-days : 1
181+ if-no-files-found : error
182+
183+ e2e :
184+ name : E2E / ${{ matrix.platform }}
185+ needs : native-build
186+ runs-on : ${{ matrix.runner }}
187+ timeout-minutes : 30
188+ strategy :
189+ fail-fast : false
190+ matrix :
191+ include :
192+ - platform : ios
193+ runner : blacksmith-6vcpu-macos-26
194+ - platform : android
195+ runner : blacksmith-8vcpu-ubuntu-2204
196+
197+ steps :
198+ - name : Checkout repo
199+ uses : actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
200+ with :
201+ persist-credentials : false
202+
203+ # Only Node (for the key resolver) is needed; the e2e job builds nothing.
204+ - uses : actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
205+ with :
206+ node-version : 24.15.0
207+
208+ - name : Check e2e secret availability
209+ id : gate
210+ env :
211+ KEYS : ${{ secrets.INTEGRATION_STAGING_INSTANCE_KEYS }}
212+ run : |
213+ if [ -n "$KEYS" ]; then
214+ echo "ok=true" >> "$GITHUB_OUTPUT"
215+ else
216+ echo "ok=false" >> "$GITHUB_OUTPUT"
217+ echo "::notice::INTEGRATION_STAGING_INSTANCE_KEYS unavailable (fork PR?); skipping e2e."
218+ fi
219+
220+ - name : Resolve Clerk instance keys
221+ id : keys
222+ if : steps.gate.outputs.ok == 'true'
223+ continue-on-error : true
224+ env :
225+ INTEGRATION_STAGING_INSTANCE_KEYS : ${{ secrets.INTEGRATION_STAGING_INSTANCE_KEYS }}
226+ run : node scripts/resolve-instance-keys.mjs INTEGRATION_STAGING_INSTANCE_KEYS "$E2E_INSTANCE_NAME"
227+
228+ - name : Download fixture app
229+ if : steps.keys.outputs.pk != ''
230+ uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
231+ with :
232+ name : expo-fixture-${{ matrix.platform }}
233+ path : ${{ runner.temp }}/fixture-app
234+
235+ # Maestro is a JVM app and needs a JDK on the Linux runner (macOS ships one).
236+ - name : Set up JDK 17
237+ if : matrix.platform == 'android' && steps.keys.outputs.pk != ''
238+ uses : actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
239+ with :
240+ distribution : temurin
241+ java-version : 17
242+
156243 - name : Cache Maestro
157244 if : steps.keys.outputs.pk != ''
158245 uses : actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
@@ -189,8 +276,8 @@ jobs:
189276 with :
190277 model : ' iPhone 17 Pro'
191278
192- # Provisioned as late as possible (after the expensive native build and
193- # simulator boot) so live credentials exist for the shortest window.
279+ # Provisioned as late as possible so live credentials exist for the
280+ # shortest window.
194281 - name : Provision test user via BAPI
195282 id : user
196283 if : steps.keys.outputs.pk != ''
@@ -224,7 +311,6 @@ jobs:
224311 # Burn-in: e2e cannot fail the check yet. Flip to hard-fail in a
225312 # follow-up once the suite has proven quiet.
226313 continue-on-error : true
227- working-directory : ${{ env.FIXTURE_DIR }}
228314 env :
229315 CLERK_TEST_EMAIL : ${{ steps.user.outputs.email }}
230316 CLERK_TEST_PASSWORD : ${{ steps.user.outputs.password }}
@@ -239,7 +325,8 @@ jobs:
239325 xcrun simctl spawn "$SIM_UDID" defaults write com.apple.keyboard.AutoCapitalization -bool NO || true
240326 xcrun simctl spawn "$SIM_UDID" defaults write com.apple.keyboard.AutoCorrection -bool NO || true
241327 xcrun simctl spawn "$SIM_UDID" defaults write com.apple.keyboard.Prediction -bool NO || true
242- xcrun simctl install "$SIM_UDID" ios/build/Build/Products/Release-iphonesimulator/ClerkExpoNativeBuildFixture.app
328+ tar -C "$RUNNER_TEMP/fixture-app" -xf "$RUNNER_TEMP/fixture-app/ClerkExpoNativeBuildFixture.app.tar"
329+ xcrun simctl install "$SIM_UDID" "$RUNNER_TEMP/fixture-app/ClerkExpoNativeBuildFixture.app"
243330 # Stream the app's console output into the debug artifact so a hang has
244331 # actionable evidence (keychain/network errors) instead of just screenshots.
245332 mkdir -p "$RUNNER_TEMP/maestro-debug"
@@ -301,7 +388,7 @@ jobs:
301388 # The action runs each script line in a separate sh -c; the folded
302389 # scalar (>-) plus && keeps everything in one shell invocation.
303390 script : >-
304- adb install -r integration/templates/expo-native/android/ app/build/outputs/apk/release/ app-release.apk &&
391+ adb install -r "$RUNNER_TEMP/fixture- app/app-release.apk" &&
305392 cd integration/tests/expo-native &&
306393 MAESTRO_DEBUG_OUTPUT="$RUNNER_TEMP/maestro-debug" ./run-flows.sh adb shell am force-stop com.clerk.exponativebuildfixture
307394
@@ -334,7 +421,7 @@ jobs:
334421 if : always() && (steps.run_e2e_ios.outcome == 'failure' || steps.run_e2e_android.outcome == 'failure')
335422 uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
336423 with :
337- name : maestro-${{ matrix.platform }}-sdk${{ matrix.expo-sdk }}
424+ name : maestro-${{ matrix.platform }}
338425 path : ${{ runner.temp }}/maestro-debug
339426 retention-days : 7
340427
@@ -346,7 +433,7 @@ jobs:
346433 run : |
347434 outcome="$IOS_OUTCOME"
348435 [ "$outcome" = "skipped" ] && outcome="$ANDROID_OUTCOME"
349- echo "## Maestro e2e (${{ matrix.platform }}, SDK ${{ matrix.expo-sdk }} ): $outcome" >> "$GITHUB_STEP_SUMMARY"
436+ echo "## Maestro e2e (${{ matrix.platform }}): $outcome" >> "$GITHUB_STEP_SUMMARY"
350437 if [ "$outcome" = "failure" ]; then
351- echo "::warning::Maestro e2e failed (burn-in mode: not failing the job). See the maestro-${{ matrix.platform }}-sdk${{ matrix.expo-sdk }} artifact."
438+ echo "::warning::Maestro e2e failed (burn-in mode: not failing the job). See the maestro-${{ matrix.platform }} artifact."
352439 fi
0 commit comments