Skip to content

iOS Build & Distribution

iOS apps build and ship to TestFlight via GitHub Actions — a build-and-upload.yml workflow in each app repo. Xcode Cloud has been retired in favour of GitHub Actions (repeatable builds + full control over runners and secrets). The historical Xcode Cloud setup is kept under Legacy for reference.

Pipeline (GitHub Actions)

Each dashecorp/dashe-* app repo has .github/workflows/build-and-upload.yml:

Aspect Value
Runner macos-26 (GitHub-hosted)
Trigger workflow_dispatch (manual)
Signing fastlane match (read-only) — appstore cert + profile pulled from dashecorp/ios-certs (git storage, master), via a token minted from the iBuild-E GitHub App
Build number computed from App Store Connect (latest build + 1) via the ASC API
Archive / export xcodebuild
Upload ASC API key → TestFlight (internal). App Store submission stays human-gated.

Apps with the workflow: Nutri-E, Fast-E, Count-E, Drink-E, Heart-E, Reward-E (all dashecorp/dashe-*).

Secrets (per app repo)

Provisioned via dashecorp/infra (dashe-secrets.tf, OpenTofu — never hand-set):

Secret Purpose
IBUILD_E_APP_ID / IBUILD_E_PRIVATE_KEY GitHub App to read dashecorp/ios-certs
MATCH_PASSWORD fastlane match decryption
ASC_KEY_ID / ASC_ISSUER_ID / ASC_KEY_P8_BASE64 App Store Connect API key (build number + upload)
FIREBASE_* (app-specific) e.g. Crashlytics GoogleService-Info.plist generation

Signing (fastlane match)

Distribution certs + provisioning profiles live encrypted in dashecorp/ios-certs (git storage). CI runs match … readonly:true and never mints certs in CI. A new app / bundle id therefore needs a one-time fastlane match appstore write run to populate ios-certs before its workflow can sign.

Onboarding a new iOS app

  1. Register the bundle id (Apple Developer / ASC API register_bundle_id).
  2. Create the App Store Connect app record in the web UI — the ASC API has no create-app endpoint.
  3. One-time fastlane match appstore write for the bundle id → dashecorp/ios-certs.
  4. Fan the iOS secrets above to the repo via dashe-secrets.tf.
  5. Add build-and-upload.yml (copy from any dashe-* app and adapt APP_IDENTIFIER / SCHEME / project path).

Legacy — Xcode Cloud (retired)

iOS CI previously ran on Apple's Xcode Cloud (archive → App Store Connect → TestFlight, triggered on main push). Retired in favour of the GitHub Actions pipeline above. Historical product IDs (no longer triggered):

App Xcode Cloud product ID
Nutri-E A7AEE8F6
Reward-E 3B4EECB2
Fast-E AAFB4E73
Count-E AEB723D3
Drink-E 275BD2D2 / 8F9F479E (dup)
SupTrackAI (pre-Nutri-E) 8B960BC7
Cuti-E Admin / Feedback / Super Admin 2F32A418 / 046A65C8 / 063839D0 (cuti-e/cutie)

Cleanup notes for the retired setup: - The Xcode Cloud GitHub App may still be installed account-wide on Stig-Johnny (creates check suites on all repos, incl. non-iOS); auto-merge workflows filter out xcode-cloud checks. Restrict/remove it in GitHub Settings → Integrations. - Disable any monitor-xcode-cloud.yml workflow on a migrated repo — it alarms on absent Xcode Cloud builds. - Apps use XcodeGen; the old ci_scripts/ci_post_clone.sh ran xcodegen generate on Xcode Cloud. The GitHub Actions workflow handles project generation + Info.plist itself.