Skip to content

fix: respect scoped simulator sets in ios runner#354

Merged
thymikee merged 4 commits intomainfrom
codex/fix-ios-runner-device-set
Apr 4, 2026
Merged

fix: respect scoped simulator sets in ios runner#354
thymikee merged 4 commits intomainfrom
codex/fix-ios-runner-device-set

Conversation

@thymikee
Copy link
Copy Markdown
Contributor

@thymikee thymikee commented Apr 3, 2026

Summary

Closes #353.

Fix the iOS XCUITest runner so --ios-simulator-device-set also works for runner-backed commands such as wait, find, press, and snapshot.

The regression was that simulator-scoped simctl calls already respected the custom device set, but the runner’s xcodebuild build-for-testing and test-without-building paths still resolved destinations through Xcode’s XCTest device-set location. That meant a simulator created in a custom set could be opened successfully, but runner commands failed because xcodebuild could not find the UDID.

This change redirects the XCTest device-set path to the requested simulator set for the lifetime of the runner build/session, restores the original state afterward, and hardens the behavior with:

  • a cross-process lock so concurrent agent-device runs do not trample the same XCTest device-set path
  • stale-state recovery so a previous crashed run can restore the original XCTest device-set directory on the next attempt
  • focused unit coverage for redirect, restore, stale redirect recovery, and stale lock takeover

Touched files: 3
Scope stayed within the iOS runner command family.

Validation

  • pnpm format
  • pnpm check:unit

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-04-04 13:46 UTC

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e81569340

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

detached: true,
},
);
const simulatorSetRedirect = await acquireXcodebuildSimulatorSetRedirect(device);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Release simulator-set redirect on abort path

ensureRunnerSession now acquires a long-lived acquireXcodebuildSimulatorSetRedirect handle, but abortAllIosRunnerSessions only kills child processes and never invokes releaseXcodebuildSimulatorSetRedirect. In the client-disconnect path (daemon/transport.ts), this leaves xctest-device-set.lock owned by the still-alive daemon PID, so later scoped simulator commands can block until the 30s lock timeout and fail even though no runner session is active anymore. Please ensure the abort flow also releases redirect handles (or routes through the same stop path that does).

Useful? React with 👍 / 👎.

Comment on lines +112 to +114
const simulatorSetPath = resolveIosSimulatorDeviceSetPath(device.simulatorSetPath);
if (!simulatorSetPath) {
return null;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Coordinate unscoped simulator runs with redirect lock

Returning early when simulatorSetPath is absent skips lock acquisition entirely, so unscoped simulator xcodebuild runs do not coordinate with a concurrent scoped run that has redirected ~/Library/Developer/XCTestDevices to another set. In that overlap, the unscoped run can resolve destinations against the redirected set and fail to find its UDID. Unscoped simulator runner invocations should also participate in the lock (or otherwise guarantee the default XCTest device-set mapping) to avoid cross-session interference.

Useful? React with 👍 / 👎.

@thymikee
Copy link
Copy Markdown
Contributor Author

thymikee commented Apr 3, 2026

Addressed the main hardening points from review in follow-up commit b4d16529:

  • replace symlink cleanup with unlinkSync instead of recursive rmSync, so orphaned XCTestDevices symlinks cannot recurse into the target set
  • emit a warning diagnostic before removing an orphaned redirect with no matching backup
  • write the lock owner file atomically via temp-file + rename
  • reduce swap fragility by installing the redirect symlink through a temp name and renameSync
  • remove the fragile legacy-backup regex coupling by deriving names from shared constants
  • make the redirect tests release handles from finally so assertion failures do not strand temp locks

Validation rerun after the changes:

  • pnpm format
  • pnpm check:unit

I did not add a retry loop around non-agent external interference during the swap. The temp-symlink + rename path narrows that window, but a fully robust answer there would need a broader strategy than the in-repo lock alone.

thymikee and others added 2 commits April 3, 2026 16:31
…ct internals

Address P1 review feedback: abortAllIosRunnerSessions now releases
simulator-set redirect handles after killing processes, preventing
stale locks from blocking subsequent scoped simulator commands.

Simplify redirect internals:
- Store redirect handle directly on session instead of wrapping in closure
- Simplify sameResolvedPath to direct comparison instead of set intersection
- Collapse double liveness check in clearStaleXcodebuildSimulatorSetLock

https://claude.ai/code/session_01VsAUdPKbQoGbwvftBZtXfB
@thymikee thymikee merged commit 48aa329 into main Apr 4, 2026
31 of 32 checks passed
@thymikee thymikee deleted the codex/fix-ios-runner-device-set branch April 4, 2026 13:46
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.

XCUITest runner does not respect --ios-simulator-device-set for xcodebuild destination

2 participants