You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							459 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							459 lines
						
					
					
						
							13 KiB
						
					
					
				
								#!/bin/bash
							 | 
						|
								
							 | 
						|
								# build-ios.sh
							 | 
						|
								# Author: Matthew Raymer
							 | 
						|
								# Description: iOS build script for TimeSafari application
							 | 
						|
								# Date: 2025-07-11
							 | 
						|
								
							 | 
						|
								# Exit on any error
							 | 
						|
								set -e
							 | 
						|
								
							 | 
						|
								# Source common utilities
							 | 
						|
								source "$(dirname "$0")/common.sh"
							 | 
						|
								
							 | 
						|
								# Default values
							 | 
						|
								BUILD_MODE="development"
							 | 
						|
								BUILD_TYPE="debug"
							 | 
						|
								OPEN_STUDIO=false
							 | 
						|
								BUILD_IPA=false
							 | 
						|
								BUILD_APP=false
							 | 
						|
								CLEAN_ONLY=false
							 | 
						|
								SYNC_ONLY=false
							 | 
						|
								ASSETS_ONLY=false
							 | 
						|
								DEPLOY_APP=false
							 | 
						|
								AUTO_RUN=false
							 | 
						|
								CUSTOM_API_IP=""
							 | 
						|
								
							 | 
						|
								# Function to print iOS-specific usage
							 | 
						|
								print_ios_usage() {
							 | 
						|
								    echo "Usage: $0 [options]"
							 | 
						|
								    echo ""
							 | 
						|
								    echo "iOS Build Options:"
							 | 
						|
								    echo "  --dev, --development    Build for development environment"
							 | 
						|
								    echo "  --test                  Build for testing environment"
							 | 
						|
								    echo "  --prod, --production    Build for production environment"
							 | 
						|
								    echo "  --debug                 Build debug app (default)"
							 | 
						|
								    echo "  --release               Build release app"
							 | 
						|
								    echo "  --studio                Open Xcode after build"
							 | 
						|
								    echo "  --ipa                   Build IPA file"
							 | 
						|
								    echo "  --app                   Build app bundle"
							 | 
						|
								    echo "  --clean                 Clean build artifacts only"
							 | 
						|
								    echo "  --sync                  Sync Capacitor only"
							 | 
						|
								    echo "  --assets                Generate assets only"
							 | 
						|
								    echo "  --deploy                Deploy app to connected device"
							 | 
						|
								    echo "  --auto-run              Auto-run app after build"
							 | 
						|
								    echo "  --api-ip <ip>          Custom IP address for claim API (uses Capacitor default)"
							 | 
						|
								    echo ""
							 | 
						|
								    echo "Common Options:"
							 | 
						|
								    echo "  -h, --help             Show this help message"
							 | 
						|
								    echo "  -v, --verbose          Enable verbose logging"
							 | 
						|
								    echo ""
							 | 
						|
								    echo "Examples:"
							 | 
						|
								    echo "  $0 --dev --studio      # Development build + open Xcode"
							 | 
						|
								    echo "  $0 --prod --ipa        # Production IPA build"
							 | 
						|
								    echo "  $0 --test --app        # Testing app build"
							 | 
						|
								    echo "  $0 --test --auto-run   # Test build + auto-run"
							 | 
						|
								    echo "  $0 --clean             # Clean only"
							 | 
						|
								    echo "  $0 --sync              # Sync only"
							 | 
						|
								    echo "  $0 --deploy            # Build and deploy to device"
							 | 
						|
								    echo "  $0 --dev                    # Dev build with Capacitor default"
							 | 
						|
								    echo "  $0 --dev --api-ip 192.168.1.100  # Dev build with custom API IP"
							 | 
						|
								    echo ""
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to parse iOS-specific arguments
							 | 
						|
								parse_ios_args() {
							 | 
						|
								    local args=("$@")
							 | 
						|
								    local i=0
							 | 
						|
								    
							 | 
						|
								    while [ $i -lt ${#args[@]} ]; do
							 | 
						|
								        local arg="${args[$i]}"
							 | 
						|
								        
							 | 
						|
								        case $arg in
							 | 
						|
								            --dev|--development)
							 | 
						|
								                BUILD_MODE="development"
							 | 
						|
								                ;;
							 | 
						|
								            --test)
							 | 
						|
								                BUILD_MODE="test"
							 | 
						|
								                ;;
							 | 
						|
								            --prod|--production)
							 | 
						|
								                BUILD_MODE="production"
							 | 
						|
								                ;;
							 | 
						|
								            --debug)
							 | 
						|
								                BUILD_TYPE="debug"
							 | 
						|
								                ;;
							 | 
						|
								            --release)
							 | 
						|
								                BUILD_TYPE="release"
							 | 
						|
								                ;;
							 | 
						|
								            --studio)
							 | 
						|
								                OPEN_STUDIO=true
							 | 
						|
								                ;;
							 | 
						|
								            --ipa)
							 | 
						|
								                BUILD_IPA=true
							 | 
						|
								                ;;
							 | 
						|
								            --app)
							 | 
						|
								                BUILD_APP=true
							 | 
						|
								                ;;
							 | 
						|
								            --clean)
							 | 
						|
								                CLEAN_ONLY=true
							 | 
						|
								                ;;
							 | 
						|
								            --sync)
							 | 
						|
								                SYNC_ONLY=true
							 | 
						|
								                ;;
							 | 
						|
								            --assets)
							 | 
						|
								                ASSETS_ONLY=true
							 | 
						|
								                ;;
							 | 
						|
								            --deploy)
							 | 
						|
								                DEPLOY_APP=true
							 | 
						|
								                ;;
							 | 
						|
								            --auto-run)
							 | 
						|
								                AUTO_RUN=true
							 | 
						|
								                ;;
							 | 
						|
								            --api-ip)
							 | 
						|
								                if [ $((i + 1)) -lt ${#args[@]} ]; then
							 | 
						|
								                    CUSTOM_API_IP="${args[$((i + 1))]}"
							 | 
						|
								                    i=$((i + 1))  # Skip the next argument
							 | 
						|
								                else
							 | 
						|
								                    log_error "Error: --api-ip requires an IP address"
							 | 
						|
								                    exit 1
							 | 
						|
								                fi
							 | 
						|
								                ;;
							 | 
						|
								            --api-ip=*)
							 | 
						|
								                CUSTOM_API_IP="${arg#*=}"
							 | 
						|
								                ;;
							 | 
						|
								            -h|--help)
							 | 
						|
								                print_ios_usage
							 | 
						|
								                exit 0
							 | 
						|
								                ;;
							 | 
						|
								            -v|--verbose)
							 | 
						|
								                set -x
							 | 
						|
								                ;;
							 | 
						|
								            *)
							 | 
						|
								                log_warn "Unknown argument: $arg"
							 | 
						|
								                ;;
							 | 
						|
								        esac
							 | 
						|
								        i=$((i + 1))
							 | 
						|
								    done
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to validate iOS environment
							 | 
						|
								validate_ios_environment() {
							 | 
						|
								    log_info "Validating iOS build environment..."
							 | 
						|
								    
							 | 
						|
								    # Check for Xcode
							 | 
						|
								    if ! command -v xcodebuild &> /dev/null; then
							 | 
						|
								        log_error "Xcode not found. Please install Xcode and command line tools."
							 | 
						|
								        exit 1
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Check for iOS Simulator
							 | 
						|
								    if ! command -v xcrun &> /dev/null; then
							 | 
						|
								        log_error "Xcode command line tools not found. Please install with: xcode-select --install"
							 | 
						|
								        exit 1
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Check for Capacitor
							 | 
						|
								    if ! command -v npx &> /dev/null; then
							 | 
						|
								        log_error "npx not found. Please install Node.js and npm."
							 | 
						|
								        exit 1
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Check for iOS platform
							 | 
						|
								    if [ ! -d "ios" ]; then
							 | 
						|
								        log_error "iOS platform not found. Please run: npx cap add ios"
							 | 
						|
								        exit 1
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_success "iOS build environment validated"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to check iOS resources
							 | 
						|
								check_ios_resources() {
							 | 
						|
								    log_info "Checking iOS resources..."
							 | 
						|
								    
							 | 
						|
								    # Check for required assets
							 | 
						|
								    if [ ! -f "assets/icon.png" ]; then
							 | 
						|
								        log_warn "App icon not found at assets/icon.png"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    if [ ! -f "assets/splash.png" ]; then
							 | 
						|
								        log_warn "Splash screen not found at assets/splash.png"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Check for iOS-specific files
							 | 
						|
								    if [ ! -f "ios/App/App/Info.plist" ]; then
							 | 
						|
								        log_warn "Info.plist not found"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    if [ ! -f "ios/App/App/AppDelegate.swift" ]; then
							 | 
						|
								        log_warn "AppDelegate.swift not found"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_success "iOS resource check completed"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to clean iOS build
							 | 
						|
								clean_ios_build() {
							 | 
						|
								    log_info "Cleaning iOS build artifacts..."
							 | 
						|
								    
							 | 
						|
								    # Clean Xcode build (temporary output directory)
							 | 
						|
								    if [ -d "ios/App/build" ]; then
							 | 
						|
								        rm -rf ios/App/build/
							 | 
						|
								        log_debug "Cleaned ios/App/build/"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Clean DerivedData
							 | 
						|
								    if [ -d "ios/App/DerivedData" ]; then
							 | 
						|
								        rm -rf ios/App/DerivedData/
							 | 
						|
								        log_debug "Cleaned ios/App/DerivedData/"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Clean Capacitor (using npm script instead of invalid cap clean command)
							 | 
						|
								    npm run clean:ios || true
							 | 
						|
								    
							 | 
						|
								    log_success "iOS build cleaned"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to build iOS app
							 | 
						|
								build_ios_app() {
							 | 
						|
								    local build_config=""
							 | 
						|
								    local scheme="App"
							 | 
						|
								    local destination=""
							 | 
						|
								    
							 | 
						|
								    if [ "$BUILD_TYPE" = "debug" ]; then
							 | 
						|
								        build_config="Debug"
							 | 
						|
								        destination="platform=iOS Simulator,name=iPhone 15 Pro"
							 | 
						|
								    else
							 | 
						|
								        build_config="Release"
							 | 
						|
								        destination="platform=iOS,id=auto"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_info "Building iOS app (${build_config})..."
							 | 
						|
								    
							 | 
						|
								    cd ios/App
							 | 
						|
								    
							 | 
						|
								    # Build the app
							 | 
						|
								    xcodebuild -workspace App.xcworkspace \
							 | 
						|
								               -scheme "$scheme" \
							 | 
						|
								               -configuration "$build_config" \
							 | 
						|
								               -destination "$destination" \
							 | 
						|
								               build \
							 | 
						|
								               CODE_SIGN_IDENTITY="" \
							 | 
						|
								               CODE_SIGNING_REQUIRED=NO \
							 | 
						|
								               CODE_SIGNING_ALLOWED=NO
							 | 
						|
								    
							 | 
						|
								    cd ../..
							 | 
						|
								    
							 | 
						|
								    log_success "iOS app built successfully"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to deploy to device
							 | 
						|
								deploy_ios_app() {
							 | 
						|
								    log_info "Deploy-app mode: building app and deploying to device"
							 | 
						|
								    
							 | 
						|
								    # Check for connected device
							 | 
						|
								    local devices=$(xcrun devicectl list devices --json | grep -c '"state":"booted"' || echo "0")
							 | 
						|
								    if [ "$devices" -eq 0 ]; then
							 | 
						|
								        log_error "No iOS device connected. Please connect a device and try again."
							 | 
						|
								        exit 1
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Build app for device
							 | 
						|
								    BUILD_TYPE="debug"
							 | 
						|
								    build_ios_app
							 | 
						|
								    
							 | 
						|
								    # Get device ID
							 | 
						|
								    local device_id=$(xcrun devicectl list devices --json | grep -o '"identifier":"[^"]*"' | head -1 | cut -d'"' -f4)
							 | 
						|
								    
							 | 
						|
								    if [ -z "$device_id" ]; then
							 | 
						|
								        log_error "Could not find device ID. Please ensure device is connected and unlocked."
							 | 
						|
								        exit 1
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Install app on device
							 | 
						|
								    log_info "Installing app on device..."
							 | 
						|
								    xcrun devicectl device install app --device "$device_id" ios/App/build/Debug-iphoneos/App.app
							 | 
						|
								    
							 | 
						|
								    log_success "iOS app deployed successfully to device!"
							 | 
						|
								    log_info "You can now run the app with: npx cap run ios"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to auto-run iOS app
							 | 
						|
								auto_run_ios_app() {
							 | 
						|
								    log_step "Auto-running iOS app..."
							 | 
						|
								    
							 | 
						|
								    # Check if we're in debug mode (simulator) or release mode (device)
							 | 
						|
								    if [ "$BUILD_TYPE" = "debug" ]; then
							 | 
						|
								        log_info "Launching iOS Simulator and installing app"
							 | 
						|
								        safe_execute "Launching app" "npx cap run ios" || {
							 | 
						|
								            log_error "Failed to launch iOS app on simulator"
							 | 
						|
								            return 1
							 | 
						|
								        }
							 | 
						|
								    else
							 | 
						|
								        log_info "Building and installing on real device"
							 | 
						|
								        # For release builds, we need to use a different approach
							 | 
						|
								        # since npx cap run ios is primarily for simulators
							 | 
						|
								        log_warn "Auto-run for release builds requires manual device setup"
							 | 
						|
								        log_info "Please use Xcode to run the app on your device"
							 | 
						|
								        return 1
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_success "iOS app launched successfully!"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Parse command line arguments
							 | 
						|
								parse_ios_args "$@"
							 | 
						|
								
							 | 
						|
								# Print build header
							 | 
						|
								print_header "TimeSafari iOS Build Process"
							 | 
						|
								log_info "Starting iOS build process at $(date)"
							 | 
						|
								log_info "Build mode: $BUILD_MODE"
							 | 
						|
								log_info "Build type: $BUILD_TYPE"
							 | 
						|
								
							 | 
						|
								# Setup environment for Capacitor build
							 | 
						|
								setup_build_env "capacitor" "$BUILD_MODE"
							 | 
						|
								
							 | 
						|
								# Override API servers for iOS development when custom IP is specified
							 | 
						|
								if [ "$BUILD_MODE" = "development" ] && [ -n "$CUSTOM_API_IP" ]; then
							 | 
						|
								    # Use custom IP for physical device development
							 | 
						|
								    export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000"
							 | 
						|
								    export VITE_DEFAULT_PARTNER_API_SERVER="http://${CUSTOM_API_IP}:3000"
							 | 
						|
								    log_info "iOS development mode: Using custom IP ${CUSTOM_API_IP} for physical device"
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Setup application directories
							 | 
						|
								setup_app_directories
							 | 
						|
								
							 | 
						|
								# Load environment-specific .env file if it exists
							 | 
						|
								env_file=".env.$BUILD_MODE"
							 | 
						|
								if [ -f "$env_file" ]; then
							 | 
						|
								    load_env_file "$env_file"
							 | 
						|
								else
							 | 
						|
								    log_debug "No $env_file file found, using default environment"
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Load .env file if it exists (fallback)
							 | 
						|
								if [ -f ".env" ]; then
							 | 
						|
								    load_env_file ".env"
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Validate iOS environment
							 | 
						|
								validate_ios_environment
							 | 
						|
								
							 | 
						|
								# Handle clean-only mode
							 | 
						|
								if [ "$CLEAN_ONLY" = true ]; then
							 | 
						|
								    log_info "Clean-only mode: cleaning build artifacts"
							 | 
						|
								    clean_ios_build
							 | 
						|
								    safe_execute "Cleaning dist directory" "clean_build_artifacts dist" || exit 1
							 | 
						|
								    log_success "Clean completed successfully!"
							 | 
						|
								    exit 0
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Handle sync-only mode
							 | 
						|
								if [ "$SYNC_ONLY" = true ]; then
							 | 
						|
								    log_info "Sync-only mode: syncing with Capacitor"
							 | 
						|
								    safe_execute "Syncing with Capacitor" "npx cap sync ios" || exit 6
							 | 
						|
								    log_success "Sync completed successfully!"
							 | 
						|
								    exit 0
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Handle assets-only mode
							 | 
						|
								if [ "$ASSETS_ONLY" = true ]; then
							 | 
						|
								    log_info "Assets-only mode: generating assets"
							 | 
						|
								    safe_execute "Generating assets" "npx capacitor-assets generate --ios" || exit 7
							 | 
						|
								    log_success "Assets generation completed successfully!"
							 | 
						|
								    exit 0
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Handle deploy-app mode
							 | 
						|
								if [ "$DEPLOY_APP" = true ]; then
							 | 
						|
								    deploy_ios_app
							 | 
						|
								    exit 0
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Step 1: Check iOS resources
							 | 
						|
								check_ios_resources
							 | 
						|
								
							 | 
						|
								# Step 2: Clean iOS build
							 | 
						|
								safe_execute "Cleaning iOS build" "clean_ios_build" || exit 1
							 | 
						|
								
							 | 
						|
								# Step 3: Clean dist directory
							 | 
						|
								log_info "Cleaning dist directory..."
							 | 
						|
								clean_build_artifacts "dist"
							 | 
						|
								
							 | 
						|
								# Step 4: Build Capacitor version with mode
							 | 
						|
								if [ "$BUILD_MODE" = "development" ]; then
							 | 
						|
								    safe_execute "Building Capacitor version (development)" "npm run build:capacitor" || exit 3
							 | 
						|
								elif [ "$BUILD_MODE" = "test" ]; then
							 | 
						|
								    safe_execute "Building Capacitor version (test)" "npm run build:capacitor -- --mode test" || exit 3
							 | 
						|
								elif [ "$BUILD_MODE" = "production" ]; then
							 | 
						|
								    safe_execute "Building Capacitor version (production)" "npm run build:capacitor -- --mode production" || exit 3
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Step 5: Sync with Capacitor
							 | 
						|
								safe_execute "Syncing with Capacitor" "npx cap sync ios" || exit 6
							 | 
						|
								
							 | 
						|
								# Step 6: Generate assets
							 | 
						|
								safe_execute "Generating assets" "npx capacitor-assets generate --ios" || exit 7
							 | 
						|
								
							 | 
						|
								# Step 7: Build iOS app
							 | 
						|
								safe_execute "Building iOS app" "build_ios_app" || exit 5
							 | 
						|
								
							 | 
						|
								# Step 8: Build IPA/App if requested
							 | 
						|
								if [ "$BUILD_IPA" = true ]; then
							 | 
						|
								    log_info "Building IPA package..."
							 | 
						|
								    cd ios/App
							 | 
						|
								    xcodebuild -workspace App.xcworkspace \
							 | 
						|
								               -scheme App \
							 | 
						|
								               -configuration Release \
							 | 
						|
								               -archivePath build/App.xcarchive \
							 | 
						|
								               archive \
							 | 
						|
								               CODE_SIGN_IDENTITY="" \
							 | 
						|
								               CODE_SIGNING_REQUIRED=NO \
							 | 
						|
								               CODE_SIGNING_ALLOWED=NO
							 | 
						|
								    
							 | 
						|
								    xcodebuild -exportArchive \
							 | 
						|
								               -archivePath build/App.xcarchive \
							 | 
						|
								               -exportPath build/ \
							 | 
						|
								               -exportOptionsPlist exportOptions.plist
							 | 
						|
								    cd ../..
							 | 
						|
								    log_success "IPA package built successfully"
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								if [ "$BUILD_APP" = true ]; then
							 | 
						|
								    log_info "Building app bundle..."
							 | 
						|
								    # App bundle is already built in step 7
							 | 
						|
								    log_success "App bundle built successfully"
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Step 9: Auto-run app if requested
							 | 
						|
								if [ "$AUTO_RUN" = true ]; then
							 | 
						|
								    safe_execute "Auto-running iOS app" "auto_run_ios_app" || exit 9
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Step 10: Open Xcode if requested
							 | 
						|
								if [ "$OPEN_STUDIO" = true ]; then
							 | 
						|
								    safe_execute "Opening Xcode" "npx cap open ios" || exit 8
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								# Print build summary
							 | 
						|
								log_success "iOS build completed successfully!"
							 | 
						|
								log_info "Build mode: $BUILD_MODE"
							 | 
						|
								log_info "Build type: $BUILD_TYPE"
							 | 
						|
								if [ "$BUILD_IPA" = true ]; then
							 | 
						|
								    log_info "IPA build: completed"
							 | 
						|
								fi
							 | 
						|
								if [ "$BUILD_APP" = true ]; then
							 | 
						|
								    log_info "App build: completed"
							 | 
						|
								fi
							 | 
						|
								if [ "$AUTO_RUN" = true ]; then
							 | 
						|
								    log_info "Auto-run: completed"
							 | 
						|
								fi
							 | 
						|
								if [ "$OPEN_STUDIO" = true ]; then
							 | 
						|
								    log_info "Xcode: opened"
							 | 
						|
								fi
							 | 
						|
								
							 | 
						|
								print_footer "iOS Build"
							 | 
						|
								
							 | 
						|
								# Exit with success
							 | 
						|
								exit 0 
							 |