# CI/CD Setup — iPhone Deploy Workflow This guide covers setting up a **Gitea Actions** macOS runner to automatically build, test, and deploy **TabataGo** to a physical iPhone on every PR to `main`. ## Prerequisites ### Hardware - **Mac** running macOS 15 (Sequoia) or later - **Xcode 26+** installed (required for iOS 26.0 / watchOS 11.0 targets) - **iPhone** (iOS 26+) connected via USB, with Developer Mode enabled ### Software - [Gitea Actions Runner](https://docs.gitea.com/usage/actions/act-runner) installed and registered - `brew` (Homebrew) installed - `xcodegen` — `brew install xcodegen` (also installed automatically by the workflow) - `ios-deploy` — `brew install ios-deploy` (also installed automatically by the workflow) - `libimobiledevice` + `ideviceinstaller` (installed automatically by the workflow) ## 1. Register the macOS Runner ```bash # On the Mac: ./act_runner register \ --instance https://gitea.1000co.fr \ --token \ --name "macos-runner" \ --labels macos # Start the runner ./act_runner daemon ``` > **Important:** The runner must have the label `macos` because the workflow uses `runs-on: macos`. ## 2. iPhone Preparation 1. Connect the iPhone to the Mac via USB 2. Trust the computer on the iPhone when prompted 3. Enable **Developer Mode** on the iPhone: `Settings → Privacy & Security → Developer Mode` 4. Get the device UDID: ```bash # Method 1: Via libimobiledevice (preferred) idevice_id -l # Method 2: Via system_profiler (no extra tools needed) system_profiler SPUSBDataType | grep -A 20 "iPhone" | grep "Serial Number" # The UDID is the 40-character hex string (not the ECID) # Method 3: Via Xcode # Window → Devices and Simulators ``` > **Important:** Bonjour/mDNS discovery does **not** work over VPN connections. Always use the USB-based UDID connection (`--id` flag with `ios-deploy`) rather than relying on network Bonjour discovery. The workflow uses `--id ${IPHONE_UDID}` which works over both direct USB and USB-over-network setups. ## 3. Configure Secrets Add these secrets in the Gitea repository: `Settings → Actions → Secrets` | Secret Name | Description | How to Get | |-------------|-------------|------------| | `IPHONE_UDID` | 40-character UDID of the target iPhone | `idevice_id -l` on the connected Mac | | `GITEA_TOKEN` | Gitea API token with repo + pull request scope | `Gitea → Settings → Applications → Generate Token` | ### Gitea Token Permissions The token needs: - `read:repository` — to read PR metadata - `write:issue` — to post LGTM comments - `write:pull_request` — to merge approved PRs ## 4. Xcode Signing The workflow uses **automatic code signing**. Ensure: 1. The Mac runner is signed into an Apple Developer account in Xcode: ```bash # Verify: xcrun security find-identity -v -p codesigning ``` 2. The Apple ID used must be part of the team `2MJF39L8VY` (configured in `ExportOptions.plist`). 3. For first-time setup, open Xcode on the runner Mac and sign in: ``` Xcode → Settings → Accounts → Add Apple ID ``` ## 5. Workflow Overview The workflow at `.gitea/workflows/pr-iphone-deploy.yml` triggers on PRs to `main`: ``` PR Opened / Updated ↓ Checkout + XcodeGen generate ↓ Resolve SPM packages ↓ Build for iPhone (Release) ↓ Export IPA + Install on device ↓ Run unit tests ↓ Post LGTM comment on PR ↓ Auto-merge (if no failures) ``` ## 6. Manual Test Run To test the workflow locally on the runner Mac: ```bash # Simulate the build: cd tabatago-swift xcodegen generate xcodebuild build \ -project TabataGo.xcodeproj \ -scheme TabataGo \ -destination "id=" \ -configuration Release \ -allowProvisioningUpdates ``` ## Troubleshooting | Issue | Solution | |-------|----------| | "Device not found" | Check USB connection, trust prompt, UDID in secrets | | "Code signing failed" | Sign into Xcode on the runner Mac, verify team membership | | "No provisioning profile" | Run `-allowProvisioningUpdates` or open project in Xcode once | | `xcodegen: command not found` | `brew install xcodegen` (workflow handles this) | | `ideviceinstaller` fails | Ensure iPhone is unlocked and trusted; try Xcode Organizer manually | | `ios-deploy` fails to find device | Use `--id` with explicit UDID. Bonjour discovery fails over VPN — always use UDID-based connection | | Runner doesn't pick up job | Verify runner label is `macos` and runner is connected | | Token permission errors | Ensure `GITEA_TOKEN` has `write:issue` and `write:pull_request` scopes |