@@ -26,10 +26,10 @@ jobs:
2626 e2e-android :
2727 name : E2E Android
2828 runs-on : ubuntu-22.04
29+ timeout-minutes : 30
2930 if : ${{ (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'android')) }}
3031 env :
3132 HARNESS_DEBUG : true
32-
3333 steps :
3434 - name : Checkout code
3535 uses : actions/checkout@v4
@@ -108,6 +108,7 @@ jobs:
108108 e2e-ios :
109109 name : E2E iOS
110110 runs-on : macos-latest
111+ timeout-minutes : 30
111112 if : ${{ (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'ios')) }}
112113 steps :
113114 - name : Checkout code
@@ -194,10 +195,10 @@ jobs:
194195 e2e-web :
195196 name : E2E Web
196197 runs-on : ubuntu-22.04
198+ timeout-minutes : 30
197199 if : ${{ (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'web')) }}
198200 env :
199201 HARNESS_DEBUG : true
200-
201202 steps :
202203 - name : Checkout code
203204 uses : actions/checkout@v4
@@ -237,3 +238,221 @@ jobs:
237238 with :
238239 runner : chromium
239240 projectRoot : apps/playground
241+
242+ crash-validate-android :
243+ name : Crash Validation Android
244+ runs-on : ubuntu-22.04
245+ timeout-minutes : 30
246+ if : ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'android') }}
247+ env :
248+ HARNESS_DEBUG : true
249+
250+ steps :
251+ - name : Checkout code
252+ uses : actions/checkout@v4
253+ with :
254+ ref : ${{ github.ref }}
255+ fetch-depth : 0
256+
257+ - name : Reclaim disk space
258+ uses : AdityaGarg8/remove-unwanted-software@v5
259+ with :
260+ remove-dotnet : true
261+ remove-haskell : true
262+ remove-codeql : true
263+ remove-docker-images : true
264+
265+ - name : Install pnpm
266+ uses : pnpm/action-setup@v2
267+ with :
268+ version : latest
269+
270+ - name : Setup Node.js
271+ uses : actions/setup-node@v4
272+ with :
273+ node-version : ' 24.10.0'
274+ cache : ' pnpm'
275+
276+ - name : Metro cache
277+ uses : actions/cache@v4
278+ with :
279+ path : apps/playground/node_modules/.cache/rn-harness/metro-cache
280+ key : metro-cache-${{ hashFiles('apps/playground/node_modules/.cache/rn-harness/metro-cache/**/*') }}
281+ restore-keys : |
282+ metro-cache
283+
284+ - name : Install dependencies
285+ run : |
286+ pnpm install
287+
288+ - name : Build packages
289+ run : |
290+ pnpm nx run-many -t build --projects="packages/*"
291+
292+ - name : Set up JDK 17
293+ uses : actions/setup-java@v3
294+ with :
295+ java-version : ' 17'
296+ distribution : ' temurin'
297+
298+ - name : Restore APK from cache
299+ id : cache-apk-restore
300+ uses : actions/cache/restore@v4
301+ with :
302+ path : apps/playground/android/app/build/outputs/apk/debug/app-debug.apk
303+ key : apk-playground
304+
305+ - name : Build Android app
306+ if : steps.cache-apk-restore.outputs.cache-hit != 'true'
307+ working-directory : apps/playground
308+ run : |
309+ pnpm nx run @react-native-harness/playground:build-android --tasks=assembleDebug
310+
311+ - name : Save APK to cache
312+ if : steps.cache-apk-restore.outputs.cache-hit != 'true' && success()
313+ uses : actions/cache/save@v4
314+ with :
315+ path : apps/playground/android/app/build/outputs/apk/debug/app-debug.apk
316+ key : apk-playground
317+
318+ - name : Run React Native Harness (expect crash)
319+ id : crash-test
320+ continue-on-error : true
321+ uses : ./actions/android
322+ with :
323+ app : android/app/build/outputs/apk/debug/app-debug.apk
324+ runner : android-crash-pre-rn
325+ projectRoot : apps/playground
326+ harnessArgs : --testPathPattern smoke
327+
328+ - name : Verify crash was detected
329+ shell : bash
330+ run : |
331+ if [ "${{ steps.crash-test.outcome }}" != "failure" ]; then
332+ echo "ERROR: Expected harness to fail (crash not detected)"
333+ exit 1
334+ fi
335+ echo "Crash was correctly detected by the harness"
336+
337+ - name : Verify crash artifacts exist
338+ shell : bash
339+ run : |
340+ CRASH_DIR="apps/playground/.harness/crash-reports"
341+ if [ -d "$CRASH_DIR" ] && [ "$(ls -A "$CRASH_DIR" 2>/dev/null)" ]; then
342+ echo "Crash report artifacts found:"
343+ ls -la "$CRASH_DIR"
344+ else
345+ echo "ERROR: No crash report artifacts found in $CRASH_DIR"
346+ exit 1
347+ fi
348+
349+ crash-validate-ios :
350+ name : Crash Validation iOS
351+ runs-on : macos-latest
352+ timeout-minutes : 30
353+ if : ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'ios') }}
354+ steps :
355+ - name : Checkout code
356+ uses : actions/checkout@v4
357+ with :
358+ ref : ${{ github.ref }}
359+ fetch-depth : 0
360+
361+ - name : Install pnpm
362+ uses : pnpm/action-setup@v2
363+ with :
364+ version : latest
365+
366+ - name : Setup Node.js
367+ uses : actions/setup-node@v4
368+ with :
369+ node-version : ' 24.10.0'
370+ cache : ' pnpm'
371+
372+ - name : Metro cache
373+ uses : actions/cache@v4
374+ with :
375+ path : apps/playground/node_modules/.cache/rn-harness/metro-cache
376+ key : metro-cache-${{ hashFiles('apps/playground/node_modules/.cache/rn-harness/metro-cache/**/*') }}
377+ restore-keys : |
378+ metro-cache
379+
380+ - name : Install Watchman
381+ run : brew install watchman
382+
383+ - name : Install dependencies
384+ run : |
385+ pnpm install
386+
387+ - name : Build packages
388+ run : |
389+ pnpm nx run-many -t build --projects="packages/*"
390+
391+ - name : Restore app from cache
392+ id : cache-app-restore
393+ uses : actions/cache/restore@v4
394+ with :
395+ path : ./apps/playground/ios/build/Build/Products/Debug-iphonesimulator/HarnessPlayground.app
396+ key : ios-app-playground
397+
398+ - name : CocoaPods cache
399+ if : steps.cache-app-restore.outputs.cache-hit != 'true'
400+ uses : actions/cache@v4
401+ with :
402+ path : |
403+ ./apps/playground/ios/Pods
404+ ~/Library/Caches/CocoaPods
405+ ~/.cocoapods
406+ key : playground-${{ runner.os }}-pods-${{ hashFiles('./apps/playground/ios/Podfile.lock') }}
407+ restore-keys : |
408+ playground-${{ runner.os }}-pods-
409+
410+ - name : Install CocoaPods
411+ if : steps.cache-app-restore.outputs.cache-hit != 'true'
412+ working-directory : apps/playground/ios
413+ run : |
414+ pod install
415+
416+ - name : Build iOS app
417+ if : steps.cache-app-restore.outputs.cache-hit != 'true'
418+ working-directory : apps/playground
419+ run : |
420+ pnpm react-native build-ios --buildFolder ./build --verbose
421+
422+ - name : Save app to cache
423+ if : steps.cache-app-restore.outputs.cache-hit != 'true' && success()
424+ uses : actions/cache/save@v4
425+ with :
426+ path : ./apps/playground/ios/build/Build/Products/Debug-iphonesimulator/HarnessPlayground.app
427+ key : ios-app-playground
428+
429+ - name : Run React Native Harness (expect crash)
430+ id : crash-test
431+ continue-on-error : true
432+ uses : ./actions/ios
433+ with :
434+ app : ios/build/Build/Products/Debug-iphonesimulator/HarnessPlayground.app
435+ runner : ios-crash-pre-rn
436+ projectRoot : apps/playground
437+ harnessArgs : --testPathPattern smoke
438+
439+ - name : Verify crash was detected
440+ shell : bash
441+ run : |
442+ if [ "${{ steps.crash-test.outcome }}" != "failure" ]; then
443+ echo "ERROR: Expected harness to fail (crash not detected)"
444+ exit 1
445+ fi
446+ echo "Crash was correctly detected by the harness"
447+
448+ - name : Verify crash artifacts exist
449+ shell : bash
450+ run : |
451+ CRASH_DIR="apps/playground/.harness/crash-reports"
452+ if [ -d "$CRASH_DIR" ] && [ "$(ls -A "$CRASH_DIR" 2>/dev/null)" ]; then
453+ echo "Crash report artifacts found:"
454+ ls -la "$CRASH_DIR"
455+ else
456+ echo "ERROR: No crash report artifacts found in $CRASH_DIR"
457+ exit 1
458+ fi
0 commit comments