Skip to content

Commit 2dd6d4b

Browse files
cipolleschimeta-codesync[bot]
authored andcommitted
Use macOS 26 runners for iOS E2E tests (#57993)
Summary: Moves the RNTester and template app iOS E2E jobs from `macos-15-large` to `macos-26-large`. The new runner image ships with Xcode 26, which is now required by `idb-companion`, and the jobs use the image default Xcode so its hosted simulator platform is available. The Maestro runner discovers an available iPhone Pro simulator and boots it by UDID instead of depending on a device name tied to an older runner image. ### CI follow-ups - `test_e2e_ios_templateapp / test (Debug)` failed before the E2E tests because the explicitly selected Xcode 26.0.1 installation did not include the iOS Simulator platform. Removed the explicit Xcode selection from both E2E workflows so `macos-26-large` uses its default Xcode 26.6 installation and hosted simulator setup. - The RNTester E2E attempts then installed `idb-companion` successfully but failed to boot the hardcoded `iPhone 16 Pro`, which is not present on the macOS 26 image. Updated the Maestro iOS runner to discover an available iPhone Pro from the newest installed runtime and boot it by UDID, with a unit test covering selection across runtimes. ## Changelog: [INTERNAL] [FIXED] - Run iOS E2E tests on macOS 26 runners with Xcode 26. Pull Request resolved: #57993 Test Plan: - `git diff --check` - `yarn prettier --check .github/workflow-scripts/maestro-ios.js .github/workflow-scripts/__tests__/maestro-ios-test.js .github/workflows/e2e-ios-rntester.yml .github/workflows/e2e-ios-templateapp.yml` - `ruby -ryaml -e "ARGV.each { |path| YAML.parse_file(path) }" .github/workflows/e2e-ios-rntester.yml .github/workflows/e2e-ios-templateapp.yml` - `node --check .github/workflow-scripts/maestro-ios.js` - `yarn jest .github/workflow-scripts/__tests__/maestro-ios-test.js --runInBand --config '{"testEnvironment":"node","transform":{}}'` Reviewed By: alanleedev, mdvacca Differential Revision: D116460922 Pulled By: cipolleschi fbshipit-source-id: e769f017b874c9da76d63f19727c358719dbdbc6
1 parent 526016d commit 2dd6d4b

4 files changed

Lines changed: 46 additions & 23 deletions

File tree

‎.github/workflow-scripts/__tests__/maestro-ios-test.js‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jest.mock('fs', () => ({
2020
const childProcess = require('child_process');
2121
const fs = require('fs');
2222

23-
const {executeFlows} = require('../maestro-ios');
23+
const {executeFlows, findAvailableSimulator} = require('../maestro-ios');
2424

2525
describe('Maestro iOS runner', () => {
2626
beforeEach(() => {
@@ -59,4 +59,23 @@ describe('Maestro iOS runner', () => {
5959
expect(call[0]).toContain('test "flow.yml"');
6060
}
6161
});
62+
63+
it('selects an iPhone Pro simulator from the latest runtime', () => {
64+
childProcess.execSync.mockReturnValue(
65+
JSON.stringify({
66+
devices: {
67+
'iOS 18.5': [{name: 'iPhone 16 Pro', udid: 'old-pro'}],
68+
'iOS 26.5': [
69+
{name: 'iPhone 17 Pro Max', udid: 'new-pro-max'},
70+
{name: 'iPhone 17 Pro', udid: 'new-pro'},
71+
],
72+
},
73+
}),
74+
);
75+
76+
expect(findAvailableSimulator()).toEqual({
77+
name: 'iPhone 17 Pro',
78+
udid: 'new-pro',
79+
});
80+
});
6281
});

‎.github/workflow-scripts/maestro-ios.js‎

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,26 @@ node maestro-android.js <path to app> <app_id> <maestro_flow> <flavor> <working_
2525

2626
const MAX_ATTEMPTS = 5;
2727

28-
function launchSimulator(simulatorName) {
29-
console.log(`Launching simulator ${simulatorName}`);
28+
function findAvailableSimulator() {
29+
const output = childProcess.execSync(
30+
'xcrun simctl list devices available -j',
31+
);
32+
const devices = Object.values(JSON.parse(String(output)).devices)
33+
.flat()
34+
.reverse();
35+
const simulator = devices.find(device => /^iPhone .* Pro$/.test(device.name));
36+
37+
if (simulator == null) {
38+
throw new Error('Unable to find an available iPhone Pro simulator');
39+
}
40+
41+
return simulator;
42+
}
43+
44+
function launchSimulator(simulator) {
45+
console.log(`Launching simulator ${simulator.name} (${simulator.udid})`);
3046
try {
31-
childProcess.execSync(`xcrun simctl boot "${simulatorName}"`);
47+
childProcess.execSync(`xcrun simctl boot "${simulator.udid}"`);
3248
} catch (error) {
3349
if (
3450
!error.message.includes('Unable to boot device in current state: Booted')
@@ -43,14 +59,6 @@ function installAppOnSimulator(appPath) {
4359
childProcess.execSync(`xcrun simctl install booted "${appPath}"`);
4460
}
4561

46-
function extractSimulatorUDID() {
47-
console.log('Retrieving device UDID');
48-
const command = `xcrun simctl list devices booted -j | jq -r '[.devices[]] | add | first | .udid'`;
49-
const udid = String(childProcess.execSync(command)).trim();
50-
console.log(`UDID is ${udid}`);
51-
return udid;
52-
}
53-
5462
function bringSimulatorInForeground() {
5563
console.log('Bringing simulator in foreground');
5664
childProcess.execSync('open -a simulator');
@@ -166,13 +174,12 @@ async function main(args = process.argv.slice(2)) {
166174
console.info(`WORKING_DIRECTORY: ${workingDirectory}`);
167175
console.info('==============================\n');
168176

169-
const simulatorName = 'iPhone 16 Pro';
170-
launchSimulator(simulatorName);
177+
const simulator = findAvailableSimulator();
178+
launchSimulator(simulator);
171179
installAppOnSimulator(appPath);
172-
const udid = extractSimulatorUDID();
173180
bringSimulatorInForeground();
174-
await launchAppOnSimulator(appId, udid, isDebug);
175-
executeFlows(appId, udid, maestroFlow, jsengine);
181+
await launchAppOnSimulator(appId, simulator.udid, isDebug);
182+
executeFlows(appId, simulator.udid, maestroFlow, jsengine);
176183
console.log('Test finished');
177184
}
178185

@@ -182,4 +189,5 @@ if (require.main === module) {
182189

183190
module.exports = {
184191
executeFlows,
192+
findAvailableSimulator,
185193
};

‎.github/workflows/e2e-ios-rntester.yml‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ on:
1616

1717
jobs:
1818
test:
19-
runs-on: macos-15-large
19+
runs-on: macos-26-large
2020
outputs:
2121
status: ${{ steps.report-status.outputs.status }}
2222
strategy:
@@ -35,8 +35,6 @@ jobs:
3535
path: /tmp/RNTesterBuild/RNTester.app
3636
- name: Check downloaded folder content
3737
run: ls -lR /tmp/RNTesterBuild
38-
- name: Setup xcode
39-
uses: ./.github/actions/setup-xcode
4038
- name: Run E2E Tests
4139
id: run-tests
4240
continue-on-error: true

‎.github/workflows/e2e-ios-templateapp.yml‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ on:
1616

1717
jobs:
1818
test:
19-
runs-on: macos-15-large
19+
runs-on: macos-26-large
2020
outputs:
2121
status: ${{ steps.report-status.outputs.status }}
2222
strategy:
@@ -26,8 +26,6 @@ jobs:
2626
steps:
2727
- name: Checkout
2828
uses: actions/checkout@v6
29-
- name: Setup xcode
30-
uses: ./.github/actions/setup-xcode
3129
- name: Setup node.js
3230
uses: ./.github/actions/setup-node
3331
- name: Run yarn

0 commit comments

Comments
 (0)