Skip to content

Pin CI to Xcode 26.3 - #346

Open
Ryanmello07 wants to merge 1 commit into
urnetwork:mainfrom
Ryanmello07:ci/pin-xcode-26
Open

Pin CI to Xcode 26.3#346
Ryanmello07 wants to merge 1 commit into
urnetwork:mainfrom
Ryanmello07:ci/pin-xcode-26

Conversation

@Ryanmello07

Copy link
Copy Markdown
Contributor

Why

CI compiles against the iOS 18 SDK while the app runs on iOS 26 devices. Anything that only exists — or only misbehaves — on the current SDK is invisible here, and that gap has started costing real time.

Two cases from one week:

  • App code merged to main needed an SDK symbol the 16.4 toolchain doesn't have. It built green in CI and failed on a developer machine.
  • ControlCenter is absent from the macOS 15 SDK that 16.4 uses. That is the entire reason WidgetRefresh.reloadControl is walled off behind #if os(iOS) instead of shipping the Control Center toggle on macOS. This bump makes that workaround unnecessary — removing it is left to its own change.

What changed

One line, plus the comment that explains it:

-      - name: Select Xcode 16.4
-        run: sudo xcode-select -s /Applications/Xcode_16.4.app
+      - name: Select Xcode 26.3
+        run: sudo xcode-select -s /Applications/Xcode_26.3.app

Still pinned to an exact path, not to the image default and not to "latest". The original pin's reasoning holds — a runner-image bump must not move the toolchain, and with it the SDK the app is compiled against, without a commit saying so. Only its target was stale.

26.3 is the newest stable on the macos-15 image, which also carries 26.2, 26.1.1 and 26.0.1 (16.4 remains the image default, which is why the explicit pin still matters). Simulator runtimes on that image include iOS 26.0–26.2, so the test step has a current runtime to run against.

What this does NOT buy

Worth stating plainly so it isn't mistaken for more than it is. The job builds and runs unit tests; it never launches the app, and -only-testing:networkTests excludes the UI tests entirely. A rendering fault that only appears on a current SDK still gets through — one just did, and no toolchain pin would have caught it. Closing that needs the app actually run in CI, which is a separate and larger change worth doing on its own merits.

Docs corrected rather than left stale

Two places reasoned from the old pin. Leaving them asserting something false is exactly how the symbol-template constraint was lost the first time — a generator that documented a rule it no longer enforced everywhere.

The generated symbols stay at Template v6.0, but the reason changes. Xcode 26's actool would accept 7.0, so the pin is no longer what enforces 6.0; it is now kept as the floor that anyone still on an Xcode 16 series can read. A 6.0 template renders identically on a newer actool, so there is nothing to gain by raising it.

Verification

I cannot verify this locally — the only Xcode on this machine is 27, so I can't reproduce a 26.3 build. This PR's own CI run is the verification, which is the appropriate place for a CI change to prove itself.

Two things to expect from that run, so neither is misread:

  1. It may fail in the unit-test step regardless of this change. main is currently red there on TunnelNativeColdRestoreTests.swift and TunnelAuthStartupContinuationTests.swift — pre-existing failures that only became visible once the asset-catalog error stopped aborting the build earlier. If this run fails the same way, the pin is fine and those tests are the separate problem.
  2. A newer SDK revalidates the whole project. Surfacing previously-hidden breakage is the point of this change, not an argument against it — but it does mean the first run is as likely to be informative as it is to be green, and a failure should be read before it is reverted.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AWV4MaF9JBcQppSX9UxATa

CI has been compiling against the iOS 18 SDK while the app runs on iOS 26
devices. Anything that only exists, or only misbehaves, on the current SDK
is invisible here, and that gap has started costing real time.

Two cases from one week. App code merged to main needed an SDK symbol the
16.4 toolchain does not have, so it built green in CI and failed on a
developer machine. And `ControlCenter` is absent from the macOS 15 SDK
that 16.4 uses, which is the entire reason WidgetRefresh.reloadControl is
walled off behind `#if os(iOS)` rather than shipping the Control Center
toggle on macOS -- a workaround this bump makes unnecessary, though
removing it is left to its own change.

Still pinned to an exact path rather than to the image default or to
"latest": the original pin's reasoning holds, only its target was stale. A
runner-image bump must not move the toolchain, and with it the SDK the app
is compiled against, without a commit that says so. 26.3 is the newest
stable on the macos-15 image, which also carries 26.2, 26.1.1 and 26.0.1.

Be clear about what this does NOT buy. The job builds and runs unit tests;
it never launches the app, and `-only-testing:networkTests` excludes the ui
tests entirely. A rendering fault that only appears on a current SDK still
gets through -- one just did. Closing that needs the app actually run in
CI, which is a separate and larger change.

Two documents reasoned from the old pin and are corrected rather than left
asserting something false, which is how the symbol-template constraint got
lost the first time. The generated symbols stay at Template v6.0, but the
reason changes: Xcode 26's actool would accept 7.0, so 6.0 is now kept for
compatibility with anyone still on an Xcode 16 series rather than because
CI rejects it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWV4MaF9JBcQppSX9UxATa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant