1010 GH_CACHE_VERSION : v1 # Global cache version
1111 GH_GEMS_CACHE_VERSION : v1 # Ruby gems cache version
1212 # Performance optimizations
13- GRADLE_OPTS : -Dorg.gradle.daemon=false -Dorg.gradle. workers.max=4 -Dorg.gradle.parallel=true -Dorg.gradle.configureondemand =true -Dorg.gradle.caching=true
13+ GRADLE_OPTS : -Dorg.gradle.workers.max=4 -Dorg.gradle.parallel=true -Dorg.gradle.caching=true
1414 CI : true
1515 # Disable Maestro analytics in CI
1616 MAESTRO_CLI_NO_ANALYTICS : true
2929
3030jobs :
3131 e2e-android :
32- # TODO: The Android E2E test job is temporarily disabled due to a recurring
33- # Maestro driver timeout issue in the CI environment. The emulator becomes
34- # unresponsive, preventing Maestro from connecting. This needs further
35- # investigation, but has been disabled to unblock the pipeline.
36- # To test locally, run `./scripts/test-e2e-local.sh android --workflow-match`
37- if : false
32+ if : false # Temporarily disable Android E2E until emulator disk issue resolved
3833 concurrency :
3934 group : ${{ github.workflow }}-android-${{ github.ref }}
4035 cancel-in-progress : true
@@ -61,13 +56,13 @@ jobs:
6156 - run : corepack enable
6257 -
run :
corepack prepare [email protected] --activate 6358 - name : Cache Yarn dependencies
64- uses : actions/cache@v4
59+ uses : ./.github/ actions/cache-yarn
6560 with :
66- path : .yarn/cache
67- key : ${{ runner.os }}-node-${{ env.NODE_VERSION_SANITIZED }}-yarn-${{ hashFiles('**/yarn.lock') }}
68- restore-keys : |
69- ${{ runner.os }}-node-${{ env.NODE_VERSION_SANITIZED }}-yarn-
61+ cache-version : ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}
7062 - run : yarn install --immutable --silent
63+ - name : Validate Maestro test file
64+ run : |
65+ [ -f app/tests/e2e/launch.android.flow.yaml ] || { echo "❌ Android E2E test file missing"; exit 1; }
7166 - name : Cache Maestro
7267 id : cache-maestro
7368 uses : actions/cache@v4
@@ -90,42 +85,19 @@ jobs:
9085 uses : android-actions/setup-android@v3
9186 with :
9287 accept-android-sdk-licenses : true
93-
94- - name : Cache NDK
95- uses : actions/cache@v4
96- with :
97- path : ${{ env.ANDROID_HOME }}/ndk/${{ env.ANDROID_NDK_VERSION }}
98- key : ${{ runner.os }}-ndk-${{ env.ANDROID_NDK_VERSION }}
9988 - name : Install NDK
10089 run : sdkmanager "ndk;${{ env.ANDROID_NDK_VERSION }}"
10190 - name : Build dependencies (outside emulator)
10291 run : |
10392 echo "Building dependencies..."
10493 yarn workspace @selfxyz/mobile-app run build:deps --silent || { echo "❌ Dependency build failed"; exit 1; }
10594 echo "✅ Dependencies built successfully"
106- - name : Cache Android build
107- uses : actions/cache@v4
108- with :
109- path : |
110- app/android/app/build
111- app/android/.gradle
112- key : ${{ runner.os }}-android-build-${{ hashFiles('app/android/**/*.gradle*', 'app/android/gradle-wrapper.properties') }}
113- restore-keys : |
114- ${{ runner.os }}-android-build-
11595 - name : Build Android APK
116- uses : reactivecircus/android-emulator-runner@v2
117- with :
118- api-level : ${{ env.ANDROID_API_LEVEL }}
119- arch : x86_64
120- target : google_apis
121- force-avd-creation : false
122- emulator-options : -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -camera-front none -memory 8192 -cores 4 -accel on
123- disable-animations : true
124- script : |
125- echo "Building Android APK..."
126- chmod +x app/android/gradlew
127- (cd app/android && ./gradlew assembleRelease --quiet --parallel --build-cache --no-configuration-cache) || { echo "❌ Android build failed"; exit 1; }
128- echo "✅ Android build succeeded"
96+ run : |
97+ echo "Building Android APK..."
98+ chmod +x app/android/gradlew
99+ (cd app/android && ./gradlew assembleDebug --quiet --parallel --build-cache --no-configuration-cache) || { echo "❌ Android build failed"; exit 1; }
100+ echo "✅ Android build succeeded"
129101 - name : Install and Test on Android
130102 uses : reactivecircus/android-emulator-runner@v2
131103 with :
@@ -137,7 +109,7 @@ jobs:
137109 disable-animations : true
138110 script : |
139111 echo "Installing app on emulator..."
140- APK_PATH="app/android/app/build/outputs/apk/release /app-release .apk"
112+ APK_PATH="app/android/app/build/outputs/apk/debug /app-debug .apk"
141113 [ -f "$APK_PATH" ] || { echo "❌ APK not found at $APK_PATH"; exit 1; }
142114 adb install -r "$APK_PATH" || { echo "❌ App installation failed"; exit 1; }
143115 echo "✅ App installed successfully"
@@ -147,9 +119,7 @@ jobs:
147119
148120 echo "🎭 Running Maestro tests..."
149121 export MAESTRO_DRIVER_STARTUP_TIMEOUT=180000
150- maestro test tests/e2e/launch.android.flow.yaml --format junit --output app/maestro-results.xml
151- env :
152- E2E_BUILD : " true"
122+ maestro test app/tests/e2e/launch.android.flow.yaml --format junit --output app/maestro-results.xml
153123 - name : Upload test results
154124 if : always()
155125 uses : actions/upload-artifact@v4
@@ -191,13 +161,13 @@ jobs:
191161 - run : corepack enable
192162 -
run :
corepack prepare [email protected] --activate 193163 - name : Cache Yarn dependencies
194- uses : actions/cache@v4
164+ uses : ./.github/ actions/cache-yarn
195165 with :
196- path : .yarn/cache
197- key : ${{ runner.os }}-node-${{ env.NODE_VERSION_SANITIZED }}-yarn-${{ hashFiles('**/yarn.lock') }}
198- restore-keys : |
199- ${{ runner.os }}-node-${{ env.NODE_VERSION_SANITIZED }}-yarn-
166+ cache-version : ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}
200167 - run : yarn install --immutable --silent
168+ - name : Validate Maestro test file
169+ run : |
170+ [ -f app/tests/e2e/launch.ios.flow.yaml ] || { echo "❌ iOS E2E test file missing"; exit 1; }
201171 - name : Cache Maestro
202172 id : cache-maestro
203173 uses : actions/cache@v4
@@ -226,53 +196,27 @@ jobs:
226196 xcodebuild -version
227197 echo "Xcode path:"
228198 xcode-select -p
229- - name : Cache Node modules
230- uses : actions/cache@v4
231- with :
232- path : app/node_modules
233- key : ${{ runner.os }}-node-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('app/yarn.lock') }}
234- restore-keys : |
235- ${{ runner.os }}-node-${{ env.NODE_VERSION_SANITIZED }}-
236- - name : Cache Ruby gems
237- uses : ./.github/actions/cache-bundler
199+ - name : Set up Ruby
200+ uses : ruby/setup-ruby@v1
238201 with :
239- path : app/vendor/bundle
240- lock-file : app/Gemfile.lock
241- cache-version : ${{ env.GH_CACHE_VERSION }}-${{ env.GH_GEMS_CACHE_VERSION }}-ruby${{ env.RUBY_VERSION }}
202+ ruby-version : " 3.3 "
203+ bundler-cache : true
204+ working-directory : app
242205 - name : Cache Pods
243206 uses : ./.github/actions/cache-pods
244207 with :
245208 path : |
246209 app/ios/Pods
247210 ~/Library/Caches/CocoaPods
248211 lock-file : app/ios/Podfile.lock
249- - name : Cache Xcode build
250- uses : actions/cache@v4
251- with :
252- path : |
253- app/ios/build
254- ~/Library/Developer/Xcode/DerivedData
255- ~/Library/Caches/com.apple.dt.Xcode
256- key : ${{ runner.os }}-xcode-${{ hashFiles('app/ios/Podfile.lock') }}-${{ hashFiles('app/ios/${{ env.IOS_PROJECT_NAME }}.xcworkspace/contents.xcworkspacedata') }}
257- restore-keys : |
258- ${{ runner.os }}-xcode-${{ hashFiles('app/ios/Podfile.lock') }}-
259- ${{ runner.os }}-xcode-
260- - name : Cache Xcode Index
261- uses : actions/cache@v4
262- with :
263- path : app/ios/build/Index.noindex
264- key : ${{ runner.os }}-xcode-index-${{ hashFiles('app/ios/Podfile.lock') }}
265- restore-keys : |
266- ${{ runner.os }}-xcode-index-
267- - name : Cache iOS Simulator
212+ - name : Cache DerivedData
268213 uses : actions/cache@v4
269214 with :
270- path : |
271- ~/Library/Developer/CoreSimulator/Devices
272- ~/Library/Developer/Xcode/iOS DeviceSupport
273- key : ${{ runner.os }}-simulator-v1
215+ path : app/ios/build
216+ key : ${{ runner.os }}-derived-data-${{ env.XCODE_VERSION }}-${{ hashFiles('app/ios/Podfile.lock', 'app/ios/OpenPassport.xcworkspace/contents.xcworkspacedata', 'app/ios/Self.xcworkspace/contents.xcworkspacedata') }}
274217 restore-keys : |
275- ${{ runner.os }}-simulator-
218+ ${{ runner.os }}-derived-data-${{ env.XCODE_VERSION }}-${{ hashFiles('app/ios/Podfile.lock') }}-
219+ ${{ runner.os }}-derived-data-${{ env.XCODE_VERSION }}-
276220 - name : Verify iOS Runtime
277221 run : |
278222 echo "📱 Verifying iOS Runtime availability..."
@@ -286,8 +230,9 @@ jobs:
286230 - name : Install iOS dependencies
287231 run : |
288232 echo "Installing iOS dependencies..."
289- (cd app/ios && pod install --silent) || { echo "❌ Pod install failed"; exit 1; }
290- echo "✅ Pods installed successfully"
233+ cd app/ios
234+ echo "📦 Installing pods via centralized script…"
235+ BUNDLE_GEMFILE=../Gemfile bundle exec bash scripts/pod-install-with-cache-fix.sh || { echo "❌ Pod install failed"; exit 1; }
291236 - name : Setup iOS Simulator
292237 run : |
293238 echo "Setting up iOS Simulator..."
@@ -358,13 +303,29 @@ jobs:
358303 # Store simulator ID for later use
359304 echo "IOS_SIMULATOR_ID=$AVAILABLE_SIMULATOR" >> $GITHUB_ENV
360305 echo "IOS_SIMULATOR_NAME=$SIMULATOR_NAME" >> $GITHUB_ENV
306+ - name : Resolve iOS workspace
307+ run : |
308+ WORKSPACE_OPEN="app/ios/OpenPassport.xcworkspace"
309+ WORKSPACE_SELF="app/ios/Self.xcworkspace"
310+
311+ if xcodebuild -list -workspace "$WORKSPACE_OPEN" 2>/dev/null | grep -q "OpenPassport"; then
312+ WORKSPACE_PATH="$WORKSPACE_OPEN"
313+ else
314+ WORKSPACE_PATH="$WORKSPACE_SELF"
315+ fi
316+
317+ echo "WORKSPACE_PATH=$WORKSPACE_PATH" >> "$GITHUB_ENV"
318+ echo "Resolved workspace: $WORKSPACE_PATH"
361319 - name : Build iOS App
362320 run : |
363321 echo "Building iOS app..."
364322 echo "Project: ${{ env.IOS_PROJECT_NAME }}, Scheme: ${{ env.IOS_PROJECT_SCHEME }}"
365323
366324 # Verify workspace exists before building
367- WORKSPACE_PATH="app/ios/${{ env.IOS_PROJECT_NAME }}.xcworkspace"
325+ if [ -z "$WORKSPACE_PATH" ]; then
326+ echo "❌ WORKSPACE_PATH is not set"
327+ exit 1
328+ fi
368329 if [ ! -d "$WORKSPACE_PATH" ]; then
369330 echo "❌ Workspace not found at: $WORKSPACE_PATH"
370331 echo "Available workspaces:"
@@ -388,13 +349,15 @@ jobs:
388349 echo "✅ Using scheme: ${{ env.IOS_PROJECT_SCHEME }}"
389350
390351 # Use cached derived data and enable parallel builds for faster compilation
352+ # Additional flags disable indexing, restrict architecture, and use whole-module Swift compilation
391353 # Use the simulator that was set up earlier in the workflow
392- xcodebuild -workspace "$WORKSPACE_PATH" -scheme ${{ env.IOS_PROJECT_SCHEME }} -configuration Release -destination "id=${{ env.IOS_SIMULATOR_ID }}" -derivedDataPath app/ios/build -jobs "$(sysctl -n hw.ncpu)" -parallelizeTargets -quiet || { echo "❌ iOS build failed"; exit 1; }
354+ FORCE_BUNDLING=1 RCT_NO_LAUNCH_PACKAGER=1 \
355+ xcodebuild -workspace "$WORKSPACE_PATH" -scheme ${{ env.IOS_PROJECT_SCHEME }} -configuration Debug -destination "id=${{ env.IOS_SIMULATOR_ID }}" -derivedDataPath app/ios/build -jobs "$(sysctl -n hw.ncpu)" -parallelizeTargets -quiet COMPILER_INDEX_STORE_ENABLE=NO ONLY_ACTIVE_ARCH=YES SWIFT_COMPILATION_MODE=wholemodule || { echo "❌ iOS build failed"; exit 1; }
393356 echo "✅ iOS build succeeded"
394357 - name : Install and Test on iOS
395358 run : |
396359 echo "Installing app on simulator..."
397- APP_PATH=$(find app/ios/build/Build/Products/Release -iphonesimulator -name "*.app" | head -1)
360+ APP_PATH=$(find app/ios/build/Build/Products/Debug -iphonesimulator -name "*.app" | head -1)
398361 [ -z "$APP_PATH" ] && { echo "❌ Could not find built iOS app"; exit 1; }
399362 echo "Found app at: $APP_PATH"
400363
0 commit comments