react-native-sop-docs/10-release-process/ios-release.md

12 KiB

iOS Release Process

Apple Developer Account Setup

Prerequisites

  1. Apple Developer Account ($99/year)
  2. Xcode (latest version)
  3. Valid certificates and provisioning profiles

App Store Connect Setup

  1. Create App Record

    • App name: Saayam
    • Bundle ID: com.saayam.app
    • SKU: unique identifier
    • Primary language: English
  2. App Information

    • Category: Social Networking / Lifestyle
    • Content rights
    • Age rating
    • App Review Information

Certificates & Provisioning

Certificate Types

# Development Certificate
# - Used for development and testing
# - Install on development devices

# Distribution Certificate
# - Used for App Store distribution
# - Required for production builds

Using Fastlane Match

# Initialize match
fastlane match init

# Generate development certificates
fastlane match development

# Generate App Store certificates
fastlane match appstore

# Generate Ad Hoc certificates (for testing)
fastlane match adhoc

Matchfile:

git_url("https://github.com/your-org/certificates")
storage_mode("git")
type("development")
app_identifier(["com.saayam.app"])
username("your-apple-id@example.com")
team_id("YOUR_TEAM_ID")

Manual Certificate Management

  1. Create Certificate Signing Request (CSR)

    • Open Keychain Access
    • Certificate Assistant → Request Certificate from Certificate Authority
    • Save CSR file
  2. Create Certificates in Developer Portal

    • iOS Development Certificate
    • iOS Distribution Certificate
  3. Create App ID

    • Bundle ID: com.saayam.app
    • Enable required capabilities (Push Notifications, etc.)
  4. Create Provisioning Profiles

    • Development Profile
    • App Store Distribution Profile

Xcode Configuration

Project Settings

Build Settings:

# Code Signing
CODE_SIGN_IDENTITY = "iPhone Distribution"
DEVELOPMENT_TEAM = "YOUR_TEAM_ID"
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.saayam.app"

# Build Configuration
ENABLE_BITCODE = YES
SWIFT_OPTIMIZATION_LEVEL = "-O"
GCC_OPTIMIZATION_LEVEL = "s"

# Deployment
IPHONEOS_DEPLOYMENT_TARGET = "12.0"
TARGETED_DEVICE_FAMILY = "1,2"  # iPhone and iPad

Info.plist Configuration

ios/SaayamApp/Info.plist:

<?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>CFBundleDisplayName</key>
    <string>Saayam</string>
    <key>CFBundleIdentifier</key>
    <string>com.saayam.app</string>
    <key>CFBundleVersion</key>
    <string>1</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0.0</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>UIRequiredDeviceCapabilities</key>
    <array>
        <string>armv7</string>
    </array>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
    </array>
    <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>This app needs access to location to show nearby fundraising requests.</string>
    <key>NSCameraUsageDescription</key>
    <string>This app needs access to camera to take photos for fundraising requests.</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>This app needs access to photo library to select images for fundraising requests.</string>
    <key>NSContactsUsageDescription</key>
    <string>This app needs access to contacts to help you share fundraising requests.</string>
</dict>
</plist>

Build Process

Manual Build

# Clean build folder
cd ios
rm -rf build/

# Install dependencies
pod install

# Build for device
xcodebuild -workspace SaayamApp.xcworkspace \
           -scheme SaayamApp \
           -configuration Release \
           -destination generic/platform=iOS \
           -archivePath $PWD/build/SaayamApp.xcarchive \
           archive

# Export IPA
xcodebuild -exportArchive \
           -archivePath $PWD/build/SaayamApp.xcarchive \
           -exportPath $PWD/build/ \
           -exportOptionsPlist ExportOptions.plist

Export Options

ios/ExportOptions.plist:

<?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>teamID</key>
    <string>YOUR_TEAM_ID</string>
    <key>uploadBitcode</key>
    <true/>
    <key>uploadSymbols</key>
    <true/>
    <key>compileBitcode</key>
    <true/>
    <key>provisioningProfiles</key>
    <dict>
        <key>com.saayam.app</key>
        <string>match AppStore com.saayam.app</string>
    </dict>
</dict>
</plist>

Fastlane Build

ios/fastlane/Fastfile:

default_platform(:ios)

platform :ios do
  desc "Build and upload to TestFlight"
  lane :beta do
    setup_ci if ENV['CI']
    
    # Sync certificates and provisioning profiles
    match(
      type: "appstore",
      readonly: true
    )
    
    # Increment build number
    increment_build_number(
      xcodeproj: "SaayamApp.xcodeproj"
    )
    
    # Build the app
    build_app(
      scheme: "SaayamApp",
      export_method: "app-store",
      export_options: {
        provisioningProfiles: {
          "com.saayam.app" => "match AppStore com.saayam.app"
        }
      }
    )
    
    # Upload to TestFlight
    upload_to_testflight(
      skip_waiting_for_build_processing: true,
      changelog: "Bug fixes and performance improvements"
    )
  end

  desc "Deploy to App Store"
  lane :release do
    setup_ci if ENV['CI']
    
    match(
      type: "appstore",
      readonly: true
    )
    
    build_app(
      scheme: "SaayamApp",
      export_method: "app-store"
    )
    
    upload_to_app_store(
      force: true,
      reject_if_possible: true,
      skip_metadata: false,
      skip_screenshots: false,
      submit_for_review: true,
      automatic_release: false,
      submission_information: {
        add_id_info_limits_tracking: true,
        add_id_info_serves_ads: false,
        add_id_info_tracks_action: true,
        add_id_info_tracks_install: true,
        add_id_info_uses_idfa: true,
        content_rights_has_rights: true,
        content_rights_contains_third_party_content: true,
        export_compliance_platform: 'ios',
        export_compliance_compliance_required: false,
        export_compliance_encryption_updated: false,
        export_compliance_uses_encryption: false,
        export_compliance_is_exempt: false
      }
    )
  end
