2121jobs :
2222 e2e-test :
2323 name : E2E-Detox ${{ inputs.test_name }}
24- runs-on : macos-latest-large
24+ # Pin to macos-15-large: macos-latest rolled to macOS-26 (2026-07-15) which
25+ # removed all Xcode 16.x versions. macos-15 image ships Xcode 16.0–16.4.
26+ runs-on : macos-15-large
2527 timeout-minutes : ${{ inputs.timeout_minutes }}
2628
2729 steps :
3234 - name : Setup node and build the repository
3335 uses : ./amplify-js/.github/actions/node-and-build
3436 - name : Set Xcode version
37+ # Prefer Xcode 16.4; fall back to newest 16.x if the exact version is
38+ # missing (e.g. runner image update removed it). Fails loudly if no
39+ # Xcode 16.x is available at all.
3540 run : |
36- sudo xcode-select -s /Applications/Xcode_16.4.app
41+ XCODE_PATH="/Applications/Xcode_16.4.app"
42+ if [ ! -d "$XCODE_PATH" ]; then
43+ echo "::warning::Xcode_16.4.app not found. Available Xcode installations:"
44+ ls -d /Applications/Xcode_*.app 2>/dev/null || echo " (none found)"
45+ # Fall back to the newest Xcode 16.x
46+ XCODE_PATH=$(ls -d /Applications/Xcode_16*.app 2>/dev/null | sort -V | tail -n1)
47+ if [ -z "$XCODE_PATH" ]; then
48+ echo "::error::No Xcode 16.x found in /Applications. Cannot proceed."
49+ exit 1
50+ fi
51+ echo "Falling back to: $XCODE_PATH"
52+ fi
53+ sudo xcode-select -s "$XCODE_PATH"
54+ echo "Active Xcode: $(xcode-select -p)"
55+ - name : Ensure iPhone 15 simulator exists
56+ # The 'iPhone 15' device name is required by detox config in the samples
57+ # repo. If the runner image doesn't ship one, create it with the newest
58+ # available iOS runtime. Passkeys tests handle their own sim (iOS 17.4).
59+ if : ${{ !contains(inputs.test_name, 'integ_rn_ios_passkeys') }}
60+ run : |
61+ if xcrun simctl list devices available | grep -q '"iPhone 15"'; then
62+ echo "iPhone 15 simulator already available."
63+ else
64+ echo "iPhone 15 simulator not found — creating one."
65+ # Pick the newest iOS runtime available on this image
66+ RUNTIME=$(xcrun simctl list runtimes iOS | grep -oE 'com\.apple\.CoreSimulator\.SimRuntime\.iOS-[0-9]+-[0-9]+' | sort -V | tail -n1)
67+ if [ -z "$RUNTIME" ]; then
68+ echo "::error::No iOS runtime found. Cannot create simulator."
69+ exit 1
70+ fi
71+ echo "Using runtime: $RUNTIME"
72+ xcrun simctl create "iPhone 15" "com.apple.CoreSimulator.SimDeviceType.iPhone-15" "$RUNTIME"
73+ echo "iPhone 15 simulator created successfully."
74+ fi
3775 - name : Download iOS platform and create simulator
3876 if : ${{ contains(inputs.test_name, 'integ_rn_ios_passkeys') }}
3977 run : |
5492 $GITHUB_WORKSPACE/amplify-js/scripts/retry-yarn-script.sh -s 'install --frozen-lockfile --non-interactive' -n 3
5593 shell : bash
5694 - name : Install CocoaPods
95+ # Retry to guard against transient network failures (CDN/specs fetch)
5796 run : |
58- cd ios && pod install
97+ for i in 1 2 3; do
98+ echo "pod install attempt $i"
99+ (cd ios && pod install) && break
100+ if [ "$i" -eq 3 ]; then
101+ echo "::error::pod install failed after 3 attempts"
102+ exit 1
103+ fi
104+ echo "Attempt $i failed, retrying in 5s..."
105+ sleep 5
106+ done
59107 working-directory : ${{ inputs.working_directory }}
60108 shell : bash
61109 - name : Start iOS simulator (background)
@@ -68,12 +116,35 @@ jobs:
68116 working-directory : ${{ inputs.working_directory }}
69117 shell : bash
70118 - name : Configure Detox
119+ # Retry brew/npm installs to guard against transient network failures
71120 env :
72121 HOMEBREW_NO_AUTO_UPDATE : ' 1'
73122 run : |
123+ # Install applesimutils with retries
74124 brew tap wix/brew
75- brew install applesimutils
76- yarn global add detox-cli
125+ # Newer Homebrew (macos-15 image ≥2026-06) requires explicit tap trust
126+ brew trust wix/brew || true
127+ for i in 1 2 3; do
128+ echo "brew install applesimutils attempt $i"
129+ brew install applesimutils && break || true
130+ if [ "$i" -eq 3 ]; then
131+ echo "::error::brew install applesimutils failed after 3 attempts"
132+ exit 1
133+ fi
134+ echo "Attempt $i failed, retrying in 5s..."
135+ sleep 5
136+ done
137+ # Install detox-cli with retries
138+ for i in 1 2 3; do
139+ echo "yarn global add detox-cli attempt $i"
140+ yarn global add detox-cli && break || true
141+ if [ "$i" -eq 3 ]; then
142+ echo "::error::yarn global add detox-cli failed after 3 attempts"
143+ exit 1
144+ fi
145+ echo "Attempt $i failed, retrying in 5s..."
146+ sleep 5
147+ done
77148 working-directory : ${{ inputs.working_directory }}
78149 shell : bash
79150 - name : Detox Build
0 commit comments