diff --git a/BUILDING.md b/BUILDING.md index 04531f01..cde074d3 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -316,6 +316,36 @@ npm run build:electron-prod && npm run electron:start Prerequisites: macOS with Xcode installed +#### Automated Build Script + +The recommended way to build for iOS is using the automated build script: + +```bash +# Standard build and open Xcode +./scripts/build-ios.sh + +# Build with specific version numbers +./scripts/build-ios.sh --version 1.0.3 --build-number 35 + +# Build without opening Xcode (for CI/CD) +./scripts/build-ios.sh --no-xcode + +# Show all available options +./scripts/build-ios.sh --help +``` + +The script handles all the necessary steps including: +- Environment setup and validation +- Web asset building +- Capacitor synchronization +- iOS asset generation +- Version number updates +- Xcode project opening + +#### Manual Build Process + +If you need to build manually or want to understand the individual steps: + #### First-time iOS Configuration - Generate certificates inside XCode. diff --git a/scripts/build-ios.sh b/scripts/build-ios.sh new file mode 100755 index 00000000..d009ea80 --- /dev/null +++ b/scripts/build-ios.sh @@ -0,0 +1,273 @@ +#!/bin/bash +# build-ios.sh +# Author: Matthew Raymer +# Description: iOS build script for TimeSafari application +# This script handles the complete iOS build process including cleanup, +# web build, Capacitor build, asset generation, version management, and Xcode launch. +# +# Prerequisites: +# - macOS with Xcode installed +# - iOS development certificates configured +# - Capacitor dependencies installed +# +# Usage: +# ./scripts/build-ios.sh # Standard build and open Xcode +# ./scripts/build-ios.sh --version 1.0.3 # Build with specific version +# ./scripts/build-ios.sh --build-number 35 # Build with specific build number +# ./scripts/build-ios.sh --no-xcode # Build without opening Xcode +# ./scripts/build-ios.sh --help # Show help +# ./scripts/build-ios.sh --verbose # Enable verbose logging +# +# NPM Script Equivalents: +# npm run build:ios # Standard iOS build +# npm run build:ios:release # Release build with version bump +# +# Exit Codes: +# 1 - iOS cleanup failed +# 2 - Web build failed +# 3 - Capacitor build failed +# 4 - Capacitor sync failed +# 5 - Asset generation failed +# 6 - Version update failed +# 7 - Xcode project opening failed +# 8 - Ruby/Gem environment setup failed +# 9 - iOS directory structure validation failed + +# Exit on any error +set -e + +# Source common utilities +source "$(dirname "$0")/common.sh" + +# Default values +VERSION="" +BUILD_NUMBER="" +OPEN_XCODE=true +MARKETING_VERSION="" + +# Function to show usage +show_usage() { + cat << EOF +Usage: $0 [OPTIONS] + +OPTIONS: + --version VERSION Set marketing version (e.g., 1.0.3) + --build-number NUMBER Set build number (e.g., 35) + --marketing-version VER Set marketing version explicitly + --no-xcode Skip opening Xcode after build + --help Show this help message + --verbose Enable verbose logging + --debug Enable debug mode + +EXAMPLES: + $0 # Standard build + $0 --version 1.0.3 --build-number 35 # Build with specific version + $0 --no-xcode # Build without opening Xcode + $0 --verbose # Build with verbose output + +EOF +} + +# Parse command line arguments +parse_ios_args() { + while [[ $# -gt 0 ]]; do + case $1 in + --version) + VERSION="$2" + MARKETING_VERSION="$2" + shift 2 + ;; + --build-number) + BUILD_NUMBER="$2" + shift 2 + ;; + --marketing-version) + MARKETING_VERSION="$2" + shift 2 + ;; + --no-xcode) + OPEN_XCODE=false + shift + ;; + --help) + show_usage + exit 0 + ;; + --verbose) + VERBOSE=true + shift + ;; + --debug) + DEBUG=true + set -x + shift + ;; + *) + log_warn "Unknown option: $1" + shift + ;; + esac + done +} + +# Function to validate iOS build environment +validate_ios_environment() { + log_info "Validating iOS build environment..." + + # Check if running on macOS + if [[ "$(uname)" != "Darwin" ]]; then + log_error "iOS builds require macOS" + exit 9 + fi + + # Check if Xcode is installed + if ! command -v xcodebuild &> /dev/null; then + log_error "Xcode is not installed or not in PATH" + exit 9 + fi + + # Check if iOS directory exists + if [ ! -d "ios" ]; then + log_error "iOS directory not found. Run 'npx cap add ios' first." + exit 9 + fi + + log_success "iOS build environment validated" +} + +# Function to setup Ruby/Gem environment for Capacitor +setup_ruby_environment() { + log_info "Setting up Ruby/Gem environment..." + + # Check if we're in a pkgx environment and setup gem paths + if command -v gem &> /dev/null; then + gem_path=$(which gem) + if [[ "$gem_path" == *"pkgx"* ]]; then + log_info "Detected pkgx environment, setting up gem paths..." + shortened_path="${gem_path%/*/*}" + export GEM_HOME="$shortened_path" + export GEM_PATH="$shortened_path" + log_info "GEM_HOME set to: $GEM_HOME" + fi + else + log_error "Ruby gem command not found" + exit 8 + fi + + log_success "Ruby/Gem environment configured" +} + +# Function to setup iOS asset directories +setup_ios_asset_directories() { + log_info "Setting up iOS asset directories..." + + # Create required asset directories that capacitor-assets expects + mkdir -p "ios/App/App/Assets.xcassets/AppIcon.appiconset" + echo '{"images":[]}' > "ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json" + + mkdir -p "ios/App/App/Assets.xcassets/Splash.imageset" + echo '{"images":[]}' > "ios/App/App/Assets.xcassets/Splash.imageset/Contents.json" + + log_success "iOS asset directories prepared" +} + +# Function to update iOS version numbers +update_ios_version() { + if [ -n "$BUILD_NUMBER" ] || [ -n "$MARKETING_VERSION" ]; then + log_info "Updating iOS version information..." + + cd ios/App + + # Update build number if provided + if [ -n "$BUILD_NUMBER" ]; then + log_info "Setting build number to: $BUILD_NUMBER" + safe_execute "Updating build number" "xcrun agvtool new-version $BUILD_NUMBER" || exit 6 + fi + + # Update marketing version if provided + if [ -n "$MARKETING_VERSION" ]; then + log_info "Setting marketing version to: $MARKETING_VERSION" + safe_execute "Updating marketing version" "perl -p -i -e 's/MARKETING_VERSION = .*/MARKETING_VERSION = $MARKETING_VERSION;/g' App.xcodeproj/project.pbxproj" || exit 6 + fi + + cd ../.. + log_success "iOS version information updated" + else + log_info "No version updates requested" + fi +} + +# Parse command line arguments +parse_ios_args "$@" + +# Print build header +print_header "TimeSafari iOS Build Process" +log_info "Starting iOS build process at $(date)" + +# Validate iOS build environment +validate_ios_environment + +# 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" + +# Setup Ruby/Gem environment +setup_ruby_environment + +# Step 1: Clean iOS app +safe_execute "Cleaning iOS app" "npm run clean:ios || true" || exit 1 + +# Step 2: Clean dist directory +log_info "Cleaning dist directory..." +clean_build_artifacts "dist" + +# Step 3: Build web assets +safe_execute "Building web assets" "npm run build:web" || exit 2 + +# Step 4: Build Capacitor version +safe_execute "Building Capacitor version" "npm run build:capacitor" || exit 3 + +# Step 5: Sync with Capacitor +safe_execute "Syncing with Capacitor" "npx cap sync ios" || exit 4 + +# Step 6: Setup iOS asset directories +setup_ios_asset_directories + +# Step 7: Generate iOS assets +safe_execute "Generating iOS assets" "npx capacitor-assets generate --ios" || exit 5 + +# Step 8: Update version information +update_ios_version + +# Step 9: Open Xcode (if requested) +if [ "$OPEN_XCODE" = true ]; then + safe_execute "Opening Xcode" "npx cap open ios" || exit 7 + log_info "Xcode opened. You can now build and run on simulator or device." + log_info "Next steps in Xcode:" + log_info " 1. Select Product -> Destination with a Simulator version" + log_info " 2. Click the run arrow to build and test" + log_info " 3. For release: Choose Product -> Destination -> Any iOS Device" + log_info " 4. For release: Choose Product -> Archive" +else + log_info "Skipping Xcode opening as requested" +fi + +# Print build summary +log_success "iOS build completed successfully!" + +if [ -n "$BUILD_NUMBER" ] || [ -n "$MARKETING_VERSION" ]; then + log_info "Version Information:" + [ -n "$BUILD_NUMBER" ] && log_info " Build Number: $BUILD_NUMBER" + [ -n "$MARKETING_VERSION" ] && log_info " Marketing Version: $MARKETING_VERSION" +fi + +log_info "iOS project ready at: ios/App/" +print_footer "iOS Build" + +# Exit with success +exit 0 \ No newline at end of file