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.
 
 
 
 
 
 

419 lines
12 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
# 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 ""
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 ""
}
# Function to parse iOS-specific arguments
parse_ios_args() {
for arg in "$@"; do
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
;;
-h|--help)
print_ios_usage
exit 0
;;
-v|--verbose)
set -x
;;
*)
log_warn "Unknown argument: $arg"
;;
esac
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_warning "App icon not found at assets/icon.png"
fi
if [ ! -f "assets/splash.png" ]; then
log_warning "Splash screen not found at assets/splash.png"
fi
# Check for iOS-specific files
if [ ! -f "ios/App/App/Info.plist" ]; then
log_warning "Info.plist not found"
fi
if [ ! -f "ios/App/App/AppDelegate.swift" ]; then
log_warning "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
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
npx cap 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"
# Setup application directories
setup_app_directories
# Load environment from .env file if it exists
load_env_file ".env"
# 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