|
| 1 | +--- |
| 2 | +title: "ADR 010: Expo CI/CD" |
| 3 | +description: "Decision to use EAS (Expo Application Services) with GitHub Actions for mobile builds, preview distribution, and PR OTA updates. Android-only v1; store submission deferred." |
| 4 | +--- |
| 5 | + |
| 6 | +## Context |
| 7 | + |
| 8 | +The monorepo includes an Expo app (`apps/mobile`) targeting Android, iOS, and web. We need CI/CD that: |
| 9 | + |
| 10 | +- Enables **PR previews** so reviewers can test changes without building locally |
| 11 | +- Requires **no Apple or Google developer accounts** for initial setup (lower barrier) |
| 12 | +- Integrates with **GitHub Actions** (our existing CI platform) |
| 13 | +- Supports **OTA updates** for fast iteration on JS/TS-only changes |
| 14 | +- Uses **path filters** so mobile workflows run only when `apps/mobile/` or `packages/ui/` change |
| 15 | +- Aligns with our monorepo (Turborepo, pnpm) and deployment practices |
| 16 | + |
| 17 | +## Considered Options |
| 18 | + |
| 19 | +### Option A – EAS + GitHub Actions (Chosen) |
| 20 | + |
| 21 | +EAS Build for native binaries, EAS Update for OTA, GitHub Actions for orchestration. |
| 22 | + |
| 23 | +**Pros** |
| 24 | + |
| 25 | +- **Install once, review many PRs**: Build baseline APK → reviewers install → each PR ships OTA with QR code |
| 26 | +- **No store accounts for v1**: Internal distribution link for preview builds; no Apple/Google enrollment |
| 27 | +- **OTA for JS-only changes**: Fast PR feedback without rebuilds; EAS Update handles channel-based delivery |
| 28 | +- **Path-filtered workflows**: `mobile-preview` and `mobile-pr-preview` run only when mobile/UI changes |
| 29 | +- **Fits existing stack**: GitHub Actions, EXPO_TOKEN, familiar YAML workflow format |
| 30 | +- **Maestro-ready**: `e2e-test` profile for simulator/emulator builds; optional mobile-e2e workflow later |
| 31 | + |
| 32 | +**Cons** |
| 33 | + |
| 34 | +- Requires Expo account and `EXPO_TOKEN` in GitHub Secrets |
| 35 | +- EAS Update is JS-only; native changes (deps, config plugins, permissions) need new builds |
| 36 | +- Reviewers must install baseline APK before PR OTA works |
| 37 | + |
| 38 | +### Option B – Local Builds Only |
| 39 | + |
| 40 | +Developers build and share artifacts manually (e.g., `eas build`, adb install). |
| 41 | + |
| 42 | +**Pros** |
| 43 | + |
| 44 | +- No CI setup, no cloud dependency |
| 45 | +- Full control over build environment |
| 46 | + |
| 47 | +**Cons** |
| 48 | + |
| 49 | +- No automated PR previews; slows review cycles |
| 50 | +- Inconsistent environments across developers |
| 51 | +- Does not scale for team collaboration |
| 52 | + |
| 53 | +### Option C – Codemagic / Bitrise / Other Mobile CI |
| 54 | + |
| 55 | +Third-party mobile CI services with native build support. |
| 56 | + |
| 57 | +**Pros** |
| 58 | + |
| 59 | +- Purpose-built for mobile, often simpler UI |
| 60 | +- Can handle iOS signing and provisioning |
| 61 | + |
| 62 | +**Cons** |
| 63 | + |
| 64 | +- Additional service and vendor to manage |
| 65 | +- Less integration with our GitHub-centric workflow |
| 66 | +- Often requires store accounts sooner |
| 67 | +- EAS is the canonical Expo build service; better alignment |
| 68 | + |
| 69 | +### Option D – Full Build Per PR |
| 70 | + |
| 71 | +Trigger a full native build for every PR instead of OTA. |
| 72 | + |
| 73 | +**Pros** |
| 74 | + |
| 75 | +- Always delivers a complete binary; no baseline dependency |
| 76 | + |
| 77 | +**Cons** |
| 78 | + |
| 79 | +- Slow (10–20+ min per build); expensive on EAS |
| 80 | +- Unnecessary when only JS/TS changed |
| 81 | +- OTA is sufficient for most PR review scenarios; full build reserved for native changes or main |
| 82 | + |
| 83 | +## Decision |
| 84 | + |
| 85 | +We adopt **EAS (Expo Application Services) + GitHub Actions** for mobile CI/CD. |
| 86 | + |
| 87 | +### TLDR: Comparison Table |
| 88 | + |
| 89 | +| Feature | EAS + GitHub Actions ✅ | Local Only | Third-Party CI | Full Build Per PR | |
| 90 | +|---------|-------------------------|------------|---------------|-------------------| |
| 91 | +| **PR preview** | ✅ OTA + QR comment | ❌ Manual | ✅ Often supported | ⚠️ Slow | |
| 92 | +| **v1 no store accounts** | ✅ Internal dist | ✅ N/A | ⚠️ Varies | ✅ Possible | |
| 93 | +| **Path filtering** | ✅ apps/mobile, packages/ui | N/A | ⚠️ Varies | ✅ Possible | |
| 94 | +| **JS-only speed** | ✅ OTA fast | N/A | ⚠️ Varies | ❌ Full rebuild | |
| 95 | +| **Expo native fit** | ✅ First-party | N/A | ⚠️ Plugin required | ✅ Possible | |
| 96 | + |
| 97 | +**Main reasons:** |
| 98 | + |
| 99 | +- Install-once + OTA per PR maximizes review speed without full rebuilds |
| 100 | +- Android-only v1 keeps setup simple; no Apple/Google accounts required |
| 101 | +- Path filters avoid unnecessary workflow runs on unrelated PRs |
| 102 | +- EAS is the official Expo build and update service; best alignment with Expo SDK |
| 103 | + |
| 104 | +### Workflows (v1) |
| 105 | + |
| 106 | +| Workflow | Trigger | Use | |
| 107 | +|----------|---------|-----| |
| 108 | +| `mobile-build` | Manual | One-off Android preview or development build | |
| 109 | +| `mobile-preview` | Push to `main` | Auto-build baseline when mobile or UI changes | |
| 110 | +| `mobile-pr-preview` | Pull request | Publish EAS Update, comment QR (app-facing PRs only) | |
| 111 | + |
| 112 | +Path filters: `apps/mobile/**`, `packages/ui/**`. |
| 113 | + |
| 114 | +### EAS Update: JS-Only |
| 115 | + |
| 116 | +EAS Update delivers **JS/TS changes only**. A new build is required for native dependencies, config plugins, permissions, splash/icon changes, or any change affecting the native binary. When such changes land, run a manual build or merge to main so `mobile-preview` produces a fresh baseline. |
| 117 | + |
| 118 | +### eas.json Profiles |
| 119 | + |
| 120 | +v1 profiles: `preview`, `development`, `e2e-test`. No `submit` block until Apple/Google accounts exist. |
| 121 | + |
| 122 | +## Related Documentation |
| 123 | + |
| 124 | +- [Mobile CI/CD](/docs/deployment/mobile-cicd) - Setup, bootstrap, and OTA limits |
| 125 | +- [GitHub Actions](/docs/deployment/github-actions) - All CI workflow configuration |
| 126 | +- [E2E Testing](/docs/testing/e2e-testing) - Maestro flows for mobile |
| 127 | +- [ADR 001: Monorepo](/docs/adrs/001-monorepo-vs-standalone) - Turborepo and unified CI/CD |
0 commit comments