end

Version Management

Automated Version Bumping

scripts/bump-ios-version.sh:

#!/bin/bash

VERSION_TYPE=${1:-patch}  # major, minor, patch
PLIST_PATH="ios/SaayamApp/Info.plist"

# Get current version
CURRENT_VERSION=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PLIST_PATH")
CURRENT_BUILD=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$PLIST_PATH")

echo "Current version: $CURRENT_VERSION ($CURRENT_BUILD)"

# Calculate new version
IFS='.' read -ra VERSION_PARTS <<< "$CURRENT_VERSION"
MAJOR=${VERSION_PARTS[0]}
MINOR=${VERSION_PARTS[1]}
PATCH=${VERSION_PARTS[2]}

case $VERSION_TYPE in
    major)
        MAJOR=$((MAJOR + 1))
        MINOR=0
        PATCH=0
        ;;
    minor)
        MINOR=$((MINOR + 1))
        PATCH=0
        ;;
    patch)
        PATCH=$((PATCH + 1))
        ;;
esac

NEW_VERSION="$MAJOR.$MINOR.$PATCH"
NEW_BUILD=$((CURRENT_BUILD + 1))

echo "New version: $NEW_VERSION ($NEW_BUILD)"

# Update Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $NEW_VERSION" "$PLIST_PATH"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $NEW_BUILD" "$PLIST_PATH"

# Update Xcode project
xcrun agvtool new-marketing-version $NEW_VERSION
xcrun agvtool new-version -all $NEW_BUILD

echo "Version updated successfully!"

TestFlight Distribution

Internal Testing

# Fastlane lane for internal testing
lane :internal do
  build_app(scheme: "SaayamApp")
  
  upload_to_testflight(
    groups: ["Internal Testers"],
    changelog: "Internal build for testing",
    distribute_external: false
  )
end

External Testing

# Fastlane lane for external testing
lane :external do
  build_app(scheme: "SaayamApp")
  
  upload_to_testflight(
    groups: ["Beta Testers"],
    changelog: "Beta version with new features",
    distribute_external: true,
    notify_external_testers: true
  )
end

App Store Submission

App Store Metadata

fastlane/metadata/en-US/:

name.txt                    # App name
subtitle.txt               # App subtitle
description.txt            # App description
keywords.txt               # App Store keywords
marketing_url.txt          # Marketing URL
support_url.txt           # Support URL
privacy_url.txt           # Privacy policy URL

description.txt:

Saayam is a revolutionary fundraising platform that connects donors with meaningful causes in their local community.

Key Features:
• Browse local fundraising requests
• Support NGOs and individual causes
• Track your donation impact
• Secure payment processing
• Real-time updates on funded projects

Join thousands of users making a difference in their communities. Download Saayam today and start supporting causes that matter to you.

Screenshots

# Generate screenshots using Fastlane
fastlane snapshot

# Upload screenshots
fastlane deliver --skip_binary_upload

Screenshotfile:

devices([
  "iPhone 14 Pro Max",
  "iPhone 14 Pro",
  "iPhone SE (3rd generation)",
  "iPad Pro (12.9-inch) (6th generation)"
])

languages([
  "en-US"
])

scheme("SaayamApp")

clear_previous_screenshots(true)

Release Checklist

Pre-Submission Checklist

  • Update version and build numbers
  • Test on multiple devices and iOS versions
  • Verify all app store metadata
  • Check app icons and screenshots
  • Test in-app purchases (if applicable)
  • Verify privacy policy and terms of service
  • Test deep linking
  • Check push notifications
  • Verify analytics integration
  • Test crash reporting

App Store Review Guidelines

  • App follows iOS Human Interface Guidelines
  • No crashes or major bugs
  • App provides value to users
  • Respects user privacy
  • Follows App Store Review Guidelines
  • Proper use of Apple APIs
  • Appropriate content rating
  • Valid contact information

Post-Submission

  • Monitor App Store Connect for review status
  • Respond to reviewer feedback if needed
  • Prepare for release day
  • Monitor crash reports and user feedback
  • Plan post-launch updates

Troubleshooting

Common Issues

# Certificate issues
# - Ensure certificates are valid and not expired
# - Check provisioning profile matches bundle ID
# - Verify team ID is correct

# Build issues
# - Clean build folder: rm -rf ios/build
# - Clean derived data: rm -rf ~/Library/Developer/Xcode/DerivedData
# - Reset CocoaPods: cd ios && pod deintegrate && pod install

# Archive issues
# - Check scheme is set to Release
# - Verify code signing settings
# - Ensure all dependencies are properly linked

Debugging Build Failures

# Verbose build output
xcodebuild -workspace SaayamApp.xcworkspace \
           -scheme SaayamApp \
           -configuration Release \
           -destination generic/platform=iOS \
           archive | xcpretty

# Check build settings
xcodebuild -workspace SaayamApp.xcworkspace \
           -scheme SaayamApp \
           -showBuildSettings