# iOS Release Skill **Description**: Build and upload iOS apps to TestFlight for beta testing and App Store distribution. ## When to Use - Releasing new iOS beta builds - Submitting to the App Store - Setting up CI/CD for iOS - Managing iOS certificates and provisioning ## Prerequisites ### Required Tools ```bash # Install Xcode Command Line Tools xcode-select --install # Install full Xcode from Mac App Store (required for iOS builds) # Install CocoaPods brew install cocoapods ``` ### Apple Developer Account 1. Enroll in [Apple Developer Program](https://developer.apple.com/programs/) 2. Team ID: `748N7QPX7J` (example) 3. Bundle ID: `com.yourapp.yourapp` ## Fresh Setup ### 1. Configure Xcode ```bash # Open Xcode → Settings → Accounts → + → Apple ID # Sign in with your Apple Developer account # Xcode auto-downloads provisioning profiles and certificates ``` ### 2. Clone and Setup ```bash git clone https://github.com/your-org/your-repo.git cd your-repo/mobile_app/ios pod install cd ../.. ``` ## Build and Release Process ### 1. Update Build Number The build number must be unique for each upload: ```bash # Option 1: Let Cascade increment (recommended) # The build number is in project.pbxproj under CURRENT_PROJECT_VERSION # Option 2: Manual update open mobile_app/ios/YourApp.xcodeproj # Navigate to Target → General → Build # Increment Build number (not Version) ``` ### 2. Install Dependencies ```bash cd mobile_app/ios && pod install && cd ../.. ``` ### 3. Clean Build Folder ```bash xcodebuild clean \ -workspace mobile_app/ios/YourApp.xcworkspace \ -scheme YourApp \ -configuration Release ``` ### 4. Archive the App ```bash xcodebuild archive \ -workspace mobile_app/ios/YourApp.xcworkspace \ -scheme YourApp \ -configuration Release \ -archivePath build/YourApp.xcarchive \ -destination 'generic/platform=iOS' \ DEVELOPMENT_TEAM=YOUR_TEAM_ID \ CODE_SIGN_STYLE=Automatic ``` ### 5. Export and Upload ```bash xcodebuild -exportArchive \ -archivePath build/YourApp.xcarchive \ -exportPath build/export \ -exportOptionsPlist scripts/ExportOptions.plist ``` The `app-store-connect` export method auto-uploads to App Store Connect. ### 6. Configure in App Store Connect 1. Go to [App Store Connect](https://appstoreconnect.apple.com) 2. Navigate to My Apps → YourApp → TestFlight 3. Wait 5-15 minutes for processing 4. Add build to testing group: - **Internal Testing**: Available immediately - **External Testing**: Requires review (~24 hours) ## Alternative: Xcode GUI 1. Open `mobile_app/ios/YourApp.xcworkspace` (not `.xcodeproj`) 2. Select scheme: **YourApp** 3. Set destination: **Any iOS Device** 4. Product → Archive 5. In Organizer window: Distribute App → App Store Connect → Upload ## Key Configuration Files ### ExportOptions.plist ```xml method app-store-connect teamID YOUR_TEAM_ID uploadBitcode uploadSymbols ``` ### Podfile ```ruby platform :ios, '15.0' target 'YourApp' do use_frameworks! # Azure Speech SDK pod 'AzureSpeech', '~> 1.0' target 'YourAppTests' do inherit! :search_paths end end ``` ## Build Configuration | Setting | Value | Location | | ----------------- | --------------------- | ------------------------------- | | Team ID | `748N7QPX7J` | Xcode project settings | | Bundle ID | `com.yourapp.yourapp` | Xcode project settings | | Code Signing | Automatic | Target → Signing & Capabilities | | Deployment Target | iOS 15.0+ | Podfile/Xcode project | ## CI/CD Integration ### GitHub Actions ```yaml name: Build and Release iOS on: push: branches: [main] pull_request: branches: [main] jobs: build: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Setup Xcode uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: latest-stable - name: Install CocoaPods run: | cd mobile_app/ios pod install cd ../.. - name: Build Archive env: DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} run: | xcodebuild archive \ -workspace mobile_app/ios/YourApp.xcworkspace \ -scheme YourApp \ -configuration Release \ -archivePath build/YourApp.xcarchive \ -destination 'generic/platform=iOS' \ DEVELOPMENT_TEAM=$DEVELOPMENT_TEAM \ CODE_SIGN_STYLE=Automatic - name: Export and Upload env: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} run: | xcodebuild -exportArchive \ -archivePath build/YourApp.xcarchive \ -exportPath build/export \ -exportOptionsPlist scripts/ExportOptions.plist ``` ## Troubleshooting ### Common Issues and Solutions | Problem | Solution | | ----------------------------- | ------------------------------------------------------------------------ | | "No signing certificate" | Xcode → Settings → Accounts → Manage Certificates → + Apple Distribution | | "Provisioning profile" error | Xcode → Target → Signing → Enable "Automatically manage signing" | | "Build number already exists" | Increment build number in Xcode project | | Upload stuck at "Processing" | Check [Apple System Status](https://developer.apple.com/system-status/) | | "Invalid bundle" | Verify Bundle ID matches App Store Connect | | Pod install fails | Run `pod deintegrate` then `pod install` | | Archive fails | Clean build folder, check for linking errors | ### Debug Commands ```bash # Validate app before upload xcrun altool --validate-app \ -f build/export/YourApp.ipa \ -t ios \ -u your@email.com \ -p @keychain:AC_PASSWORD # Check upload status xcrun altool --notarization-info \ -u your@email.com \ -p @keychain:AC_PASSWORD # List available provisioning profiles ls ~/Library/MobileDevice/Provisioning\ Profiles/ ``` ## Best Practices ### Version Management - Use semantic versioning: `MAJOR.MINOR.PATCH` - Increment build number for every upload - Keep release notes in App Store Connect ### Testing Before Release 1. **Internal Testing** - Test with team first 2. **External Testing** - Select beta testers 3. **TestFlight Groups** - Organize testers by type 4. **Feedback Collection** - Use TestFlight feedback ### Release Checklist - [ ] Build number incremented - [ ] All tests passing - [ ] Release notes written - [ ] Screenshots updated (all device sizes) - [ ] App metadata current - [ ] Privacy policy updated - [ ] Age rating appropriate - [ ] In-app purchases configured (if applicable) ## App Store Submission ### From TestFlight to Production 1. Ensure TestFlight build is stable 2. Create new app version in App Store Connect 3. Select build from TestFlight 4. Complete app review information 5. Submit for Review ### Review Process - **Average time**: 24-48 hours - **Common rejections**: Metadata issues, crashes, guideline violations - **Expedited review**: Available for critical bug fixes ## Notes - **Always test on real devices** - Simulators can miss issues - **Keep certificates secure** - Never commit .p12 files - **Monitor expiration dates** - Certificates expire annually - **Use app-specific passwords** - For Apple ID authentication - **Backup provisioning profiles** - Export from Xcode ## Related Skills - [Generate Store Assets](./generate-store-assets.md) - Create required screenshots - [Mobile Code Quality](./mobile-code-quality.md) - Before release - [Desktop Release](./desktop-release.md) - Cross-platform releases - [Test iOS App](./test-ios-app.md) - Local testing