10.6 — Xcode Cloud Full Walkthrough

Opening scenario

You’re a solo dev. You’ve spent two weekends fighting GitHub Actions YAML, certificate provisioning, and xcodebuild flag arcana just to get tests running on a hosted Mac. You watch a friend with an Apple Developer subscription open Xcode 16, click “Create Workflow”, point it at his GitHub repo, and have green CI running in 90 seconds. He pays $0 extra because his usage is under 25 hours/month.

Xcode Cloud is Apple’s first-party CI for iOS/macOS. It’s not always the right answer — but when it is, nothing else competes on integration depth.

Context taxonomy

LayerWhat you configureWhere
WorkflowTrigger + actions + post-actionsXcode Report Navigator → Cloud, or App Store Connect
TriggerBranch, PR, tag, scheduledWorkflow config
EnvironmentmacOS image, Xcode version, env vars, secretsWorkflow → Environment
ActionTest, Build, Analyze, ArchiveWorkflow → Actions
Post-actionTestFlight distribution, notification, webhookWorkflow → Post-Actions
PricingFree 25 compute hours/month, ~$0.05/hr afterApp Store Connect → Users and Access → Xcode Cloud

Concept → Why → How → Code

Concept. Xcode Cloud is a managed CI service tightly coupled to Xcode and App Store Connect. Workflows live in App Store Connect; the build environment is Apple-managed; signing is automatic if you let it be.

Why. Apple owns the entire toolchain — they can pre-cache Xcode versions, simulator runtimes, and signing identities far better than third-party hosted runners. The setup tax goes from hours to minutes.

How — first-time setup.

  1. Open your project in Xcode 16+.
  2. Reports navigator (⌘9) → “Cloud” tab → “Get Started”.
  3. Connect to App Store Connect (if not already).
  4. Connect source repository — Apple OAuth flow with GitHub/GitLab/Bitbucket. Choose repository-scoped access, never org-wide.
  5. Apple analyzes your project and proposes a default workflow:
    • Trigger: any branch change
    • Action: Build (release config)
    • Post-action: none
  6. Edit before saving — most defaults are too eager.

A realistic 4-workflow setup.

Workflow nameTriggerActionsPost-actions
PR TestsPR to mainTest (iPhone 16, iOS 18 simulator)GitHub status check
Main CIPush to mainTest + ArchiveTestFlight: Internal Testing
Release CandidateTag v*.*.*Test + ArchiveTestFlight: External “Beta Wide” + Slack
NightlyScheduled, 02:00 UTCTest + AnalyzeSlack on failure only

Environment variables and secrets.

# Public (visible in logs):
DEFAULT_REGION         = US
SLACK_WEBHOOK_PUBLIC   = (not actually public — see below)

# Secret (masked in logs, encrypted at rest):
SLACK_WEBHOOK          = https://hooks.slack.com/...
ASC_API_KEY_ID         = AAAA1111BB
ASC_API_ISSUER_ID      = 69a6de70-...

Secrets are managed in App Store Connect → Xcode Cloud → Workflow → Environment → Secrets. They appear as $SLACK_WEBHOOK etc. in CI scripts.

Custom scripts. Xcode Cloud runs three optional shell scripts you place in ci_scripts/ at the repo root:

# ci_scripts/ci_post_clone.sh — after checkout, before build
#!/bin/sh
set -e
echo "Installing dependencies"
brew install swiftlint
# ci_scripts/ci_pre_xcodebuild.sh — just before xcodebuild runs
#!/bin/sh
agvtool new-version -all "$CI_BUILD_NUMBER"
# ci_scripts/ci_post_xcodebuild.sh — after xcodebuild succeeds
#!/bin/sh
if [ "$CI_WORKFLOW" = "Release Candidate" ]; then
  curl -X POST -H 'Content-Type: application/json' \
    --data "{\"text\":\"✅ Build $CI_BUILD_NUMBER ready\"}" \
    "$SLACK_WEBHOOK"
fi

These scripts execute on the runner. They have access to all env vars (CI_* are auto-populated by Xcode Cloud).

