Guide

Running an iOS CI/CD pipeline on your own machine

Most iOS CI advice optimizes the wrong thing. The build step is rarely where the minutes go. This is what actually moves the needle on a real pipeline, and how dedicated hardware changes the calculation.

Where the minutes really go

On a hosted runner, a typical iOS job spends a large share of its time before it compiles a single line of your code: resolving and downloading dependencies, warming an empty DerivedData directory, installing tooling, and booting a simulator. That work repeats on every run because the machine is destroyed afterwards.

On a dedicated machine that work is mostly already done. In our benchmark, the clean build improved 40 percent from the faster chip, but the incremental build improved 74 percent and a warm pod install improved 93 percent, purely because the caches persisted.

A pipeline worth copying

  • Split the work. Lint, shared Swift package tests and release automation can run on Linux. Only put simulator and device work on the Mac.
  • Cache the right paths. DerivedData, SwiftPM, CocoaPods and Gems. On a dedicated box these persist for free.
  • Use fastlane for the boring parts. Build, test, screenshot and upload lanes give you the same commands locally and in CI.
  • Keep signing predictable. fastlane match with a private certificates repository is still the most reliable approach. MacRun does not manage signing for you, which means nothing surprises you either.
  • Trim the matrix. Full device and OS matrices belong on main and nightly runs, not on every pull request.

Example workflow

name: iOS
on: [pull_request]

jobs:
  test:
    runs-on: [self-hosted, macOS, macrun-unit-01]
    steps:
      - uses: actions/checkout@v4
      - run: sudo xcodes select 16.2
      - run: bundle install
      - run: bundle exec fastlane test

Because the runner is dedicated, there is no cache restore step here. The dependencies and DerivedData from the previous run are already on disk.

What this does not solve

Dedicated hardware does not fix a slow test suite, a module graph that forces full rebuilds, or flaky simulator tests. It removes the repeated setup tax and the per-minute meter. The rest is still engineering work on your side.

Frequently asked questions

How do I make iOS builds faster in GitHub Actions?

+

Cut repeated setup before optimizing compilation. Persist DerivedData, SwiftPM and CocoaPods caches, move non-Mac work to Linux runners, trim device matrices on pull requests, and pin one Xcode version. On dedicated hardware the caches persist automatically between runs.

Can I use fastlane on a self-hosted macOS runner?

+

Yes. fastlane, CocoaPods, Ruby and Node come preinstalled on MacRun machines, and you invoke them exactly as you would locally. Signing with fastlane match works the same way it does on any Mac.

Does MacRun handle code signing for me?

+

No, and that is deliberate. You keep control of your certificates and provisioning profiles, typically with fastlane match against your own private repository. We provide the machine, not a managed signing service.

Can I run iOS UI tests on a dedicated runner?

+

Yes. Simulators run normally, and because the machine is not recycled, simulator boot state and derived data stay warm between runs, which usually cuts several minutes off a UI test job.

Related guides