diff --git a/.github/workflows/mobile-ci.yml b/.github/workflows/mobile-ci.yml index 56c8b0354..a10ac461f 100644 --- a/.github/workflows/mobile-ci.yml +++ b/.github/workflows/mobile-ci.yml @@ -4,6 +4,8 @@ env: # Node version is read from .nvmrc during workflow execution RUBY_VERSION: 3.2 JAVA_VERSION: 17 + ANDROID_NDK_VERSION: 27.0.11718014 + XCODE_VERSION: 16.4 # Path configuration WORKSPACE: ${{ github.workspace }} APP_PATH: ${{ github.workspace }}/app @@ -123,7 +125,27 @@ jobs: - name: Set up Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: "16.4" + xcode-version: ${{ env.XCODE_VERSION }} + - name: Configure Xcode path + run: | + echo "🔧 Configuring Xcode path to fix iOS SDK issues..." + # Fix for macOS 15 runner iOS SDK issues + # See: https://github.com/actions/runner-images/issues/12758 + sudo xcode-select --switch /Applications/Xcode_${{ env.XCODE_VERSION }}.app + echo "✅ Xcode path configured" + + # Verify Xcode setup + echo "Xcode version:" + xcodebuild -version + echo "Xcode path:" + xcode-select -p + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + bundler-cache: false + working-directory: ./app - uses: actions/checkout@v4 - name: Cache Node Modules @@ -178,15 +200,36 @@ jobs: key: ${{ runner.os }}-gradle-${{ hashFiles('app/android/**/gradle-wrapper.properties', 'app/android/**/gradle-wrapper.jar') }} restore-keys: | ${{ runner.os }}-gradle- + - name: Setup Java environment + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: ${{ env.JAVA_VERSION }} + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + with: + accept-android-sdk-licenses: true + - name: Cache NDK + uses: actions/cache@v4 + with: + path: ${{ env.ANDROID_HOME }}/ndk/${{ env.ANDROID_NDK_VERSION }} + key: ${{ runner.os }}-ndk-${{ env.ANDROID_NDK_VERSION }} + - name: Install NDK + run: sdkmanager "ndk;${{ env.ANDROID_NDK_VERSION }}" - name: Install Mobile Dependencies uses: ./.github/actions/yarn-install - name: Build Dependencies run: yarn build:deps working-directory: ./app + - name: Install Ruby Dependencies + run: | + echo "Installing Ruby dependencies..." + bundle config set --local path 'vendor/bundle' + bundle install --jobs 4 --retry 3 + working-directory: ./app - name: Install iOS Dependencies run: | echo "Installing iOS dependencies..." - cd app/ios # Clean Pods directory if it's corrupted or empty if [ ! -d "Pods" ] || [ -z "$(ls -A Pods 2>/dev/null)" ]; then @@ -214,10 +257,10 @@ jobs: fi echo "✅ iOS dependencies installed successfully" + working-directory: ./app/ios - name: Verify iOS Workspace run: | echo "Verifying iOS workspace setup..." - cd app/ios if [ ! -f "OpenPassport.xcworkspace/contents.xcworkspacedata" ]; then echo "❌ OpenPassport.xcworkspace is missing or corrupted" @@ -230,6 +273,7 @@ jobs: fi echo "✅ iOS workspace is properly configured" + working-directory: ./app/ios - name: Build iOS run: yarn ios working-directory: ./app diff --git a/.github/workflows/mobile-deploy.yml b/.github/workflows/mobile-deploy.yml index 9e062cc82..a8b92f84a 100644 --- a/.github/workflows/mobile-deploy.yml +++ b/.github/workflows/mobile-deploy.yml @@ -6,6 +6,7 @@ env: JAVA_VERSION: 17 ANDROID_API_LEVEL: 35 ANDROID_NDK_VERSION: 27.0.11718014 + XCODE_VERSION: 16.4 # Cache versioning - increment these to bust caches when needed GH_CACHE_VERSION: v1 # Global cache version @@ -119,7 +120,21 @@ jobs: if: inputs.platform != 'android' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: "16.4" + xcode-version: ${{ env.XCODE_VERSION }} + - name: Configure Xcode path + if: inputs.platform != 'android' + run: | + echo "🔧 Configuring Xcode path to fix iOS SDK issues..." + # Fix for macOS 15 runner iOS SDK issues + # See: https://github.com/actions/runner-images/issues/12758 + sudo xcode-select --switch /Applications/Xcode_${{ env.XCODE_VERSION }}.app + echo "✅ Xcode path configured" + + # Verify Xcode setup + echo "Xcode version:" + xcodebuild -version + echo "Xcode path:" + xcode-select -p - name: Cache Yarn dependencies id: yarn-cache diff --git a/.github/workflows/mobile-e2e.yml b/.github/workflows/mobile-e2e.yml index 2b8acc155..c2a28c06d 100644 --- a/.github/workflows/mobile-e2e.yml +++ b/.github/workflows/mobile-e2e.yml @@ -5,6 +5,7 @@ env: JAVA_VERSION: 17 ANDROID_API_LEVEL: 33 ANDROID_NDK_VERSION: 27.0.11718014 + XCODE_VERSION: 16.4 # Cache versions GH_CACHE_VERSION: v1 # Global cache version GH_GEMS_CACHE_VERSION: v1 # Ruby gems cache version @@ -163,6 +164,12 @@ jobs: concurrency: group: ${{ github.workflow }}-ios-${{ github.ref }} cancel-in-progress: true + env: + # iOS project configuration - hardcoded for E2E testing stability + # Note: During migration, project name is "Self" but scheme is still "OpenPassport" + # mobile-deploy.yml uses secrets for production deployment + IOS_PROJECT_NAME: "Self" + IOS_PROJECT_SCHEME: "OpenPassport" steps: - uses: actions/checkout@v4 - name: Read and sanitize Node.js version @@ -205,7 +212,20 @@ jobs: - name: Set up Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: "16.4" + xcode-version: ${{ env.XCODE_VERSION }} + - name: Configure Xcode path + run: | + echo "🔧 Configuring Xcode path to fix iOS SDK issues..." + # Fix for macOS 15 runner iOS SDK issues + # See: https://github.com/actions/runner-images/issues/12758 + sudo xcode-select --switch /Applications/Xcode_${{ env.XCODE_VERSION }}.app + echo "✅ Xcode path configured" + + # Verify Xcode setup + echo "Xcode version:" + xcodebuild -version + echo "Xcode path:" + xcode-select -p - name: Cache Node modules uses: actions/cache@v4 with: @@ -233,7 +253,7 @@ jobs: app/ios/build ~/Library/Developer/Xcode/DerivedData ~/Library/Caches/com.apple.dt.Xcode - key: ${{ runner.os }}-xcode-${{ hashFiles('app/ios/Podfile.lock') }}-${{ hashFiles('app/ios/OpenPassport.xcworkspace/contents.xcworkspacedata') }} + key: ${{ runner.os }}-xcode-${{ hashFiles('app/ios/Podfile.lock') }}-${{ hashFiles('app/ios/${{ env.IOS_PROJECT_NAME }}.xcworkspace/contents.xcworkspacedata') }} restore-keys: | ${{ runner.os }}-xcode-${{ hashFiles('app/ios/Podfile.lock') }}- ${{ runner.os }}-xcode- @@ -253,34 +273,11 @@ jobs: key: ${{ runner.os }}-simulator-v1 restore-keys: | ${{ runner.os }}-simulator- - - name: Install iOS Runtime + - name: Verify iOS Runtime run: | - echo "📱 Checking iOS Runtime availability..." - echo "Available iOS runtimes (JSON):" - xcrun simctl list -j runtimes || true - # Determine latest available iOS runtime identifier - if command -v jq >/dev/null 2>&1; then - RUNTIME_ID=$( - xcrun simctl list -j runtimes \ - | jq -r '.runtimes[] - | select(.platform=="iOS" and .isAvailable==true) - | .identifier' \ - | sort -V \ - | tail -1 - ) - else - # Fallback: parse human output (less reliable) - RUNTIME_ID=$( - xcrun simctl list runtimes \ - | awk '/iOS/ && /com.apple.CoreSimulator.SimRuntime.iOS-/ {print $NF}' \ - | tail -1 - ) - fi - if [ -n "$RUNTIME_ID" ] && [[ "$RUNTIME_ID" == com.apple.CoreSimulator.SimRuntime.iOS-* ]]; then - echo "✅ Latest iOS runtime: $RUNTIME_ID" - else - echo "⚠️ Could not determine an iOS runtime identifier" - fi + echo "📱 Verifying iOS Runtime availability..." + echo "Available iOS runtimes:" + xcrun simctl list runtimes | grep iOS - name: Build dependencies (outside main flow) run: | echo "Building dependencies..." @@ -323,11 +320,11 @@ jobs: if [ -z "$AVAILABLE_SIMULATOR" ]; then echo "❌ No available iPhone simulator found" echo "Creating a new iPhone SE (3rd generation) simulator..." - # Create a new iPhone SE (3rd generation) simulator with the latest iOS version - xcrun simctl create "iPhone SE (3rd generation)" "iPhone SE (3rd generation)" "iOS17.5" || { + # Create a new iPhone SE (3rd generation) simulator + xcrun simctl create "iPhone SE (3rd generation)" "iPhone SE (3rd generation)" || { echo "❌ Failed to create iPhone SE (3rd generation) simulator" echo "Trying to create any iPhone SE simulator..." - xcrun simctl create "iPhone SE" "iPhone SE" "iOS17.5" || { + xcrun simctl create "iPhone SE" "iPhone SE" || { echo "❌ Failed to create simulator" exit 1 } @@ -364,8 +361,35 @@ jobs: - name: Build iOS App run: | echo "Building iOS app..." + echo "Project: ${{ env.IOS_PROJECT_NAME }}, Scheme: ${{ env.IOS_PROJECT_SCHEME }}" + + # Verify workspace exists before building + WORKSPACE_PATH="app/ios/${{ env.IOS_PROJECT_NAME }}.xcworkspace" + if [ ! -d "$WORKSPACE_PATH" ]; then + echo "❌ Workspace not found at: $WORKSPACE_PATH" + echo "Available workspaces:" + find app/ios -name "*.xcworkspace" -type d + exit 1 + fi + + # Verify scheme exists by listing available schemes + echo "Verifying scheme availability..." + AVAILABLE_SCHEMES=$(xcodebuild -list -workspace "$WORKSPACE_PATH" 2>/dev/null | grep -A 200 "Schemes:" | grep -v "Schemes:" | xargs) + echo "Available schemes (first 20): $(echo $AVAILABLE_SCHEMES | cut -d' ' -f1-20)..." + + if [[ ! "$AVAILABLE_SCHEMES" =~ ${{ env.IOS_PROJECT_SCHEME }} ]]; then + echo "❌ Scheme '${{ env.IOS_PROJECT_SCHEME }}' not found" + echo "Full scheme list:" + xcodebuild -list -workspace "$WORKSPACE_PATH" 2>/dev/null | grep -A 200 "Schemes:" | grep -v "Schemes:" | head -50 + exit 1 + fi + + echo "✅ Using workspace: $WORKSPACE_PATH" + echo "✅ Using scheme: ${{ env.IOS_PROJECT_SCHEME }}" + # Use cached derived data and enable parallel builds for faster compilation - xcodebuild -workspace app/ios/OpenPassport.xcworkspace -scheme OpenPassport -configuration Release -sdk iphonesimulator -derivedDataPath app/ios/build -jobs "$(sysctl -n hw.ncpu)" -parallelizeTargets -quiet || { echo "❌ iOS build failed"; exit 1; } + # Use the simulator that was set up earlier in the workflow + 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; } echo "✅ iOS build succeeded" - name: Install and Test on iOS run: | diff --git a/common/package.json b/common/package.json index 76f016afc..1ed098232 100644 --- a/common/package.json +++ b/common/package.json @@ -362,6 +362,7 @@ }, "devDependencies": { "@types/js-sha1": "^0.6.3", + "@types/node": "^22.0.0", "@types/node-forge": "^1.3.10", "@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/parser": "^8.0.0", diff --git a/yarn.lock b/yarn.lock index 595256bdf..d1384bcd7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4933,6 +4933,7 @@ __metadata: "@openpassport/zk-kit-lean-imt": "npm:^0.0.6" "@openpassport/zk-kit-smt": "npm:^0.0.1" "@types/js-sha1": "npm:^0.6.3" + "@types/node": "npm:^22.0.0" "@types/node-forge": "npm:^1.3.10" "@typescript-eslint/eslint-plugin": "npm:^8.0.0" "@typescript-eslint/parser": "npm:^8.0.0"