Automatic code signing. Xcode Cloud manages its own signing identity — you don’t import a .p12 or use match. App Store Connect provisions a “Xcode Cloud” certificate scoped to the connected workflow. To use it, set the project’s Signing & Capabilities → Team and check “Automatically manage signing.” Locally you can still use your own cert.

In the wild

  • Apple’s own sample apps (e.g., the WWDC SwiftUI Trips demo) use Xcode Cloud workflows, visible in the public-facing sample repos.
  • Indie shops with one app love Xcode Cloud — Marco Arment (Overcast), Mike Rundle’s app — because the setup overhead vanishes.
  • The Browser Company publicly mentioned moving Arc on iOS to Xcode Cloud for the speed of TestFlight integration.
  • Larger orgs rarely fully replace GitHub Actions with Xcode Cloud — they use Xcode Cloud for archive/sign/upload and GitHub Actions for the broader release orchestration (changelogs, Jira updates, web companion deployment).

Common misconceptions

  1. “Xcode Cloud is free.” It’s free up to 25 compute hours/month per organization. A typical 5-engineer team blows through that in a week.
  2. “Xcode Cloud requires zero YAML.” Mostly — but workflow config is JSON-backed and not easily diffable in PRs. Some prefer GitHub Actions specifically because the config is text-in-repo.
  3. “You can use any Xcode version.” You can pick from Apple-supported versions — typically current GA, current beta, and ~3 prior majors. No custom Xcode versions.
  4. “Xcode Cloud manages signing — I never need a certificate again.” True for the App Store distribution path. You still need certs for local development and any non-Xcode-Cloud release path.
  5. “Workflows live in the repo.” They live in App Store Connect, not in the repo. Backing them up means exporting JSON from the App Store Connect API.

Seasoned engineer’s take

Xcode Cloud is the best CI for two situations:

  • Solo or small team shipping a single app, wanting zero infra overhead.
  • Large team’s archive/sign/upload step where you want first-party reliability for the most failure-prone part of the pipeline.

It’s the wrong choice when:

  • You need cross-platform CI (Android, web, backend) and want one runner pool.
  • You need budget visibility — at scale, GitHub Actions on macos-15 is often cheaper.
  • You want config in the repo for PR-reviewable changes.

TIP. Start with the default workflow Apple proposes, run it once, then turn off triggers you don’t want (it defaults to “every branch change” which fills your queue with stale branch builds). Pin the Xcode version explicitly — “latest” will change under you when Apple releases a new GA.

WARNING. The 25-hour free tier counts all workflows across the org. A misconfigured nightly that rebuilds for 90 minutes daily eats the budget by day 17.

Interview corner

Junior“Where do you configure an Xcode Cloud workflow?” In Xcode’s Report Navigator → Cloud, or directly in App Store Connect → Xcode Cloud. The config lives in App Store Connect, not the repo.

Mid“How do you customize the build without touching workflow JSON?” Put scripts in ci_scripts/ci_post_clone.sh, ci_pre_xcodebuild.sh, ci_post_xcodebuild.sh. They run automatically and inherit all CI_* environment variables Xcode Cloud injects.

Senior“Cost-compare Xcode Cloud vs GitHub Actions macOS for a team of 8 doing 10 builds/day, 15 min each.” 8 × 10 × 15 = 1200 minutes/day = 600 hours/month. Xcode Cloud: 25 free + 575 × $0.05 ≈ $29/mo. GitHub Actions macos-15 standard: 600 × $0.08/min × 60 ≈ $2880/mo. Xcode Cloud is ~100× cheaper at this volume. But Xcode Cloud charges per hour, GHA per minute — short builds favor GHA, long archives favor Xcode Cloud.

Red flag“We use Xcode Cloud and rebuild every commit on every branch.” That’s a fast way to burn $300/month for nothing. Filter to main + PR + tags.

Lab preview

Lab 10.2 walks you through creating two workflows (PR Tests + Main CI) end-to-end on a real project, including secrets, a Slack post-action, and a custom ci_post_clone.sh.


Next: 10.7 — GitHub Actions iOS Full Walkthrough