fix: 从 Xcode 项目中移除 SceneDelegate.swift 引用 #37
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: iOS/Mac - App Store Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| submit_for_review: | |
| description: 'Submit to App Store Review after upload' | |
| required: false | |
| default: false | |
| type: boolean | |
| env: | |
| FLUTTER_VERSION: '3.32.2' | |
| jobs: | |
| build-and-release-ios: | |
| name: Build and Release iOS to App Store | |
| runs-on: macos-14 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| channel: 'stable' | |
| cache: true | |
| - name: Get dependencies | |
| working-directory: opencli_mobile | |
| run: flutter pub get | |
| - name: Run code analysis | |
| working-directory: opencli_mobile | |
| run: flutter analyze --no-fatal-infos --no-fatal-warnings | |
| - name: Setup Xcode | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: latest-stable | |
| - name: Setup App Store Connect API Key | |
| env: | |
| APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} | |
| APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} | |
| APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} | |
| run: | | |
| mkdir -p ~/private_keys | |
| echo "$APP_STORE_CONNECT_API_KEY_BASE64" | base64 --decode > ~/private_keys/AuthKey_${APP_STORE_CONNECT_API_KEY_ID}.p8 | |
| chmod 600 ~/private_keys/AuthKey_${APP_STORE_CONNECT_API_KEY_ID}.p8 | |
| echo "✅ App Store Connect API Key configured" | |
| ls -lh ~/private_keys/ | |
| - name: Import Signing Certificate | |
| env: | |
| DISTRIBUTION_CERTIFICATE_BASE64: ${{ secrets.DISTRIBUTION_CERTIFICATE_BASE64 }} | |
| DISTRIBUTION_CERTIFICATE_PASSWORD: ${{ secrets.DISTRIBUTION_CERTIFICATE_PASSWORD }} | |
| KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} | |
| run: | | |
| # Create temporary keychain | |
| KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db | |
| 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 | |
| echo "$DISTRIBUTION_CERTIFICATE_BASE64" | base64 --decode > $RUNNER_TEMP/certificate.p12 | |
| security import $RUNNER_TEMP/certificate.p12 \ | |
| -P "$DISTRIBUTION_CERTIFICATE_PASSWORD" \ | |
| -A -t cert -f pkcs12 -k $KEYCHAIN_PATH | |
| security list-keychain -d user -s $KEYCHAIN_PATH | |
| # Allow codesign to access keychain | |
| security set-key-partition-list -S apple-tool:,apple:,codesign: \ | |
| -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
| echo "✅ Signing certificate imported" | |
| - name: Install Provisioning Profile | |
| env: | |
| PROVISIONING_PROFILE_BASE64: ${{ secrets.PROVISIONING_PROFILE_BASE64 }} | |
| run: | | |
| mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles | |
| # Install with UUID as filename for manual signing | |
| PP_UUID="77603a37-5393-4eee-a01a-bce52f4fa6b6" | |
| echo "$PROVISIONING_PROFILE_BASE64" | base64 --decode > ~/Library/MobileDevice/Provisioning\ Profiles/${PP_UUID}.mobileprovision | |
| echo "✅ Provisioning profile installed with UUID: $PP_UUID" | |
| ls -lh ~/Library/MobileDevice/Provisioning\ Profiles/ | |
| - name: Create ExportOptions.plist | |
| run: | | |
| cat > opencli_mobile/ios/ExportOptions.plist << 'EOF' | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| <plist version="1.0"> | |
| <dict> | |
| <key>method</key> | |
| <string>app-store</string> | |
| <key>uploadBitcode</key> | |
| <false/> | |
| <key>uploadSymbols</key> | |
| <true/> | |
| <key>signingStyle</key> | |
| <string>manual</string> | |
| <key>signingCertificate</key> | |
| <string>Apple Distribution</string> | |
| <key>teamID</key> | |
| <string>G9VG22HGJG</string> | |
| <key>provisioningProfiles</key> | |
| <dict> | |
| <key>com.opencli.opencliMobile</key> | |
| <string>OpenCLI Mobile App Store (opencliMobile)</string> | |
| </dict> | |
| </dict> | |
| </plist> | |
| EOF | |
| echo "✅ ExportOptions.plist created" | |
| cat opencli_mobile/ios/ExportOptions.plist | |
| - name: Install CocoaPods dependencies | |
| working-directory: opencli_mobile/ios | |
| run: | | |
| echo "📦 Installing CocoaPods dependencies..." | |
| pod install --repo-update | |
| echo "✅ CocoaPods dependencies installed" | |
| - name: Build IPA | |
| working-directory: opencli_mobile | |
| run: | | |
| echo "🔨 Building iOS IPA..." | |
| # Build using flutter - the installed certificate and provisioning profile | |
| # combined with ExportOptions.plist should be sufficient | |
| flutter build ipa --release \ | |
| --export-options-plist=ios/ExportOptions.plist | |
| echo "✅ IPA built successfully" | |
| ls -lh build/ios/ipa/ | |
| - name: Upload IPA Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ios-release-ipa | |
| path: opencli_mobile/build/ios/ipa/*.ipa | |
| retention-days: 30 | |
| - name: Upload to App Store Connect | |
| env: | |
| APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} | |
| APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} | |
| run: | | |
| IPA_PATH=$(find opencli_mobile/build/ios/ipa -name "*.ipa" | head -n 1) | |
| if [ -z "$IPA_PATH" ]; then | |
| echo "❌ IPA file not found" | |
| exit 1 | |
| fi | |
| echo "🚀 Uploading IPA to App Store Connect..." | |
| echo "📦 IPA path: $IPA_PATH" | |
| xcrun altool --upload-app \ | |
| --type ios \ | |
| --file "$IPA_PATH" \ | |
| --apiKey "$APP_STORE_CONNECT_API_KEY_ID" \ | |
| --apiIssuer "$APP_STORE_CONNECT_ISSUER_ID" \ | |
| --apiKeyPath ~/private_keys/AuthKey_${APP_STORE_CONNECT_API_KEY_ID}.p8 | |
| echo "✅ IPA uploaded successfully to App Store Connect!" | |
| - name: Cleanup Keychain | |
| if: always() | |
| run: | | |
| KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db | |
| if [ -f "$KEYCHAIN_PATH" ]; then | |
| security delete-keychain $KEYCHAIN_PATH | |
| echo "🧹 Keychain cleaned up" | |
| fi | |
| - name: Create GitHub Release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| files: opencli_mobile/build/ios/ipa/*.ipa | |
| generate_release_notes: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| notify: | |
| name: Notify on completion | |
| needs: build-and-release-ios | |
| runs-on: ubuntu-latest | |
| if: always() | |
| steps: | |
| - name: Send notification | |
| run: | | |
| if [ "${{ needs.build-and-release-ios.result }}" == "success" ]; then | |
| echo "✅ iOS release to App Store completed successfully!" | |
| else | |
| echo "❌ iOS release to App Store failed!" | |
| exit 1 | |
| fi |