ci: Move iOS runtime tests off macOS-14 (backport 6.8) - #24964
MartinZikmund wants to merge 8 commits into
Conversation
Backport of #24680 (CI part) to servicing/6.8. The macOS-14 hosted image is retired on 2 Nov 2026. The shards now use the build image and Xcode, take the simulator runtime that Xcode ships, create the 12.9-inch iPad when the image lacks it, and install with xcrun simctl instead of idb. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018riLfyvT4wZYEh8iFjWkKa
Backport of #24961 (cleanup part) to servicing/6.8. Nothing runs on macOSVMImage_UITests / xCodeRoot_iOS_UITests anymore; the disabled native iOS stage and TestFlight now take the build image and Xcode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018riLfyvT4wZYEh8iFjWkKa
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: 2
Open (4)
The previous loop waited for simulators to appear becausesimctl listcan briefly return… · Newjq -rwill printnull(a non-empty string) if the UDID isn’t found ordataPathis missing,… · NewsimctlJSON output is commonly requested via-j(historically more compatible across Xcode… · NewsimctlJSON output is commonly requested via-j(historically more compatible across Xcode… · New
What changed in this PR
Moves iOS Skia runtime tests off the retiring macOS-14 image by consolidating iOS test jobs onto the build macOS image/Xcode and updating the iOS UI-test harness to use the simulator runtime that ships with the selected Xcode (dropping idb).
Changes:
- Update
ios-uitest-run.shto dynamically resolve the iOS simulator runtime/device from the selected Xcode and install viaxcrun simctl install(with a retry). - Remove macOS-14 / Xcode 15.3 “UITest” image parameters from Azure DevOps templates and route iOS test jobs to the build macOS image/Xcode.
- Delete macOS-14/Xcode 15.3 variables from
.vsts-ci.yml.
| File | Description |
|---|---|
| build/test-scripts/ios-uitest-run.sh | Switches runtime/device resolution to Xcode-provided simulator runtime, drops idb, and installs via simctl. |
| build/ci/tests/.azure-devops-tests-windows-skia.yml | Removes unused “test mac image/xcode” template parameters. |
| build/ci/tests/.azure-devops-tests-skia-stages.yml | Stops threading removed “test mac image/xcode” parameters through stages. |
| build/ci/tests/.azure-devops-tests-macos-skia.yml | Removes unused “test mac image/xcode” template parameters. |
| build/ci/tests/.azure-devops-tests-linux-skia.yml | Removes unused “test mac image/xcode” template parameters. |
| build/ci/tests/.azure-devops-tests-ios-skia.yml | Runs iOS Skia runtime tests on the build macOS image/Xcode. |
| build/ci/tests/.azure-devops-tests-ios-skia-build.yml | Removes unused “test mac image/xcode” template parameters. |
| build/ci/tests/.azure-devops-tests-ios-native.yml | Routes iOS native test jobs to the build image/Xcode and removes test-only Xcode parameter. |
| build/ci/publish/.azure-devops-publish-ios-testflight.yml | Removes unused test-only Xcode parameter. |
| build/ci/.azure-devops-stages.yml | Stops passing macOS-14/Xcode 15.3 test parameters to templates. |
| .vsts-ci.yml | Removes macOS-14/Xcode 15.3 variables. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| find_ios_device() { | ||
| xcrun simctl list devices --json | jq -r --arg sim "$UNO_UITEST_SIMULATOR_VERSION" --arg name "$UNO_UITEST_SIMULATOR_NAME" ' | ||
| (.devices[$sim] // []) | ||
| | map(select(.name == $name and .isAvailable == true)) | ||
| | .[0].udid // empty' | ||
| } | ||
|
|
||
| # Check for the presence of idb, and install it if it's not present | ||
| # NOTE: fb-idb currently breaks under Python 3.14 (asyncio get_event_loop change), | ||
| # so we pin fb-idb to Python 3.12 to avoid "There is no current event loop in thread 'MainThread'". | ||
| # Historical context: prior installs referenced an App Center issue/workaround. | ||
| # https://github.com/microsoft/appcenter/issues/2605#issuecomment-1854414963 | ||
| export PATH=$PATH:~/.local/bin | ||
| UITEST_IOSDEVICE_ID=$(find_ios_device) | ||
|
|
||
| if ! command -v idb >/dev/null 2>&1 | ||
| then | ||
| echo "Installing idb (fb-idb + idb-companion) pinned to Python 3.12" | ||
| # The images only pre-create current device models, and the screen size the tests were written | ||
| # against is the 12.9-inch iPad Pro, so create that device when it is missing. | ||
| if [ -z "$UITEST_IOSDEVICE_ID" ]; then | ||
| IOS_DEVICETYPE_ID=$(xcrun simctl list devicetypes --json | jq -r --arg name "$UNO_UITEST_SIMULATOR_NAME" ' | ||
| .devicetypes | ||
| | map(select(.name == $name)) | ||
| | .[0].identifier // empty') |
| export UITEST_IOSDEVICE_ID | ||
| export UITEST_IOSDEVICE_DATA_PATH=$(xcrun simctl list devices --json | jq -r --arg udid "$UITEST_IOSDEVICE_ID" '[.devices[][] | select(.udid == $udid)][0].dataPath') |
| UNO_UITEST_SIMULATOR_VERSION=$(xcrun simctl list runtimes --json | jq -r --arg ver "$IOS_SDK_VERSION" ' | ||
| .runtimes | ||
| | map(select(.isAvailable == true and (.identifier | test("SimRuntime\.iOS")) and (.version | startswith($ver)))) | ||
| | sort_by(.version | split(".") | map(tonumber? // 0)) | ||
| | .[-1].identifier // empty') |
| # The images only pre-create current device models, and the screen size the tests were written | ||
| # against is the 12.9-inch iPad Pro, so create that device when it is missing. | ||
| if [ -z "$UITEST_IOSDEVICE_ID" ]; then | ||
| IOS_DEVICETYPE_ID=$(xcrun simctl list devicetypes --json | jq -r --arg name "$UNO_UITEST_SIMULATOR_NAME" ' |
Moves the remaining macOS-15 jobs to macOS-26, as on master. macOS-26 does not ship the iOS 26.1 simulator runtime that Xcode 26.1.1 needs, so Xcode moves to 26.6 (iOS 26.5 runtime preinstalled). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018riLfyvT4wZYEh8iFjWkKa
|
Claude finished @MartinZikmund's task in 2m 39s —— View job Review complete ✅
Verdict: ship (minor, non-blocking finding only) Findings: 1 minor
Verified clean:
Cross-cutting note (non-blocking): The PR description says the iOS shards use The removal of the old "wait for simulator to appear" retry loop in favor of a direct |
| echo "##vso[task.logissue type=error]UNOBLD008: No iOS $IOS_SDK_VERSION simulator runtime is available on this agent." | ||
| xcrun simctl list runtimes || true | ||
| exit 1 | ||
| fi | ||
| fi | ||
| export UNO_UITEST_SIMULATOR_VERSION | ||
|
|
||
| echo "Waiting for the simulator to be available" | ||
| sleep 5 | ||
| done | ||
|
|
||
| export DEVICELIST_FILEPATH=$LOG_FILEPATH/DeviceList-$LOG_PREFIX.json | ||
| echo "Listing iOS simulators to $DEVICELIST_FILEPATH" | ||
| xcrun simctl list devices --json > $DEVICELIST_FILEPATH | ||
| find_ios_device() { | ||
| xcrun simctl list devices --json | jq -r --arg sim "$UNO_UITEST_SIMULATOR_VERSION" --arg name "$UNO_UITEST_SIMULATOR_NAME" ' | ||
| (.devices[$sim] // []) | ||
| | map(select(.name == $name and .isAvailable == true)) | ||
| | .[0].udid // empty' | ||
| } | ||
|
|
||
| # Check for the presence of idb, and install it if it's not present | ||
| # NOTE: fb-idb currently breaks under Python 3.14 (asyncio get_event_loop change), | ||
| # so we pin fb-idb to Python 3.12 to avoid "There is no current event loop in thread 'MainThread'". | ||
| # Historical context: prior installs referenced an App Center issue/workaround. | ||
| # https://github.com/microsoft/appcenter/issues/2605#issuecomment-1854414963 | ||
| export PATH=$PATH:~/.local/bin | ||
| UITEST_IOSDEVICE_ID=$(find_ios_device) | ||
|
|
||
| if ! command -v idb >/dev/null 2>&1 | ||
| then | ||
| echo "Installing idb (fb-idb + idb-companion) pinned to Python 3.12" | ||
| # The images only pre-create current device models, and the screen size the tests were written | ||
| # against is the 12.9-inch iPad Pro, so create that device when it is missing. | ||
| if [ -z "$UITEST_IOSDEVICE_ID" ]; then | ||
| IOS_DEVICETYPE_ID=$(xcrun simctl list devicetypes --json | jq -r --arg name "$UNO_UITEST_SIMULATOR_NAME" ' | ||
| .devicetypes | ||
| | map(select(.name == $name)) | ||
| | .[0].identifier // empty') | ||
|
|
||
| # 1) Make sure we have a usable python3.12, but don't fail if Homebrew linking conflicts | ||
| if ! command -v python3.12 >/dev/null 2>&1; then | ||
| # Install, but ignore link-step failure; we'll use the keg path explicitly | ||
| brew list --versions python@3.12 >/dev/null 2>&1 || brew install python@3.12 || true | ||
| fi | ||
| # Prefer an existing python3.12 on PATH; otherwise use the keg path | ||
| PY312_BIN="$(command -v python3.12 || echo "$(brew --prefix)/opt/python@3.12/bin/python3.12")" | ||
| export PIPX_DEFAULT_PYTHON="$PY312_BIN" | ||
| echo "Using Python for pipx: $PIPX_DEFAULT_PYTHON" | ||
|
|
||
| # 2) Install helpers | ||
| brew list --versions pipx >/dev/null 2>&1 || brew install pipx | ||
| brew tap facebook/fb >/dev/null 2>&1 || true | ||
| # Pin the tap to the v1.1.8 formula. Its tip (1.5.0.b2) requires macOS | ||
| # Sequoia and Xcode 26, which the macOS 14 UI test agents cannot satisfy, | ||
| # so `brew install idb-companion` aborts with "Unsatisfied requirements". | ||
| # Detaching the tap checkout is enough: brew reads the formula straight | ||
| # from the working tree. HOMEBREW_NO_AUTO_UPDATE keeps a later `brew | ||
| # install` from fast-forwarding the tap back to its default branch. | ||
| export HOMEBREW_NO_AUTO_UPDATE=1 | ||
| IDB_TAP_REVISION=c0386793f59da10c619787f2aa18d938ef1d69c9 | ||
| IDB_TAP_REPO="$(brew --repo facebook/fb)" | ||
| if [ ! -d "$IDB_TAP_REPO/.git" ]; then | ||
| echo "Tap facebook/fb is not checked out at $IDB_TAP_REPO — cannot pin idb-companion." >&2 | ||
| if [ -z "$IOS_DEVICETYPE_ID" ]; then | ||
| echo "##vso[task.logissue type=error]UNOBLD008: No '$UNO_UITEST_SIMULATOR_NAME' simulator device type is available on this agent." |
There was a problem hiding this comment.
UNOBLD008 is used here for two distinct failure causes: "no matching iOS simulator runtime" (line 180) and "no matching simulator device type" (line 205). Every other error code in this script (UNOBLD001/002/003/006/007) maps to exactly one condition, which is what makes them useful for triaging a failed CI run at a glance or grepping historical failures. Reusing the same code for two different root causes defeats that — give the device-type failure its own code (e.g. UNOBLD009).
|
Claude finished @MartinZikmund's task in 2m 48s —— View job Review complete
Verdict: ship (minor non-blocking nits)This is a CI-only backport (shell script + Azure DevOps YAML), so most of the C#/XAML-specific review checklist (DependencyProperty, async/cancellation, SOLID, XAML styling) doesn't apply. I focused on script correctness and template wiring. What I verified:
On the automated Copilot findings above: I independently traced the same two code paths and they're technically accurate:
Neither blocks merge; both are reasonable tightening if the author wants to address them, since the PR's own stated risk is already the CI run itself validating iOS 17.5 → 26.x simulator behavior. |
|
🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24964/wasm-skia-net9/index.html |
.NET for iOS 26.1 refuses any Xcode but 26.1 ("requires Xcode 26.1. The current version of Xcode is 26.6"), so builds stay on Xcode 26.1.1, which macOS-26 also ships. That image has no iOS 26.1 simulator runtime, so build-only jobs skip the runtime check in Select Xcode, and the iOS runtime-test shards select Xcode 26.6, whose iOS 26.5 runtime is preinstalled.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018riLfyvT4wZYEh8iFjWkKa
|
Claude finished @MartinZikmund's task in 2m 28s —— View job Review complete
Verdict: ship (minor, non-blocking findings only) Findings: 4 minor, 0 blocking
Verified clean:
Cross-cutting note (non-blocking): these are the same shell-script findings an earlier automated review pass on this PR already surfaced (duplicate error code, |
| find_ios_device() { | ||
| xcrun simctl list devices --json | jq -r --arg sim "$UNO_UITEST_SIMULATOR_VERSION" --arg name "$UNO_UITEST_SIMULATOR_NAME" ' | ||
| (.devices[$sim] // []) | ||
| | map(select(.name == $name and .isAvailable == true)) | ||
| | .[0].udid // empty' | ||
| } | ||
|
|
||
| # Check for the presence of idb, and install it if it's not present | ||
| # NOTE: fb-idb currently breaks under Python 3.14 (asyncio get_event_loop change), | ||
| # so we pin fb-idb to Python 3.12 to avoid "There is no current event loop in thread 'MainThread'". | ||
| # Historical context: prior installs referenced an App Center issue/workaround. | ||
| # https://github.com/microsoft/appcenter/issues/2605#issuecomment-1854414963 | ||
| export PATH=$PATH:~/.local/bin | ||
| UITEST_IOSDEVICE_ID=$(find_ios_device) |
There was a problem hiding this comment.
find_ios_device() is called exactly once, with no retry. The retry loop it replaces (the one removed just above) existed specifically because simctl list devices can return an incomplete list for a few seconds right after a runtime/device is registered. With the new flow, a transient empty result here is indistinguishable from "device genuinely doesn't exist" and falls straight into the simctl create branch below — on a busy/booting agent this can create a duplicate "iPad Pro (12.9-inch) (6th generation)" simulator (two matches for find_ios_device() pre-existing + the new one isn't actually ambiguous since .[0] is taken, but it does leave an orphaned extra device and masks a possibly-valid existing one with a cold, freshly-created one, losing e.g. previously accepted permission dialogs).
A small bounded retry (e.g. 2-3 attempts with a short sleep) around find_ios_device before falling back to simctl create would preserve the original resiliency this script intentionally had for exactly this race.
| if [ ! -d "$IDB_TAP_REPO/.git" ]; then | ||
| echo "Tap facebook/fb is not checked out at $IDB_TAP_REPO — cannot pin idb-companion." >&2 | ||
| if [ -z "$IOS_DEVICETYPE_ID" ]; then | ||
| echo "##vso[task.logissue type=error]UNOBLD008: No '$UNO_UITEST_SIMULATOR_NAME' simulator device type is available on this agent." |
There was a problem hiding this comment.
UNOBLD008 is reused here for a second, distinct failure cause (missing simulator device type) — it's already used at line 180 for "no matching simulator runtime". Every other error code in this script (UNOBLD001/002/003/006/007) maps to exactly one condition, which is what makes grepping historical CI logs for a code a reliable way to triage. This was already flagged by an earlier automated review pass on this PR and hasn't been addressed in the subsequent commits — give this branch its own code (e.g. UNOBLD009).
| fi | ||
|
|
||
| export UITEST_IOSDEVICE_ID | ||
| export UITEST_IOSDEVICE_DATA_PATH=$(xcrun simctl list devices --json | jq -r --arg udid "$UITEST_IOSDEVICE_ID" '[.devices[][] | select(.udid == $udid)][0].dataPath') |
There was a problem hiding this comment.
jq -r '... // empty' is missing here, unlike find_ios_device()/the devicetype lookup above. If UITEST_IOSDEVICE_ID somehow doesn't match any entry in simctl list devices --json (e.g. the just-created device isn't reflected yet), jq -r on a missing .dataPath prints the literal string "null" (non-empty), which export UITEST_IOSDEVICE_DATA_PATH then silently accepts instead of failing loudly. Recommend appending // empty to the jq filter and checking for an empty result the same way the runtime/devicetype lookups do.
| TEST_KIND: runtime | ||
| xCodeRoot: ${{ parameters.xCodeRootTest }} | ||
| # The shards only drive a simulator; this Xcode's runtime ships preinstalled on the image. | ||
| xCodeRoot: $(xCodeRootSimulator) |
There was a problem hiding this comment.
This reaches directly for the global pipeline variable $(xCodeRootSimulator) instead of being threaded through as a template parameter, unlike vmMacImage/xCodeRootBuild used two lines above in this same job, and unlike every other template touched in this PR (which all receive their Xcode/image values as ${{ parameters.* }}). It works today because .vsts-ci.yml is the only caller and defines xCodeRootSimulator globally, but it makes this template implicitly depend on top-level pipeline state rather than its declared parameter surface — harder to reuse or unit-test the template in isolation, and inconsistent with the parameter-threading convention the rest of this backport otherwise preserves. Consider adding an xCodeRootSimulator (or similarly named) parameter to this template's parameters: block and threading it down from .azure-devops-stages.yml like the other Xcode/image values.
actool refuses to compile asset catalogs without a simulator runtime that matches the SDK ("No simulator runtime version from [...] available to use with iphonesimulator SDK version 23B77"), so the build jobs need the runtime after all. Select Xcode downloads it as before; only the simulator test shards use Xcode 26.6.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018riLfyvT4wZYEh8iFjWkKa
|
Claude finished @MartinZikmund's task in 2m 4s —— View job Review complete
Verdict: ship (minor, non-blocking)This is a CI-only backport (shell script + Azure DevOps YAML), so most of the C#/XAML-specific checklist (DependencyProperty, async/cancellation, SOLID, XAML styling) doesn't apply. I re-verified the prior findings from earlier automated passes against the current HEAD and didn't re-post them as new inline comments since they're unchanged and already visible on the thread — summarized below instead to avoid duplicate noise. Still open from earlier review passes (unaddressed across the 4 commits since they were first raised):
New finding (this pass): PR description is out of date relative to the final diff. Verified clean (re-confirmed on current HEAD):
|
|
🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24964/wasm-skia-net9/index.html |
jq rejects "\." in a string literal, so every iOS shard aborted while resolving the simulator. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018riLfyvT4wZYEh8iFjWkKa
|
Claude finished @MartinZikmund's task in 1m 0s —— View job Review complete
Verdict: ship (minor, non-blocking — unchanged from prior passes)This trigger fired on a new commit pushed since the last automated pass. I verified that commit in isolation and re-checked the file state as a whole; I did not re-post inline comments for findings already surfaced on this thread, to avoid further duplicate noise — they're summarized below instead. The new commit ( Still open from earlier review passes on this PR (unaffected by the new commit, unaddressed across prior commits since first raised):
Verified clean (re-confirmed on current HEAD):
None of the four still-open items are blocking — they're either latent/cosmetic or a risk-reducing hardening opportunity rather than a correctness defect, and the PR's own stated risk (iOS 17.5 → 26.5 simulator jump) is best validated by this PR's CI run, which the latest commit shows is actively doing its job. |
|
🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24964/wasm-skia-net9/index.html |
The 6.x suite took 26-55 min on macOS-15 against a 60 min job timeout, and ran past it on macOS-26. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018riLfyvT4wZYEh8iFjWkKa
|
Claude finished @MartinZikmund's task in 37s —— View job Review complete
Verdict: ship (minor, non-blocking — unchanged from prior passes)This trigger fired on a new commit ( Still open from earlier review passes on this PR (unaffected by the new commit, unaddressed across the commits since first raised):
None of these are blocking — they're either latent/cosmetic or a risk-reducing hardening opportunity rather than a correctness defect. I did not re-post inline comments for them since they're already visible on the thread from earlier passes and unchanged. Verified clean (re-confirmed on current HEAD):
|
|
🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24964/wasm-skia-net9/index.html |
|
Claude finished @MartinZikmund's task in 1m 33s —— View job Review complete
Verdict: ship (no new findings)This trigger fired on a new commit ( What I verified on this commit:
Still open from earlier review passes on the CI portion of this PR (unaffected by the new commit, unaddressed across all commits since first raised — not re-posted inline to avoid duplicate noise):
None of these are blocking — they're latent/cosmetic hardening opportunities, not correctness defects, and the PR's own stated risk (iOS 17.5 → 26.5 simulator jump) is being validated by this PR's CI run. |
|
🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24964/wasm-skia-net9/index.html |
On the macOS-26 image these segfault the whole Desktop Skia macOS run on 6.x, in three out of three runs, taking every later test with it. They are already skipped on iOS and Win32 for #11997; master passes them, so the crash is 6.x-specific and needs a Mac to root-cause. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018riLfyvT4wZYEh8iFjWkKa
8116508 to
7d05428
Compare
|
Claude finished @MartinZikmund's task in 1m 44s —— View job Review complete
Verdict: fix-first (1 new finding, not blocking CI but worth resolving before merge)New since the last review pass: the branch was force-pushed/rebased, and the commit this thread previously reviewed in depth — Why this matters: this swaps a root-cause fix for a defensive test-skip, which this repo's debugging discipline requires to be explicitly labeled and justified, not silently substituted. It also makes the PR description inaccurate — it still states "Also backports #24112 (macOS native-peer use-after-free)" as part of what changed, which is no longer true of the code on this branch. Everything flagged in earlier passes on this thread remains open and unaffected by this change (not re-posted to avoid duplicate noise):
Also re-verified as fine: the most recent CI-only commit ( |
|
|
||
| [TestMethod] | ||
| [PlatformCondition(ConditionMode.Exclude, RuntimeTestPlatforms.SkiaUIKit | RuntimeTestPlatforms.NativeUIKit | RuntimeTestPlatforms.SkiaWin32)] // Temporarily disabled due to #11997 | ||
| [PlatformCondition(ConditionMode.Exclude, RuntimeTestPlatforms.SkiaUIKit | RuntimeTestPlatforms.NativeUIKit | RuntimeTestPlatforms.SkiaWin32 | RuntimeTestPlatforms.SkiaMacOS)] // Temporarily disabled due to #11997; on macOS 26 these segfault the test process |
There was a problem hiding this comment.
This commit (7d05428f) disables all five ExecuteScriptAsync tests on SkiaMacOS, but it replaces — rather than complements — the root-cause fix this same PR previously carried. Earlier commits on this branch (reviewed in a prior automated pass, commit 81165084, "Stop two native-peer use-after-free crashes", a cherry-pick of master's #24112) fixed exactly this segfault by correcting native-peer ownership/lifetime in MacOSNativeElementHostingExtension/UNONative.m/MacOSNativeWebView. That commit is no longer present in the current branch history (git diff origin/servicing/6.8...HEAD -- '*MacOSNative*' '*UNONative*' is empty) — it appears to have been dropped by a force-push/rebase between the last review pass and this one.
So the current state masks the crash with a test skip instead of applying the available root-cause fix, and the PR description still says "Also backports #24112 (macOS native-peer use-after-free)" — that's no longer true of the code as it stands, only of the description.
Per this repo's debugging discipline (root-cause fix vs. defensive/guard-only change must be labeled, and skipped tests must be flagged): either re-apply the #24112 cherry-pick (it was reportedly building and clean before), or, if it's being intentionally deferred, update the PR description to say so and open a tracking issue for the macOS-26-specific segfault referenced by "needs a Mac to root-cause" in the commit message, since none is linked here (unlike the #11997 reference the comment piggybacks on, which covers a different, pre-existing exclusion).
|
🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24964/wasm-skia-net9/index.html |
|
|


GitHub Issue: part of #24959
Backport of #24680 and #24961 to
servicing/6.8, in one PR.PR Type:
🏗️ Build or CI related changes
What changed? 🚀
The hosted
macOS-14image is retired on 2 Nov 2026, with outage windows from 5 Oct. On this branch the iOS Skia runtime tests still ran on it (macOSVMImage_UITests/ Xcode 15.3), and every other Mac job ran onmacOS-15. This branch has no tvOS stage.macOS-15tomacOS-26. The DevServer CLI template-test jobs that hardcodedmacOS-15move too.xCodeRootSimulator), whose iOS 26.5 runtime is preinstalled, so they skip that download. An app built with the 26.1 SDK runs on the newer simulator.macOS-26, iOS 26.5 simulator).ios-uitest-run.shuses the simulator runtime that ships with the selected Xcode instead of the hardcodediOS-17-5, createsiPad Pro (12.9-inch) (6th generation)when the image lacks it (same screen size as before), and installs withxcrun simctl install(one retry). idb and its Homebrew tap / Python pins are gone.macOSVMImage_UITests,xCodeRoot_iOS_UITestsand thevmMacImageTest/vmImageTest/xCodeRootTesttemplate parameters are removed. The disabled native iOS stage and TestFlight now take the build image and Xcode.Also skips the five WebView2
ExecuteScriptAsyncruntime tests onSkiaMacOS, next to their existing iOS/Win32 #11997 exclusion. On the macOS-26 image they segfault the whole Desktop Skia macOS process on 6.x (3 out of 3 runs on 6.7), so every later test is lost. Master passes them on macOS-26, and backporting the #24112 native-peer fix did not help, so the root cause is 6.x-specific and needs a Mac to chase.The iOS multi-window scene fix from #24680 isn't needed here: this branch doesn't support multiple windows on iOS (
SupportsMultipleWindowsisfalse), so closing a window can't background the app.Risk: the simulator moves from iOS 17.5 to iOS 26.5, so outcomes can shift. This PR's CI run is the check.
PR Checklist ✅
Screenshots Compare Test Runresults.🤖 Generated with Claude Code
https://claude.ai/code/session_018riLfyvT4wZYEh8iFjWkKa