Skip to content

iOS pull request checks duplicate the core build and run the heaviest job on the smallest runner #763

Description

@TarikGul

The iOS pull request checks take about 31 minutes, and roughly a third of that
is duplicated work. Measured from a fully green run.

job runner total dominant step bootstrap
build macos-26 30m54s Build app 17m27s 11m13s
test macos-26-xlarge 19m21s Run tests 12m07s 5m44s
preview macos-26-xlarge new a third copy

The core is compiled once per job

bootstrap-ios-core generates the same artifacts in every job: the Rust codegen
output, the host bindings and xcframework, and the provider bindings. That is
11m13s plus 5m44s today, and a third copy once the preview job lands.

The output is deterministic for a given commit, so it can be built once and
shared. A job that produces it and uploads the bindings and xcframework as an
artifact, with the app jobs downloading it, removes the duplication. It is the
same output release-ios.yml already produces.

  • Build the core once per run and share it with the app jobs

The heaviest job is on the smallest runner

The same bootstrap step takes 11m13s on macos-26 and 5m44s on
macos-26-xlarge, so the 3 cpu runner is roughly half the speed of the 5 cpu
one. build compiles 2,533 Swift files and archives for a device on the smaller
runner, while test finishes eleven minutes earlier on the larger one.

Swift whole-module compilation parallelises, so this is likely a direct win.
Worth confirming with a measurement rather than assuming.

  • Move build to macos-26-xlarge and measure the difference

The SPM cache has never hit

Cache not found for input keys: macOS-xcode-26.4.1-spm-b882d255...
restore-keys: macOS-xcode-26.4.1-spm-

A complete miss including the prefix fallback, which means the cache has never
been populated rather than merely being stale. The key is
hashFiles('**/Package.resolved') and there are 28 of those under hosts/ios,
so it changes whenever any one of them does. Resolving 27 local packages plus the
remote graph is a real part of the 17 minutes.

  • Work out why the cache is never written, and whether the key is too broad

Expected outcome

Fixing the first two should bring the critical path under 20 minutes: a shared
bootstrap of around six minutes, then the app jobs in parallel at roughly twelve
to thirteen each.

Not before #754

All three touch ios-pr.yml, which is in the queue. Optimising it before it
lands risks reopening questions that took a day to close.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions