Skip to content

ci: route all macOS compile/test gates to Swift 6.3 Xcode (match what ships) - #6603

Merged
azooz2003-bit merged 7 commits into
mainfrom
feat-ci-xcode-26
Jun 22, 2026
Merged

azooz2003-bit merged 7 commits into
mainfrom
feat-ci-xcode-26

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jun 22, 2026 •

Copy link
Copy Markdown
Collaborator

What

Route all macOS compile/test CI gates at the newest macOS-26-SDK Xcode (Swift 6.3) instead of the runner's default /Applications/Xcode.app (Xcode 16.4 / Swift 6.1), via a shared scripts/select-ci-xcode.sh, and fix the warnings the 6.3 toolchain newly surfaces.

Why

The Blacksmith/Warp runner images already have Xcode 16.0–16.4 and 26.0–26.3 installed. /Applications/Xcode.app is symlinked to 16.4, and the old "prefer /Applications/Xcode.app" inline selection pinned the test/compile gates to Swift 6.1, while nightly and release already build on 26.x / Swift 6.3 via select-nightly-xcodes.sh. So the gates were older than what we ship: code that compiles locally (6.3) and in release (6.3) could fail only on the 6.1 gates (e.g. isolated deinit, region-based isolation).

How

scripts/select-ci-xcode.sh ranks installed Xcodes by macOS SDK version and picks the highest (falls back to newest available, so it never hard-fails a runner lacking 26.x), exports DEVELOPER_DIR to GITHUB_ENV, and prints xcodebuild -version + xcrun --sdk macosx --show-sdk-path in-process. Each macOS gate's "Select Xcode" step calls it.

Workflows changed

  • test-e2e.yml — e2e gate.
  • ci.yml — all five macOS jobs (app-host-unit-tests, swift-package-tests, tests-build-and-lag, release-build, ui-regressions).
  • perf-activation.yml, reload-build.yml, tmux-corpus.yml, test-depot.yml — one macOS job each.
  • The SDK-path diagnostic now lives inside select-ci-xcode.sh. Previously the trailing xcrun --sdk macosx --show-sdk-path sat in the workflow step after the script and resolved the stale xcode-select default (printed MacOSX15.5.sdk), because the subshell's DEVELOPER_DIR reaches only later steps via GITHUB_ENV. Builds were always correct; only that log line lied.

Warnings surfaced by the 6.3 toolchain (triage)

Diffing the 26.x run against the prior mixed run isolates 66 unique new compiler warnings (the mass XCTest inconsistently imported warnings pre-date the bump). Zero new compile errors. Fixed here (safe, self-contained, root-cause):

  • Deprecation: String(cString:) → String(decoding:as: UTF8.self) in CmuxSettings/SocketControlSettings.swift.
  • #ExistentialAny (any P): 11 sites in CmuxRemoteSession, CmuxRemoteDaemon, CmuxCommandPalette (tests). Purely syntactic; any compiles identically on the 16.x fallback.

Deferred to a focused follow-up (substantive but risky / submodule / non-shipping):

  • Sources/AppDelegate.swift main-actor-isolation + non-Sendable-capture warnings (~20) — typing/focus-sensitive file, needs careful concurrency review + dogfood.
  • CmuxRemoteSession captured-self [#SendableClosureCaptures] (3) — actor-model review.
  • vendor/bonsplit submodule: onChange(of:perform:) deprecation (3) + nonisolated bounds (1) — requires a submodule PR.
  • Sparkle SUAppcastItem(dictionary:) deprecation (1) — vendor private-API.
  • Test-target concurrency warnings in cmuxTests/ (~22) — non-shipping.

Deliberately left on the old toolchain

  • release.yml, nightly.yml, build-ghosttykit.yml — deliberate dual-Xcode split building the Ghostty universal CLI helper on a pre-26 Xcode (HELPER_DEVELOPER_DIR via select-nightly-xcodes.sh). Untouched. (ci.yml's release-ghostty-cli-helper builds the helper with zig, no Xcode selection, and release-build downloads the prebuilt GhosttyKit — so converting release-build to 26.x is correct.)
  • ci-macos-compat.yml — workflow_dispatch-only macOS-version compat matrix; already selects the newest Xcode (not the buggy symlink-preferring logic) and exports XCODE_VER for its cache key, so converting it would gain nothing and risk the cache key. Left as-is.
  • test-ios.yml, ios-testflight.yml — iOS gates that still carry the identical buggy inline block on macos-26 runners. Out of scope for this macOS-gate PR (ios-testflight.yml is a TestFlight submission path). Flagged as a recommended follow-up.

Verification

ci.yml run on this branch selected Xcode 26.3 / MacOSX26.2.sdk and all macOS jobs are green: app-host unit tests (1-4/4), swift-package-tests, tests-build-and-lag, ui-regressions, release-build. The standalone e2e AutomationSocketUITests run confirms Selected Xcode … macOS SDK 26.2; its 4 test failures are a pre-existing GUI-activation limitation on the default runner (Failed to activate application … Running Background), reproduced identically on Xcode 16.4, not a toolchain regression.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Route all macOS compile/test CI gates to the newest Xcode with the macOS 26 SDK (Swift 6.3) via scripts/select-ci-xcode.sh. This aligns CI with release builds, replaces inline Xcode selection, and prints accurate SDK diagnostics; release/nightly and Ghostty dual-Xcode jobs are unchanged.

  • Bug Fixes
    • Replace deprecated String(cString:) with String(decoding:as:) in CmuxSettings/SocketControlSettings.
    • Adopt any existentials in CmuxRemoteSession, CmuxRemoteDaemon, and CmuxCommandPalette tests.

Written for commit b321e34. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Chores
    • Updated macOS CI workflows to use a single, consistent Xcode selection process based on installed SDK versions.
    • This improves reliability and consistency across automated gates (builds, unit tests, Swift package tests, and UI regressions) by ensuring the intended Xcode environment is used.
    • Reduced duplicated “select Xcode” logic across workflows for easier maintenance.
  • Chores
    • Added a shared CI helper to select Xcode, export the developer directory, and run SDK diagnostics.

The runner images ship Xcode 16.x (macOS 15 SDK / Swift 6.1) AND Xcode 26.x
(macOS 26 SDK / Swift 6.3), but /Applications/Xcode.app is symlinked to 16.4.
The old 'prefer /Applications/Xcode.app' selection pinned the test gate to
Swift 6.1, while nightly + release already build on 26.x via
select-nightly-xcodes.sh. That divergence lets code that compiles locally (6.3)
and ships (6.3) fail only on the 6.1 test gate (isolated deinit, region-based
isolation differences, etc).

Add scripts/select-ci-xcode.sh: pick the highest macOS-SDK Xcode (falls back to
newest available so it never hard-fails a runner without 26.x). Wire test-e2e's
Select Xcode step to it. This aligns the test toolchain with what ships.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jun 22, 2026 10:37pm

@coderabbitai

coderabbitai Bot commented Jun 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Inline Xcode-discovery shell logic scattered across six CI workflows is extracted into a new scripts/select-ci-xcode.sh script that scans for Xcode*.app installations, ranks each by macOS SDK version, selects the highest-ranked candidate, exports DEVELOPER_DIR to both shell and GITHUB_ENV, and verifies the toolchain. All workflows delegate Xcode selection to this single script. The PR also systematically migrates Error and protocol types to Swift 6 existential form (any Error, any DispatchSourceTimer, any NSTextViewDelegate) across RemoteSession, RemoteDaemon, and test packages. A minor improvement refactors symlink target string construction to use direct UTF-8 byte decoding.

Changes

Xcode CI Selection Extraction

Layer / File(s) Summary
SDK ranking and Xcode discovery
scripts/select-ci-xcode.sh
New Bash script with strict mode, sdk_rank() function computing major*1000+minor, iteration over sorted Xcode*.app entries under CMUX_XCODE_APPLICATIONS_DIR (default /Applications), best-candidate tracking by rank (alphabetical tiebreaker), DEVELOPER_DIR export to shell and GITHUB_ENV, error-on-no-match validation, and xcodebuild -version and xcrun verification.
Workflow delegation across CI jobs
.github/workflows/ci.yml, .github/workflows/test-e2e.yml, .github/workflows/perf-activation.yml, .github/workflows/reload-build.yml, .github/workflows/test-depot.yml, .github/workflows/tmux-corpus.yml
Inline Xcode-discovery/DEVELOPER_DIR-export shell blocks in the "Select Xcode" step of six workflows are replaced with single calls to ./scripts/select-ci-xcode.sh. Affects five separate jobs in ci.yml (app-host-unit-tests, swift-package-tests, tests-build-and-lag, release-build, ui-regressions) plus five additional workflow files.

Swift 6 Existential Type Migration

Layer / File(s) Summary
Storage and value type conversions
Packages/macOS/CmuxRemoteDaemon/Sources/CmuxRemoteDaemon/Client/RemoteDaemonRPCClient.swift, Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Session/RemoteSessionCoordinator.swift, Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Process/RemoteSessionProcessRunner.swift, Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Values/LockedResult.swift, Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Values/PendingPTYBridgeStart.swift
Timer properties change from DispatchSourceTimer? to (any DispatchSourceTimer)?; error storage in state containers and value types changes from Error? to any Error? in Result types, maintaining optionality and error-handling semantics.
Callback and public API error types
Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Session/RemoteSessionCoordinator+PTYBridge.swift, Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Session/RemoteSessionCoordinator+Upload.swift
Callback closure Result error types change from Error to any Error in PTY bridge completion and public uploadDroppedFiles API signature, aligning with Swift 6 existential error typing.
Test helper protocol updates
Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/FocusGuards/CommandPaletteFocusStealingTests.swift
DelegateTrackingTextView overridden delegate property type annotation changes from NSTextViewDelegate? to (any NSTextViewDelegate)? while preserving getter/setter and delegate-read counting behavior.

Symlink String Handling Improvement

Layer / File(s) Summary
Direct UTF-8 byte decoding
Packages/macOS/CmuxSettings/Sources/CmuxSettings/SocketControl/SocketControlSettings.swift
Symlink target string construction refactored from manual NUL-terminator write with String(cString:) to direct UTF-8 byte decoding via buffer.prefix(length), eliminating the terminator write step.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~13 minutes

Possibly related PRs

  • manaflow-ai/cmux#4922: Modifies the same "Select Xcode" step in test-e2e.yml using inline find/sort/tail selection logic, which this PR extracts and centralizes.
  • manaflow-ai/cmux#5077: Both PRs change GitHub Actions "Select Xcode" logic by scanning installed Xcode*.app SDK versions, ranking/selecting a specific Xcode/toolchain, and exporting DEVELOPER_DIR for subsequent build steps.
  • manaflow-ai/cmux#6354: Adds the .github/workflows/reload-build.yml workflow with inline Xcode-selection logic; this PR refactors that workflow to use the new centralized script.

Suggested reviewers

  • lawrencecchen

Poem

🐇 Hop hop, the workflows now gleam,
A script extracts the Xcode dream.
SDK ranks sorted with care,
Swift 6's any types everywhere.
DEVELOPER_DIR set fair—
Our symlinks decoded with flair! 🍎


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux Source Artifacts ❌ Error HEAD commit adds 25+ files in .claude/ directory (e.g., .claude/commands/, .claude/skills/, .claude/scheduled_tasks.lock), which violates the source-control-artifacts rule prohibiting hidden scratc... Remove all .claude/ directory contents from the commit except .claude/worktrees/ (which is in .gitignore), or add appropriate .gitignore patterns for .claude/commands, .claude/skills, and .claude/scheduled_tasks.lock.
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (21 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: routing macOS CI gates to Swift 6.3 Xcode to match production builds, which is the core objective.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed All Swift changes are existential type conformance updates (Error→any Error, concrete protocols→any) for Swift 6; no @MainActor, nonisolated, or isolation declaration changes introduced; existing @...
Cmux Swift Blocking Runtime ✅ Passed PR makes only syntactic type annotation changes (Error→any Error) and string encoding fix. All blocking patterns (NSLock, DispatchSemaphore, semaphore.wait) pre-existed and are unchanged; no new bl...
Cmux Expensive Synchronous Load ✅ Passed PR contains only CI workflow updates, Swift 6 type annotation fixes, and a symlink reading improvement; no expensive agent-history loads or synchronous I/O on main actor/interactive paths added.
Cmux Cache Substitution Correctness ✅ Passed PR makes no cache substitution changes: workflows delegate to fresh Xcode discovery, Swift changes are type annotations only, and SocketControlSettings reads from fresh syscalls with no persistence.
Cmux No Hacky Sleeps ✅ Passed The new select-ci-xcode.sh shell script uses deterministic Xcode selection with no sleep, poll, delay, or timing-based workarounds; workflow YAML changes are out of scope.
Cmux Algorithmic Complexity ✅ Passed All code changes are either CI configuration, type signature updates, or involve fixed-size collections (2-5 Xcode installations). No scalable collections, nested scans, or unbenchmarked algorithms...
Cmux Swift Concurrency ✅ Passed PR makes only syntactic type annotation updates (any existential syntax) and deprecation fixes for Swift 6.3; introduces zero legacy async patterns.
Cmux Swift @Concurrent ✅ Passed PR contains no async function isolation changes; all Swift changes are type annotations updating existential forms (Error→any Error, protocols→any protocols) for Swift 6 compatibility.
Cmux Swift File And Package Boundaries ✅ Passed All Swift changes are focused type updates (Swift 6 existential 'any' compatibility) or a focused bug fix, with no new files, no new mixed responsibilities, and all changes staying within file size...
Cmux Swiftpm Lockfiles ✅ Passed PR contains no SwiftPM package, Package.swift, Package.resolved, or .gitignore changes. Changes are workflow routing, shell script, and Swift existential-type syntax updates—none trigger the swiftp...
Cmux Swift Logging ✅ Passed PR contains no Swift logging violations. Shell script output is appropriate CI infrastructure logging; Swift changes only modify type annotations without adding logging statements.
Cmux User-Facing Error Privacy ✅ Passed PR contains CI build script and type annotation changes. Script outputs are developer/CI diagnostics not shown to end users. No prohibited sensitive information, vendor names, credentials, or raw e...
Cmux Full Internationalization ✅ Passed All changes are CI infrastructure, type annotations for Swift 6.3 compatibility, or internal implementation details—no user-facing text is added or modified, so no localization is required.
Cmux Swiftui State Layout ✅ Passed PR contains no SwiftUI state management changes. Changes are workflow updates and Swift protocol/type updates (existential-any syntax for Swift 6 compatibility) with no ObservableObject, @Published...
Cmux Architecture Rethink ✅ Passed PR does not violate swift-architectural-rethink.md rules. Changes are: (1) CI infrastructure script consolidation (select-ci-xcode.sh), (2) Swift 6 type signature updates (any Error, any DispatchSo...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR does not add or materially change standalone cmux-owned windows; modifications are CI workflow changes and Swift 6 type annotation updates (Error→any Error, DispatchSourceTimer existential types...
Cmux No Test Or Debug Seam In Production Source ✅ Passed All Swift changes in production Sources/ paths are Swift 6 compatibility updates (changing Error to any Error, DispatchSourceTimer to any DispatchSourceTimer). No test/debug seams, visibility widen...
Description check ✅ Passed The PR description is comprehensive and well-structured, covering the problem statement, solution, implementation details, scope, verification, and deferred work.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-ci-xcode-26

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jun 22, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR aligns all macOS CI compile/test gates with the Swift 6.3 toolchain (Xcode 26.x / macOS 26 SDK) that release and nightly already use, by introducing scripts/select-ci-xcode.sh and replacing the identical inline Xcode-selection blocks spread across six workflow files. It also fixes the two categories of Swift 6.3 warnings the bump surfaces: the deprecated String(cString:) call in SocketControlSettings and eleven #ExistentialAny sites across CmuxRemoteSession, CmuxRemoteDaemon, and a test file.

  • New script scripts/select-ci-xcode.sh ranks every installed Xcode by its macOS SDK major/minor version, exports DEVELOPER_DIR to $GITHUB_ENV, and falls back to the newest available Xcode so the gate never hard-fails on a runner without a 26.x image.
  • Six workflow files (ci.yml, perf-activation.yml, reload-build.yml, test-depot.yml, test-e2e.yml, tmux-corpus.yml) replace identical inline Xcode-selection blocks with ./scripts/select-ci-xcode.sh.
  • Swift source fixes add any to eleven existential type positions and replace the deprecated String(cString:) with String(decoding:as: UTF8.self) using UInt8(bitPattern:) for correct sign-to-unsigned conversion.

Confidence Score: 5/5

Safe to merge. All changes are either DRY refactors of duplicated CI shell blocks, mechanical Swift 6.3 existential-keyword additions, or a well-scoped deprecation fix — none alter production runtime logic.

The CI changes remove six identical inline blocks and centralise them in a script whose selection logic is straightforward and tested in a live run. The Swift changes are purely syntactic any-keyword additions required by #ExistentialAny — compilers on both 16.x and 26.x accept them identically. The String(cString:) replacement correctly bounds the read with buffer.prefix(length) and reinterprets sign bits via UInt8(bitPattern:). No new concurrency primitives, no new blocking calls, and no production behaviour changes.

No files require special attention.

Important Files Changed

Filename Overview
scripts/select-ci-xcode.sh New shared CI helper. Ranks installed Xcodes by macOS SDK version (maj×1000+min), exports DEVELOPER_DIR to GITHUB_ENV, and falls back gracefully. The sdk_rank function correctly handles major-only, major.minor, and major.minor.patch SDK strings. The GITHUB_ENV guard allows local use without a GitHub environment.
.github/workflows/ci.yml Removes five copies of the inline Xcode-selection block (including the stale xcrun SDK diagnostic that resolved against the old xcode-select default) and replaces each with ./scripts/select-ci-xcode.sh.
.github/workflows/perf-activation.yml One inline Xcode-selection block replaced with ./scripts/select-ci-xcode.sh. No logic change.
.github/workflows/reload-build.yml One inline Xcode-selection block (the compressed single-line variant) replaced with ./scripts/select-ci-xcode.sh. No logic change.
.github/workflows/test-depot.yml One inline Xcode-selection block replaced with ./scripts/select-ci-xcode.sh. No logic change.
.github/workflows/test-e2e.yml One inline Xcode-selection block replaced with ./scripts/select-ci-xcode.sh. The stale xcrun diagnostic from the prior thread is eliminated by the script's in-process xcrun call.
.github/workflows/tmux-corpus.yml One inline Xcode-selection block replaced with ./scripts/select-ci-xcode.sh. No logic change.
Packages/macOS/CmuxSettings/Sources/CmuxSettings/SocketControl/SocketControlSettings.swift Replaces deprecated String(cString:) with String(decoding:as: UTF8.self) using UInt8(bitPattern:) to correctly reinterpret signed CChar bytes as unsigned UInt8. The null-terminator step is correctly dropped since buffer.prefix(length) bounds the read.
Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Values/LockedResult.swift Three Result<T, Error> occurrences updated to Result<T, any Error> for #ExistentialAny compliance. No logic change.
Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Session/RemoteSessionCoordinator+PTYBridge.swift Closure type annotation updated from Result<…, Error> to Result<…, any Error>. The surrounding semaphore/DispatchSemaphore pattern is pre-existing and not introduced by this PR.
Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Session/RemoteSessionCoordinator+Upload.swift Public API completion handler updated from Result<[String], Error> to Result<[String], any Error>. Correct existential fix; no semantic change.
Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Session/RemoteSessionCoordinator.swift remotePortPollTimer type updated from DispatchSourceTimer? to (any DispatchSourceTimer)?. Correct existential fix.
Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Process/RemoteSessionProcessRunner.swift Two Error? stored properties updated to (any Error)?. Correct existential fix.
Packages/macOS/CmuxRemoteDaemon/Sources/CmuxRemoteDaemon/Client/RemoteDaemonRPCClient.swift webSocketKeepaliveTimer type updated from DispatchSourceTimer? to (any DispatchSourceTimer)?. Correct existential fix.
Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Values/PendingPTYBridgeStart.swift completion closure type updated to use any Error. Correct existential fix.
Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/FocusGuards/CommandPaletteFocusStealingTests.swift Test file: delegate property override type updated to (any NSTextViewDelegate)?. Correct existential fix; lives in Tests/ so no production seam concern.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A([select-ci-xcode.sh]) --> B[find Xcode*.app under /Applications]
    B --> C{Any apps found?}
    C -- No --> FAIL[exit 1]
    C -- Yes --> D[For each Xcode.app in sort order]
    D --> E[xcrun --sdk macosx --show-sdk-version\nwith per-app DEVELOPER_DIR]
    E --> F{SDK version\nparseable?}
    F -- No --> G[warn & skip]
    G --> D
    F -- Yes --> H[Compute rank =\nmaj×1000 + min]
    H --> I{rank >= BEST_RANK?}
    I -- No --> D
    I -- Yes --> J[Update BEST_DIR / BEST_VER / BEST_RANK]
    J --> D
    D -- loop done --> K{BEST_DIR set?}
    K -- No --> FAIL
    K -- Yes --> L[Write DEVELOPER_DIR to GITHUB_ENV]
    L --> M[export DEVELOPER_DIR in-process]
    M --> N[xcodebuild -version]
    N --> O[xcrun --sdk macosx --show-sdk-path\ndiagnostic only — uses in-process DEVELOPER_DIR]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A([select-ci-xcode.sh]) --> B[find Xcode*.app under /Applications]
    B --> C{Any apps found?}
    C -- No --> FAIL[exit 1]
    C -- Yes --> D[For each Xcode.app in sort order]
    D --> E[xcrun --sdk macosx --show-sdk-version\nwith per-app DEVELOPER_DIR]
    E --> F{SDK version\nparseable?}
    F -- No --> G[warn & skip]
    G --> D
    F -- Yes --> H[Compute rank =\nmaj×1000 + min]
    H --> I{rank >= BEST_RANK?}
    I -- No --> D
    I -- Yes --> J[Update BEST_DIR / BEST_VER / BEST_RANK]
    J --> D
    D -- loop done --> K{BEST_DIR set?}
    K -- No --> FAIL
    K -- Yes --> L[Write DEVELOPER_DIR to GITHUB_ENV]
    L --> M[export DEVELOPER_DIR in-process]
    M --> N[xcodebuild -version]
    N --> O[xcrun --sdk macosx --show-sdk-path\ndiagnostic only — uses in-process DEVELOPER_DIR]
Loading

Reviews (6): Last reviewed commit: "Merge branch 'main' into feat-ci-xcode-2..." | Re-trigger Greptile

Comment thread .github/workflows/test-e2e.yml Outdated
Comment on lines 93 to 97
- name: Select Xcode
run: |
set -euo pipefail
if [ -d "/Applications/Xcode.app/Contents/Developer" ]; then
XCODE_DIR="/Applications/Xcode.app/Contents/Developer"
else
XCODE_APP="$(
find /Applications -maxdepth 1 -name 'Xcode*.app' -print 2>/dev/null \
| sort \
| tail -n 1 \
|| true
)"
if [ -n "$XCODE_APP" ]; then
XCODE_DIR="$XCODE_APP/Contents/Developer"
else
echo "No Xcode.app found under /Applications" >&2
exit 1
fi
fi
echo "DEVELOPER_DIR=$XCODE_DIR" >> "$GITHUB_ENV"
export DEVELOPER_DIR="$XCODE_DIR"
xcodebuild -version
./scripts/select-ci-xcode.sh
xcrun --sdk macosx --show-sdk-path

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 xcrun verification uses the unselected default Xcode

./scripts/select-ci-xcode.sh writes DEVELOPER_DIR to $GITHUB_ENV and runs export DEVELOPER_DIR inside its own subshell, but neither propagates to the parent shell running this step. GitHub Actions only makes $GITHUB_ENV entries available to subsequent steps, not the current one. So the xcrun --sdk macosx --show-sdk-path call on line 97 resolves against the system default (/Applications/Xcode.app → Xcode 16.4 / macOS 15 SDK), printing a misleading path in the log even though subsequent steps correctly use the new Xcode via DEVELOPER_DIR from $GITHUB_ENV.

The remaining macOS jobs still ran the old "prefer /Applications/Xcode.app"
inline block, which pins them to Xcode 16.4 (macOS 15 SDK / Swift 6.1) because
/Applications/Xcode.app is symlinked to 16.4 on the runner images. That is the
same divergence the e2e gate already fixed: code that compiles locally (6.3) and
ships via nightly/release (6.3) could fail only on these 6.1 gates.

Replace the inline block with ./scripts/select-ci-xcode.sh (picks the highest
macOS-SDK Xcode, falls back to newest) in the macOS jobs of ci.yml,
perf-activation.yml, reload-build.yml, tmux-corpus.yml, and test-depot.yml.
Trailing `xcrun --sdk macosx --show-sdk-path` diagnostics are preserved.

Left intact: release.yml, nightly.yml, build-ghosttykit.yml (deliberate
dual-Xcode split building the Ghostty universal CLI helper on a pre-26 Xcode).
ci-macos-compat.yml is workflow_dispatch-only, already selects the newest Xcode
(not the buggy symlink-preferring logic), and exports XCODE_VER for its cache
key, so it is left as-is.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@azooz2003-bit azooz2003-bit changed the title ci: select Swift 6.3 Xcode for the e2e test gate (match what ships) ci: route all macOS compile/test gates to Swift 6.3 Xcode (match what ships) Jun 22, 2026
azooz2003-bit added a commit that referenced this pull request Jun 22, 2026
…ed fix)

The interim nonisolated deinit (09ecbb9) was rejected by BOTH toolchains:
local Swift 6.3 and CI Swift 6.1 both forbid a nonisolated deinit reading the
instance's own @mainactor stored properties. The original isolated deinit
compiles cleanly on Swift 6.3 (the local refactor toolchain), restoring a green
local build baseline for the batch integrators. It needs Swift 6.1's
IsolatedDeinit only on the old CI gate, which is being retired by the move to
the Swift 6.3 / Xcode 26 CI toolchain (PR #6603); there it is valid with no flag.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
azooz2003-bit and others added 2 commits June 22, 2026 11:49
The trailing `xcrun --sdk macosx --show-sdk-path` lived in the workflow step
*after* `./scripts/select-ci-xcode.sh`. The script runs in a subshell and only
propagates DEVELOPER_DIR via GITHUB_ENV, which applies to later steps, not the
current shell, so that bare xcrun resolved the stale xcode-select default
(e.g. printed MacOSX15.5.sdk even though the build steps correctly used the
selected Xcode 26.3 / MacOSX26.2 SDK). Move the diagnostic into the script,
right after it exports DEVELOPER_DIR in-process, and drop the misleading
trailing copies from ci.yml, test-e2e.yml, and test-depot.yml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e toolchain bump

The macOS CI gates now build on Xcode 26.3 (Swift 6.3 / macOS 26 SDK). The
6.3 compiler surfaces warnings the 6.1 gate did not. Fix the safe, self-contained
ones at the root cause (no -w, no warnings-as-errors disable, no #if):

- SocketControlSettings: String(cString:) is deprecated; decode the readlink
  bytes explicitly with String(decoding:as: UTF8.self) over the valid prefix.
- CmuxRemoteSession / CmuxRemoteDaemon / CmuxCommandPalette: write protocol
  existentials as `any P` (any Error, any DispatchSourceTimer, any
  NSTextViewDelegate) per [#ExistentialAny]. Purely syntactic; `any` compiles
  identically on the 16.x fallback toolchain.

Deferred to a follow-up (see PR description): main-actor isolation / non-Sendable
capture warnings in Sources/AppDelegate.swift (typing-sensitive, needs dogfood),
CmuxRemoteSession captured-`self` Sendable-closure warnings (actor-model review),
the bonsplit submodule onChange/bounds warnings (submodule PR), the Sparkle
SUAppcastItem deprecation (private-API), and test-target concurrency warnings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/macOS/CmuxSettings/Sources/CmuxSettings/SocketControl/SocketControlSettings.swift`:
- Line 317: The readlink buffer decoding on line 317 uses String(decoding:as:)
which silently replaces invalid UTF-8 bytes with U+FFFD, corrupting symlink
target canonicalization. Replace this with the failable UTF-8 decode pattern
String(bytes:encoding:.utf8) that is already used elsewhere in the codebase
(ControlClientLineReader.swift, CmuxTopProcessArguments.swift,
TerminalSSHSessionDetector.swift) for untrusted binary data. This will ensure
that invalid UTF-8 sequences in the readlink result cause the operation to fail
fast instead of being silently corrupted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 541ee2c7-31c9-4381-9496-e91ce5cb60af

📥 Commits

Reviewing files that changed from the base of the PR and between 3d7cbe4 and 380cd75.

📒 Files selected for processing (13)
  • .github/workflows/ci.yml
  • .github/workflows/test-depot.yml
  • .github/workflows/test-e2e.yml
  • Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/FocusGuards/CommandPaletteFocusStealingTests.swift
  • Packages/macOS/CmuxRemoteDaemon/Sources/CmuxRemoteDaemon/Client/RemoteDaemonRPCClient.swift
  • Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Process/RemoteSessionProcessRunner.swift
  • Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Session/RemoteSessionCoordinator+PTYBridge.swift
  • Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Session/RemoteSessionCoordinator+Upload.swift
  • Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Session/RemoteSessionCoordinator.swift
  • Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Values/LockedResult.swift
  • Packages/macOS/CmuxRemoteSession/Sources/CmuxRemoteSession/Values/PendingPTYBridgeStart.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/SocketControl/SocketControlSettings.swift
  • scripts/select-ci-xcode.sh
💤 Files with no reviewable changes (3)
  • .github/workflows/test-depot.yml
  • .github/workflows/test-e2e.yml
  • .github/workflows/ci.yml

guard length > 0 else { return nil }
buffer[Int(length)] = 0
let target = String(cString: buffer)
let target = String(decoding: buffer.prefix(Int(length)).map { UInt8(bitPattern: $0) }, as: UTF8.self)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate this helper and its callers/tests.
rg -n -C3 '\bsymbolicLinkTarget\s*\(' --type swift
rg -n -C3 '\bcanonicalSocketPath\s*\(' --type swift
rg -n -C3 'symlink\(' --type swift

Repository: manaflow-ai/cmux

Length of output: 10184


🏁 Script executed:

# Read the complete function around line 317
sed -n '313,327p' Packages/macOS/CmuxSettings/Sources/CmuxSettings/SocketControl/SocketControlSettings.swift

Repository: manaflow-ai/cmux

Length of output: 835


🏁 Script executed:

# Check for any existing tests of invalid UTF-8 or malformed symlink targets
rg -n 'invalid|malform|UTF-8|utf8|non.*utf|encode' --type swift cmuxTests/ Packages/macOS/CmuxControlSocket/Tests/ | grep -i 'symlink\|readlink\|target' | head -20

Repository: manaflow-ai/cmux

Length of output: 2305


🏁 Script executed:

# Search test files for symbolicLinkTarget or canonicalSocketPath testing
rg -n 'symbolicLinkTarget|canonicalSocketPath' --type swift cmuxTests/ Packages/

Repository: manaflow-ai/cmux

Length of output: 1223


🏁 Script executed:

# Check if there's any documentation or test comment about encoding expectations
rg -n 'readlink|symlink.*UTF|encoding' --type swift Packages/macOS/CmuxSettings/Sources/CmuxSettings/SocketControl/SocketControlSettings.swift -B2 -A2

Repository: manaflow-ai/cmux

Length of output: 463


🏁 Script executed:

# Check macOS/POSIX docs and any similar code patterns in the repo
rg -n 'String\(decoding.*UTF8' --type swift | head -15

Repository: manaflow-ai/cmux

Length of output: 2097


🏁 Script executed:

# Look for existing failable UTF-8 decoding patterns in the codebase
rg -n 'String\(bytes.*encoding.*utf' --type swift | head -15

Repository: manaflow-ai/cmux

Length of output: 2110


🏁 Script executed:

# Check if there are any symlink-related security or correctness comments
rg -n 'symbolicLink|readlink' --type swift -B3 -A3 cmuxTests/CMUXCLIErrorOutputRegressionTests.swift

Repository: manaflow-ai/cmux

Length of output: 42


Use a failable UTF-8 decode for readlink bytes.

String(decoding:as:) silently replaces invalid UTF-8 bytes with U+FFFD, which can corrupt symlink target canonicalization. Symlink paths from readlink() should fail fast on invalid UTF-8. The codebase uses the failable pattern String(bytes:encoding:.utf8) elsewhere for untrusted binary data (ControlClientLineReader.swift, CmuxTopProcessArguments.swift, TerminalSSHSessionDetector.swift).

Suggested fix
-        let target = String(decoding: buffer.prefix(Int(length)).map { UInt8(bitPattern: $0) }, as: UTF8.self)
+        let targetBytes = buffer.prefix(Int(length)).map { UInt8(bitPattern: $0) }
+        guard let target = String(bytes: targetBytes, encoding: .utf8) else {
+            return nil
+        }
🧰 Tools
🪛 SwiftLint (0.64.0)

[Warning] 317-317: Prefer failable String(bytes:encoding:) initializer when converting Data to String

(optional_data_string_conversion)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/macOS/CmuxSettings/Sources/CmuxSettings/SocketControl/SocketControlSettings.swift`
at line 317, The readlink buffer decoding on line 317 uses String(decoding:as:)
which silently replaces invalid UTF-8 bytes with U+FFFD, corrupting symlink
target canonicalization. Replace this with the failable UTF-8 decode pattern
String(bytes:encoding:.utf8) that is already used elsewhere in the codebase
(ControlClientLineReader.swift, CmuxTopProcessArguments.swift,
TerminalSSHSessionDetector.swift) for untrusted binary data. This will ensure
that invalid UTF-8 sequences in the readlink result cause the operation to fail
fast instead of being silently corrupted.

Source: Linters/SAST tools

@azooz2003-bit
azooz2003-bit merged commit da3d1a0 into main Jun 22, 2026
37 checks passed
azooz2003-bit added a commit that referenced this pull request Jun 22, 2026
…ft 6.3)

Incorporate the merged toolchain bump (cmux PR #6603) onto the isolated
integration branch so its CI runs on Xcode 26.3 / Swift 6.3 — matching the
local integrator build and main. Validates the whole refactor branch (incl. the
restored Workspace isolated deinit) on the real CI toolchain, not just locally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview – cmux — b321e342 Deployed Jun 22, 2026 by vercel[bot]
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