# Runbook: iOS native-build toolchain

Owner: mobile team Last reviewed: 2026-05-28

Audit #58 called out missing host-environment setup for iOS builds. This runbook
lists the prerequisites and the one-shot check script that verifies them.

## Required tooling

| Tool                  | Required version    | Why                                               |
| --------------------- | ------------------- | ------------------------------------------------- |
| macOS                 | 13+                 | Xcode 15 requires Ventura or later                |
| Xcode.app             | 15.0+               | iOS 17+ SDK; AGP 8.x / RN 0.85 toolchain          |
| Command Line Tools    | any current         | required by `xcrun simctl`, `xcodebuild`          |
| Ruby                  | 3.0+                | CocoaPods 1.15 dropped Ruby 2.6 (macOS default)   |
| CocoaPods             | 1.15+               | Required by RN 0.85 / Expo SDK 55+ podfile syntax |
| iOS simulator runtime | iOS 17 SDK or later | Detox / e2e runs                                  |

`scripts/check-ios-toolchain.sh` reports each of the above and exits non-zero on
any missing piece — run it before opening a "my iOS build broke" Linear ticket.

## Step-by-step setup

1. **Install Xcode.app** from the Mac App Store (free, ~12 GB). Command Line
   Tools alone are NOT sufficient — they ship a stripped toolchain that cannot
   build iOS apps.
2. **Switch active developer dir** to Xcode.app:
   ```bash
   sudo xcode-select -s /Applications/Xcode.app
   ```
3. **Accept the Xcode license** (required for `xcodebuild`):
   ```bash
   sudo xcodebuild -license accept
   ```
4. **Install Ruby 3.x** via Homebrew. macOS ships 2.6.10 which CocoaPods has
   dropped:
   ```bash
   brew install ruby
   echo 'export PATH="$(brew --prefix)/opt/ruby/bin:$PATH"' >> ~/.zshrc
   exec zsh
   ruby --version  # → ruby 3.x
   ```
5. **Install CocoaPods**:
   ```bash
   gem install cocoapods
   pod --version  # → 1.15+
   ```
6. **Install at least one iOS simulator runtime**:
   ```bash
   xcodebuild -downloadPlatform iOS
   ```
7. **Verify the whole stack**:
   ```bash
   scripts/check-ios-toolchain.sh
   ```

## CI runners

CI uses `macos-14` (Sonoma) runners — Xcode 15.4 is preinstalled. The
mobile-e2e.yml workflow pins this via
`sudo xcode-select -s /Applications/Xcode_15.4.app` early in each iOS job. The
`mobile-build-smoke.yml` workflow added in #83 does the same.

If a build fails on CI with "xcodebuild: command not found", first check the
runner image (a deprecated `macos-12` would mean Xcode 14 is the default). Bump
to `macos-14` in the workflow file.

## Common failures

- **`error: Could not find ...`** during `pod install` → Ruby version drift.
  Re-run the toolchain check; CocoaPods loads .gemspec files that pin Ruby ≥3.
- **`xcrun: error: invalid active developer path`** → step 2 above wasn't run,
  or Xcode.app was moved. Re-run `sudo xcode-select -s /Applications/Xcode.app`.
- **`xcodebuild requires Xcode, but active developer directory ... is Command Line Tools`**
  → same as above.
- **iOS simulator boot hangs in CI** → the runner is on a stale image. In CI,
  the iPhone 15 simulator that mobile-e2e.yml expects requires iOS 17 SDK;
  `xcodebuild -downloadPlatform iOS` is preinstalled on macos-14 but missing on
  macos-12.
