Enhanced simulator auto-detection for better reliability: Device ID Support: - Extracts both device name and UUID from simulator list - Uses device ID (UUID) for xcodebuild destination when available - More reliable than device name matching - Falls back to device name if ID not available Detection Improvements: - Better parsing of simulator list output - Handles edge cases where device name might not match exactly - Logs both device name and ID for debugging Fixes: - Device not found: Using UUID ensures exact device matching - Auto-detection: More robust extraction of device information - Build reliability: Device ID is more reliable than name matching Result: Script should now correctly auto-detect and use available iPhone simulators
227 lines
7.0 KiB
Bash
Executable File
227 lines
7.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# iOS Test App Build and Deploy Script
|
|
# Builds and deploys the DailyNotification iOS test app to iOS Simulator
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
log_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
log_step() {
|
|
echo -e "${BLUE}[STEP]${NC} $1"
|
|
}
|
|
|
|
# Check if we're in the right directory
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
TEST_APP_DIR="$(dirname "$SCRIPT_DIR")"
|
|
|
|
if [ ! -d "$TEST_APP_DIR/App" ]; then
|
|
log_error "App directory not found at $TEST_APP_DIR/App"
|
|
log_info "Please run setup first (see SETUP.md)"
|
|
exit 1
|
|
fi
|
|
|
|
cd "$TEST_APP_DIR"
|
|
|
|
# Check prerequisites
|
|
log_step "Checking prerequisites..."
|
|
|
|
if ! command -v xcodebuild &> /dev/null; then
|
|
log_error "xcodebuild not found. Install Xcode command line tools:"
|
|
log_info " xcode-select --install"
|
|
exit 1
|
|
fi
|
|
|
|
# Check for CocoaPods (try multiple locations)
|
|
POD_CMD=""
|
|
if command -v pod &> /dev/null; then
|
|
POD_CMD="pod"
|
|
elif [ -f ~/.rbenv/shims/pod ]; then
|
|
POD_CMD="~/.rbenv/shims/pod"
|
|
elif [ -f ~/.gem/bin/pod ]; then
|
|
POD_CMD="~/.gem/bin/pod"
|
|
else
|
|
log_error "CocoaPods not found."
|
|
log_info ""
|
|
log_info "Installation options:"
|
|
log_info " 1. Using rbenv (recommended):"
|
|
log_info " rbenv install 3.1.0"
|
|
log_info " rbenv global 3.1.0"
|
|
log_info " gem install cocoapods"
|
|
log_info ""
|
|
log_info " 2. Using system Ruby (requires Ruby 3.1+):"
|
|
log_info " gem install cocoapods"
|
|
log_info ""
|
|
log_info " 3. Using Homebrew:"
|
|
log_info " brew install cocoapods"
|
|
log_info ""
|
|
log_info "Current Ruby version: $(ruby --version 2>/dev/null || echo 'not found')"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Using CocoaPods: $POD_CMD"
|
|
|
|
# Get simulator device (default to first available iPhone, or user-specified)
|
|
if [ -z "$1" ]; then
|
|
# Auto-detect first available iPhone simulator
|
|
# Extract device name from: " iPhone 17 Pro (UUID) (Status)"
|
|
SIMULATOR_LINE=$(xcrun simctl list devices available | grep -i "iPhone" | head -1)
|
|
if [ -z "$SIMULATOR_LINE" ]; then
|
|
# Fallback to generic simulator
|
|
SIMULATOR_DEVICE="generic/platform=iOS Simulator"
|
|
log_warn "No iPhone simulators found, using generic destination"
|
|
else
|
|
# Extract device name (everything before the first parenthesis)
|
|
SIMULATOR_DEVICE=$(echo "$SIMULATOR_LINE" | sed 's/^[[:space:]]*\([^(]*\).*/\1/' | xargs)
|
|
# Extract device ID (UUID in parentheses)
|
|
SIMULATOR_ID=$(echo "$SIMULATOR_LINE" | sed -n 's/.*(\([^)]*\)).*/\1/p' | head -1)
|
|
log_info "Auto-detected simulator: $SIMULATOR_DEVICE (ID: $SIMULATOR_ID)"
|
|
fi
|
|
else
|
|
SIMULATOR_DEVICE="$1"
|
|
log_info "Using specified simulator: $SIMULATOR_DEVICE"
|
|
fi
|
|
|
|
# Boot simulator (only if specific device name provided)
|
|
if [ "$SIMULATOR_DEVICE" != "Any iOS Simulator Device" ] && [ "$SIMULATOR_DEVICE" != "generic/platform=iOS Simulator" ]; then
|
|
log_step "Booting simulator..."
|
|
|
|
# Check if simulator is already booted (more robust check)
|
|
BOOTED=$(xcrun simctl list devices | grep "$SIMULATOR_DEVICE" | grep -i "Booted" || echo "")
|
|
|
|
if [ -n "$BOOTED" ]; then
|
|
log_info "✓ Simulator already booted: $SIMULATOR_DEVICE"
|
|
# Ensure Simulator window is visible
|
|
log_info "Opening Simulator app window..."
|
|
open -a Simulator
|
|
else
|
|
log_info "Booting $SIMULATOR_DEVICE..."
|
|
# Try to boot by device name first
|
|
if xcrun simctl boot "$SIMULATOR_DEVICE" 2>&1; then
|
|
log_info "✓ Simulator booted successfully"
|
|
# Open Simulator app window so user can see it
|
|
log_info "Opening Simulator app window..."
|
|
open -a Simulator
|
|
# Wait a moment for simulator to fully initialize and window to appear
|
|
sleep 3
|
|
else
|
|
log_warn "Could not boot simulator automatically"
|
|
log_info "Opening Simulator app... (you may need to select device manually)"
|
|
open -a Simulator
|
|
sleep 5
|
|
# Verify it's booted after opening
|
|
BOOTED=$(xcrun simctl list devices | grep "$SIMULATOR_DEVICE" | grep -i "Booted" || echo "")
|
|
if [ -z "$BOOTED" ]; then
|
|
log_warn "Simulator may not be booted. Continuing anyway..."
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Install CocoaPods dependencies
|
|
log_step "Installing CocoaPods dependencies..."
|
|
cd App
|
|
export LANG=en_US.UTF-8 # Required for CocoaPods
|
|
|
|
if [ ! -f "Podfile.lock" ] || [ "Podfile" -nt "Podfile.lock" ]; then
|
|
if eval "$POD_CMD install"; then
|
|
log_info "✓ CocoaPods dependencies installed"
|
|
else
|
|
log_error "Failed to install CocoaPods dependencies"
|
|
log_info "Try running manually: export LANG=en_US.UTF-8 && $POD_CMD install"
|
|
exit 1
|
|
fi
|
|
else
|
|
log_info "CocoaPods dependencies up to date"
|
|
fi
|
|
|
|
# Build iOS app
|
|
log_step "Building iOS app..."
|
|
WORKSPACE="App.xcworkspace"
|
|
SCHEME="App"
|
|
CONFIG="Debug"
|
|
SDK="iphonesimulator"
|
|
|
|
# Use generic destination if device name is generic, otherwise use specific device
|
|
if [ "$SIMULATOR_DEVICE" = "Any iOS Simulator Device" ] || [ "$SIMULATOR_DEVICE" = "generic/platform=iOS Simulator" ]; then
|
|
DESTINATION="generic/platform=iOS Simulator"
|
|
elif [ -n "$SIMULATOR_ID" ]; then
|
|
# Use device ID for more reliable matching
|
|
DESTINATION="platform=iOS Simulator,id=$SIMULATOR_ID"
|
|
log_info "Using device ID for destination: $SIMULATOR_ID"
|
|
else
|
|
# Fallback to device name
|
|
DESTINATION="platform=iOS Simulator,name=$SIMULATOR_DEVICE"
|
|
fi
|
|
|
|
log_info "Build destination: $DESTINATION"
|
|
|
|
xcodebuild -workspace "$WORKSPACE" \
|
|
-scheme "$SCHEME" \
|
|
-configuration "$CONFIG" \
|
|
-sdk "$SDK" \
|
|
-destination "$DESTINATION" \
|
|
-derivedDataPath build/derivedData \
|
|
CODE_SIGN_IDENTITY='' \
|
|
CODE_SIGNING_REQUIRED=NO \
|
|
CODE_SIGNING_ALLOWED=NO \
|
|
clean build
|
|
|
|
# Find built app
|
|
APP_PATH=$(find build/derivedData -name "*.app" -type d -path "*/Build/Products/*-iphonesimulator/*.app" | head -1)
|
|
|
|
if [ -z "$APP_PATH" ]; then
|
|
log_error "Could not find built app"
|
|
log_info "Searching in: build/derivedData"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Found app: $APP_PATH"
|
|
|
|
# Install app on simulator
|
|
log_step "Installing app on simulator..."
|
|
if xcrun simctl install booted "$APP_PATH"; then
|
|
log_info "✓ App installed"
|
|
else
|
|
log_error "Failed to install app"
|
|
exit 1
|
|
fi
|
|
|
|
# Get bundle identifier
|
|
BUNDLE_ID=$(plutil -extract CFBundleIdentifier raw App/Info.plist 2>/dev/null || echo "com.timesafari.dailynotification")
|
|
log_info "Bundle ID: $BUNDLE_ID"
|
|
|
|
# Launch app
|
|
log_step "Launching app..."
|
|
if xcrun simctl launch booted "$BUNDLE_ID"; then
|
|
log_info "✓ App launched"
|
|
else
|
|
log_warn "App may already be running"
|
|
fi
|
|
|
|
log_info ""
|
|
log_info "✅ Build and deploy complete!"
|
|
log_info ""
|
|
log_info "To view logs:"
|
|
log_info " xcrun simctl spawn booted log stream"
|
|
log_info ""
|
|
log_info "To uninstall app:"
|
|
log_info " xcrun simctl uninstall booted $BUNDLE_ID"
|
|
|