diff --git a/.github/workflows/ios-publish.yml b/.github/workflows/ios-publish.yml new file mode 100644 index 000000000..a82db0ea8 --- /dev/null +++ b/.github/workflows/ios-publish.yml @@ -0,0 +1,193 @@ +name: "iOS Publish" + +# Required GitHub Secrets: +# +# IOS_CERTIFICATE_BASE64 - Apple distribution certificate (.p12) encoded in base64 +# IOS_CERTIFICATE_PASSWORD - Password for the .p12 certificate +# IOS_PROVISION_PROFILE_BASE64 - App Store provisioning profile (.mobileprovision) encoded in base64 +# ASC_API_KEY_P8_BASE64 - App Store Connect API key (.p8) encoded in base64 +# ASC_API_KEY_ID - App Store Connect API Key ID +# ASC_ISSUER_ID - App Store Connect Issuer ID + +on: + workflow_dispatch: + +jobs: + prepare-assets: + name: Prepare iOS Assets + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get-version.outputs.version }} + + steps: + - uses: actions/checkout@v4 + + - name: Get version from package.json + id: get-version + run: | + VERSION=$(node -p "require('./package.json').version") + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Version: $VERSION" + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install dependencies + run: npm install + + - name: Install electron dependencies + run: | + pushd electron + npm install + popd + + - name: Init mobile submodule + run: | + git submodule init + git submodule update --remote "resources/mobile" + + - name: Build app assets + run: ./cmd appbuild publish + + - name: Upload iOS platform artifacts + uses: actions/upload-artifact@v4 + with: + name: ios-platform + path: resources/mobile/platforms/ios/ + retention-days: 1 + + build-ios: + name: Build & Submit iOS + needs: prepare-assets + runs-on: macos-15 + environment: build + + steps: + - uses: actions/checkout@v4 + + - name: Init mobile submodule + run: | + git submodule init + git submodule update --remote "resources/mobile" + + - name: Download prepared assets + uses: actions/download-artifact@v4 + with: + name: ios-platform + path: resources/mobile/platforms/ios/ + + - name: Select Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - name: Install CocoaPods + run: | + if [ -f "resources/mobile/platforms/ios/eeuiApp/Podfile" ]; then + cd resources/mobile/platforms/ios/eeuiApp + pod install + fi + + - name: Import signing certificate + env: + IOS_CERTIFICATE_BASE64: ${{ secrets.IOS_CERTIFICATE_BASE64 }} + IOS_CERTIFICATE_PASSWORD: ${{ secrets.IOS_CERTIFICATE_PASSWORD }} + run: | + # Create temporary keychain + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + KEYCHAIN_PASSWORD=$(openssl rand -hex 20) + + security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" + security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$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 \ + -k "$KEYCHAIN_PATH" + + security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + security list-keychain -d user -s "$KEYCHAIN_PATH" + + - name: Import provisioning profile + env: + IOS_PROVISION_PROFILE_BASE64: ${{ secrets.IOS_PROVISION_PROFILE_BASE64 }} + run: | + PROFILE_PATH=$RUNNER_TEMP/profile.mobileprovision + echo "$IOS_PROVISION_PROFILE_BASE64" | base64 --decode > "$PROFILE_PATH" + + mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles + cp "$PROFILE_PATH" ~/Library/MobileDevice/Provisioning\ Profiles/ + + - name: Build archive + run: | + cd resources/mobile/platforms/ios/eeuiApp + xcodebuild archive \ + -workspace eeuiApp.xcworkspace \ + -scheme eeuiApp \ + -configuration Release \ + -archivePath $RUNNER_TEMP/eeuiApp.xcarchive \ + -allowProvisioningUpdates \ + CODE_SIGN_STYLE=Manual \ + | xcpretty + + - name: Export IPA + run: | + cd resources/mobile/platforms/ios/eeuiApp + + # Generate ExportOptions.plist + cat > $RUNNER_TEMP/ExportOptions.plist << 'PLIST' + + + + + method + app-store + uploadBitcode + + uploadSymbols + + + + PLIST + + xcodebuild -exportArchive \ + -archivePath $RUNNER_TEMP/eeuiApp.xcarchive \ + -exportOptionsPlist $RUNNER_TEMP/ExportOptions.plist \ + -exportPath $RUNNER_TEMP/ipa-output \ + -allowProvisioningUpdates \ + | xcpretty + + - name: Submit to App Store Connect + env: + ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }} + ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }} + ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }} + run: | + # Prepare API key + mkdir -p ~/private_keys + echo "$ASC_API_KEY_P8_BASE64" | base64 --decode > ~/private_keys/AuthKey_${ASC_API_KEY_ID}.p8 + + # Find and upload IPA + IPA_PATH=$(find $RUNNER_TEMP/ipa-output -name "*.ipa" | head -1) + echo "Uploading: $IPA_PATH" + + xcrun altool --upload-app \ + -f "$IPA_PATH" \ + --type ios \ + --apiKey "$ASC_API_KEY_ID" \ + --apiIssuer "$ASC_ISSUER_ID" + + - name: Clean up + if: always() + run: | + security delete-keychain $RUNNER_TEMP/app-signing.keychain-db 2>/dev/null || true + rm -f $RUNNER_TEMP/certificate.p12 + rm -f $RUNNER_TEMP/profile.mobileprovision + rm -rf ~/private_keys