name: Build and upload iOS app on: push: branches: - release workflow_dispatch: jobs: ios: runs-on: macos-latest timeout-minutes: 120 steps: - name: Checkout repository uses: https://github.com/actions/checkout@v6 - name: Setup Ruby uses: ruby/setup-ruby@v1 with: ruby-version: '4.0.2' bundler-cache: true working-directory: fastlane - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: '22' cache: 'pnpm' - name: Install pnpm uses: pnpm/action-setup@v6 with: version: 10.33.0 - name: Install dependencies run: pnpm install --frozen-lockfile - name: Generate app assets run: pnpm assets - name: Build Nuxt app run: pnpm build - name: Sync to iOS run: npx cap sync ios - name: Setup Xcode uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: latest-stable - name: Set up App Store Connect API key env: APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }} APP_STORE_CONNECT_API_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }} run: | mkdir -p ~/.appstoreconnect/private_keys echo "$APP_STORE_CONNECT_API_KEY_CONTENT" | base64 --decode > ~/.appstoreconnect/private_keys/AuthKey_$APP_STORE_CONNECT_API_KEY_ID.p8 echo "Created API key file" - name: Import code signing certificate env: IOS_CERTIFICATE_BASE64: ${{ secrets.IOS_CERTIFICATE_BASE64 }} IOS_CERTIFICATE_PASSWORD: ${{ secrets.IOS_CERTIFICATE_PASSWORD }} IOS_PROVISIONING_PROFILE_BASE64: ${{ secrets.IOS_PROVISIONING_PROFILE_BASE64 }} run: | # Create temporary keychain KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db KEYCHAIN_PASSWORD=$(openssl rand -base64 32) security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH security set-keychain-settings -lut 21600 $KEYCHAIN_PATH security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH security list-keychains -d user -s $KEYCHAIN_PATH # Import certificate CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12 echo "$IOS_CERTIFICATE_BASE64" | base64 --decode > $CERTIFICATE_PATH security import $CERTIFICATE_PATH -P "$IOS_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 security list-keychain -d user -s $KEYCHAIN_PATH security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH # Import provisioning profile PROVISIONING_PROFILE_PATH=$RUNNER_TEMP/profile.mobileprovision echo "$IOS_PROVISIONING_PROFILE_BASE64" | base64 --decode > $PROVISIONING_PROFILE_PATH mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles cp $PROVISIONING_PROFILE_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ echo "Code signing setup complete" - name: Run Fastlane iOS release env: APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }} APP_STORE_CONNECT_API_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }} FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} FASTLANE_USER: ${{ secrets.FASTLANE_USER }} FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }} run: | cd fastlane bundle exec fastlane ios release working-directory: fastlane - name: Clean up keychain if: always() run: | KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db security delete-keychain $KEYCHAIN_PATH || true rm -rf ~/.appstoreconnect || true rm -rf ~/Library/MobileDevice/Provisioning\ Profiles/*.mobileprovision || true - name: Upload IPA artifact if: success() || failure() uses: actions/upload-artifact@v7 with: name: ios-app path: | fastlane/*.ipa fastlane/*.dSYM.zip retention-days: 30