@@ -17,28 +17,81 @@ permissions:
1717
1818jobs :
1919 test-e2e :
20- runs-on : macos-latest
21- # Skip E2E when MAESTRO_API_KEY secret is absent (fix for issue #915)
22- # The APK must be built before Maestro can test it.
23- if : ${{ secrets.MAESTRO_API_KEY != '' }}
20+ runs-on : ubuntu-latest
21+ # Skip E2E when secrets are absent
22+ if : ${{ secrets.MAESTRO_API_KEY != '' && secrets.EXPO_TOKEN != '' }}
2423 permissions :
2524 contents : read
25+ timeout-minutes : 30
2626 steps :
2727 - uses : actions/checkout@v4
28+
2829 - name : Setup Node.js
2930 uses : actions/setup-node@v4
3031 with :
3132 node-version : 20
33+ cache : ' npm'
34+
3235 - name : Install dependencies
3336 run : npm ci --prefer-offline --no-audit
34- - name : Build Android APK
35- run : npx expo build:android --type apk --non-interactive
37+
38+ - name : Build Android preview APK via EAS
39+ run : eas build --platform android --profile preview --non-interactive --no-wait
3640 env :
3741 EXPO_TOKEN : ${{ secrets.EXPO_TOKEN }}
38- - name : Install Maestro
42+ GIT_WORKAROUND : ' true'
43+
44+ - name : Wait for EAS build
45+ id : eas-build
46+ run : |
47+ BUILD_ID=$(eas build:list --platform android --limit 1 --json --non-interactive | jq -r '.[0].id')
48+ echo "build_id=$BUILD_ID" >> "$GITHUB_OUTPUT"
49+ echo "Waiting for EAS build $BUILD_ID to complete..."
50+ while true; do
51+ STATUS=$(eas build:view $BUILD_ID --json --non-interactive | jq -r '.status')
52+ if [ "$STATUS" = 'finished' ]; then
53+ echo "Build finished"
54+ break
55+ elif [ "$STATUS" = 'errored' ] || [ "$STATUS" = 'canceled' ]; then
56+ echo "Build failed with status: $STATUS"
57+ exit 1
58+ fi
59+ echo "Build status: $STATUS — waiting 60s..."
60+ sleep 60
61+ done
62+
63+ - name : Download APK artifact
64+ run : |
65+ BUILD_ID=${{ steps.eas-build.outputs.build_id }}
66+ eas build:download --id $BUILD_ID --platform android --path ./app.apk --non-interactive
67+
68+ - name : Install Maestro CLI
3969 run : curl -Ls "https://get.maestro.mobile.dev" | bash
40- - name : Run E2E tests
41- run : maestro cloud --api-key ${{ secrets.MAESTRO_API_KEY }} --app-file ./app.apk maestro/
70+
71+ - name : Run Maestro E2E tests
72+ run : |
73+ export PATH="$HOME/.maestro/bin:$PATH"
74+ maestro test maestro/ --format junit --output maestro-results.xml || MAESTRO_EXIT=$?
75+ echo "maestro_exit=$MAESTRO_EXIT" >> "$GITHUB_OUTPUT"
76+ exit 0 # Don't fail yet — upload artifacts first
77+ id : maestro
78+ continue-on-error : true
79+
80+ - name : Upload Maestro results
81+ if : always()
82+ uses : actions/upload-artifact@v4
83+ with :
84+ name : maestro-results
85+ path : |
86+ maestro-results.xml
87+ maestro/**/*.png
88+ retention-days : 14
89+
90+ - name : Fail if Maestro tests failed
91+ if : steps.maestro.outputs.maestro_exit != '0'
92+ run : |
93+ echo "Maestro E2E tests failed (exit code: ${{ steps.maestro.outputs.maestro_exit }})"
94+ exit 1
4295 ci :
4396 runs-on : ubuntu-latest
4497 permissions :
@@ -193,6 +246,9 @@ jobs:
193246 - name : Validate OpenAPI Spec
194247 run : npm run validate:openapi
195248
249+ - name : Run contract tests
250+ run : npm test -- --testPathPattern='openapi.contract|validation' --cache --cacheDirectory=.jest-cache
251+
196252 - name : Cache Expo build output
197253 uses : actions/cache@v4
198254 with :
0 commit comments