# Mobile CI CD Overview

> Mobile CI/CD fundamentals - branching, build matrices, signing, artifact caching, store uploads, and common pipeline shapes across Xcode Cloud, GitHub Actions, Bitrise, and Codemagic. Use when designing or rebuilding a mobile pipeline.

- Skill: `almasumdev/mobile-ci-cd-overview` (Agent Skill)
- Install (CLI): `npx skillmds@latest add almasumdev/mobile-ci-cd-overview`
- Raw SKILL.md: https://api.skillmd.com/api/skills/almasumdev/mobile-ci-cd-overview/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: almasumdev (https://skillmd.com/u/almasumdev)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/almasumdev/mobile-ci-cd-overview

---


# Mobile CI/CD Overview

## Instructions

A mobile CI/CD pipeline reliably turns a commit into a signed, store-ready artifact. Builds are slow, signing is finicky, and store APIs are rate-limited. A pragmatic pipeline invests in caching, parallelism, and guard rails more than in clever automation.

### 1. Pipeline Shape

```
Commit -> PR checks (lint, unit, integration)
       -> Build artifact (debug)
       -> UI smoke on emulator
       -> Merge to main
       -> Build artifact (release, signed)
       -> Upload to internal/TestFlight/Play Internal
       -> Optional: promote to production with staged rollout
```

Keep PR lane fast (under 10 minutes). Promote heavy work (device cloud, E2E, size analysis) to the main lane.

### 2. Branching

- **Trunk-based** with short-lived branches works best for mobile. Long release branches invite merge pain and diverging metadata.
- **Release branches** only when multiple versions must be supported simultaneously (enterprise distribution).
- Tag every production release on the merge commit (`v2.5.0`).
- Protect `main` with required checks, linear history, and signed commits.

### 3. Build Matrices

- **iOS**: one macOS runner per job. Match Xcode version to the project's `required_xcode_version`. Keep SDK up to date.
- **Android**: Linux runners; use cached Gradle caches and AVD images.
- **Flutter**: matrix of iOS + Android builds; share analyzer/test job.
- **React Native**: similar matrix; use Hermes; cache Metro.
- Avoid matrices that fan out to 20 jobs for a PR. Most issues repro on one target.

### 4. Caching

Caching is where mobile pipelines win or lose.

- **Gradle**: cache `~/.gradle/caches`, `~/.gradle/wrapper`, keyed on `**/*.gradle*`, `**/gradle-wrapper.properties`, `gradle/libs.versions.toml`.
- **CocoaPods**: cache `Pods` and `~/Library/Caches/CocoaPods`, keyed on `Podfile.lock`.
- **SwiftPM**: cache `~/Library/Developer/Xcode/DerivedData/*/SourcePackages`, keyed on `Package.resolved`.
- **Yarn/npm**: cache `~/.yarn/cache` or `~/.npm` keyed on lockfile. Enable Yarn zero-install if appropriate.
- **Dart/pub**: cache `~/.pub-cache`, keyed on `pubspec.lock`.
- **Xcode DerivedData**: cache selectively; often cheaper to rebuild than to invalidate.

### 5. Signing

- Keep signing assets out of the repo. Use CI secrets (`.p12`, keystore, provisioning profiles, App Store Connect API key JSON).
- Prefer **App Store Connect API keys** over Apple ID-based `altool`. They are session-safe and scriptable.
- Prefer **signing by Google Play** (upload key in CI, app signing key with Google).
- Use **fastlane match** or equivalent to centralize provisioning profiles and certs for iOS across engineers and CI.

```yaml
# GitHub Actions snippet - iOS signing
- name: Import certs
  run: |
    echo "$IOS_DIST_CERT_P12_BASE64" | base64 -d > cert.p12
    security create-keychain -p "" build.keychain
    security import cert.p12 -k build.keychain -P "$IOS_DIST_CERT_PASSWORD" -T /usr/bin/codesign
- name: Download provisioning profile
  run: echo "$IOS_PROVISIONING_PROFILE_BASE64" | base64 -d > app.mobileprovision
```

### 6. Artifacts

- Upload debug builds to Firebase App Distribution or TestFlight internal for quick QA.
- Store `.ipa`, `.aab`, `mapping.txt` (Android), `dSYM` (iOS) for every release with 90-day retention at minimum.
- dSYM and mapping files must be uploaded to the crash reporter on every release; without them stack traces are unreadable.

### 7. Store Upload

- **Fastlane**: `pilot` (TestFlight), `supply` (Play). Battle-tested.
- **Gradle Play Publisher**: Play upload via Gradle tasks.
- **Xcode Cloud**: first-class Apple pipeline; good for iOS-only teams.
- **Codemagic / Bitrise / AppCircle**: mobile-focused hosted CI with prebuilt store steps.

Automate internal/TestFlight on every main merge. Automate production only when staged rollout and halt criteria are owned by the pipeline.

### 8. Environments and Flavors

- Use **build flavors / schemes / productFlavors** to separate `dev`, `staging`, `prod` bundles with distinct bundle IDs.
- Separate Firebase / analytics projects per flavor. Never mix staging and prod analytics.
- Secrets come from the CI environment, not from committed files. Use `gradle.properties` readers or `xcconfig` with CI injection.

### 9. Versioning

- Version code / build number must strictly increase. Compute from commit count (`git rev-list --count HEAD`) or CI run number.
- Version name from a tag or `package.json`/`pubspec.yaml`/`Info.plist`/`build.gradle`.
- Fail the build if version code is not greater than the last uploaded artifact.

### 10. Observability for the Pipeline

- Track build duration, cache hit rate, test duration, and failure reasons.
- Alert when PR lane exceeds a budget (e.g., 15 minutes) consistently.
- Keep a rolling dashboard of flaky jobs; quarantine or fix.

### 11. Anti-Patterns

- Self-hosted runners without auto-scaling. Either accept queueing or invest in elasticity.
- Signing secrets stored in plain repo files, even in private repos.
- Single giant job that does lint, build, test, and upload. Split so failures are isolated.
- Version number bumped manually. Automate.
- No dSYM/mapping upload step. Crashes will be unreadable and ownership lost.
- Running real device tests on every PR. Sample on PR, full matrix on main.

## Checklist

- [ ] Trunk-based branching with required PR checks.
- [ ] PR lane runs under 10 minutes with caches warm.
- [ ] Release lane signs artifacts using secrets from CI storage.
- [ ] dSYMs and mapping files uploaded to the crash reporter per release.
- [ ] Store uploads automated to internal/TestFlight on main merge.
- [ ] Version code/build number auto-computed and monotonic.
- [ ] Separate flavors for dev/staging/prod with isolated analytics.
- [ ] Pipeline metrics (duration, flake rate) are monitored.
- [ ] Cache keys include the lockfiles that govern their invalidation.

