ci: pin iOS workload set + Xcode version for todoapp-avalonia/maui iOS builds#530
Merged
Merged
Conversation
…ch (CommunityToolkit#529) todoapp-avalonia / ios and todoapp-maui / ios both call 'dotnet workload install ios' / 'maui-ios' unpinned (loose-manifests mode), which always resolves the newest published Microsoft.iOS.Sdk.net10.0_* pack. As of workload set 10.0.108, that's 26.5.10284, which requires Xcode 26.5 - not installed on either macOS-15 or macOS-26 runner images currently backing the macos-latest label during its migration window (see actions/runner-images#14167), causing intermittent 'This version of .NET for iOS (26.5.10284) requires Xcode 26.5' build failures. - Add repo-root global.json pinning sdk.workloadVersion to 10.0.107, the last workload set before the iOS/MacCatalyst/macOS/tvOS manifest moved to the 26.4/26.5 pack line, while keeping the MAUI (10.0.20) and Android (36.1.53) manifests at their latest versions. This applies automatically to every 'dotnet workload install' call in CI (including the currently-disabled todoapp-uno / ios-maccatalyst job, once CommunityToolkit#506 is resolved and it's wired back in) with no per-job or per-project edits needed. - Pin the todoapp-avalonia / ios and todoapp-maui / ios jobs to macos-15 (instead of macos-latest) as defense-in-depth so the Xcode version these jobs build against is deterministic during the migration window, rather than randomly landing on macos-15 or macos-26.
…ommunityToolkit#529) The repo-root global.json approach broke every other sample build (todoapp-mvc, todoapp-blazor-wasm, datasync-server, etc.) on a fresh runner with: error MSB4242: SDK Resolver Failure: ... Workload version 10.0.107, which was specified in .../global.json, was not found. Run 'dotnet workload restore' to install this workload version. Microsoft.NET.Sdk.ImportWorkloads.props enforces the pinned workload version for every 'dotnet build'/'restore' invocation whose cwd falls under a global.json declaring sdk.workloadVersion - regardless of whether that specific project has any workload dependency - and it's not satisfied lazily; it must already be installed. Confirmed via a real workflow_dispatch run (see https://github.com/adrianhall/CommunityToolkit-Datasync/actions/runs/29081276609). Replaced with 'dotnet workload install ios/maui-ios --version 10.0.107' scoped to just the ios job's env/steps in each affected workflow. This pins only that job's install (and the restore/build steps that follow it on the same runner), leaving every other job - including the android jobs in the same workflows - on unpinned/latest workload resolution.
…mmunityToolkit#529) Testing the --version 10.0.107 workload pin alone (previous commit) still failed on macos-15: error: This version of .NET for iOS (26.2.10233) requires Xcode 26.3. The current version of Xcode is 16.4. Confirmed via a real workflow_dispatch run (https://github.com/adrianhall/CommunityToolkit-Datasync/actions/runs/29081474204) that both todoapp-avalonia/ios and todoapp-maui/ios resolve to the SAME newest-available pack within the pinned workload set (26.2.10233, _RecommendedXcodeVersion=26.3 per Microsoft.iOS.Sdk.Versions.props), not an older Xcode-16.4-compatible one - there is no currently-published net10.0 iOS SDK pack (checked back to workload set 10.0.100, published 2025-11-11) whose _RecommendedXcodeVersion is anywhere close to 16.4, so no workload-version pin alone can satisfy macos-15's default Xcode. Per actions/runner-images' macos-15 Readme, Xcode 26.3 IS already installed on the image (just not the default) at /Applications/Xcode_26.3.app, alongside 26.0.1/26.1.1/26.2. Added a 'sudo xcode-select -s' step to explicitly select it, matching the 26.2.10233 pack's requirement, instead of installing anything extra.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #529.
todoapp-avalonia / ios(and, latently,todoapp-maui / ios) calldotnet workload install ios/maui-iosunpinned, which always resolves the newest publishedMicrosoft.iOS.Sdk.net10.0_*pack. As of workload set10.0.108, that's26.5.10284, which requires Xcode 26.5 - not installed on either the macOS-15 or macOS-26 runner images currently backing themacos-latestlabel during its migration window (see actions/runner-images#14167, rollout through 2026-07-15), causing thefailure from #529. This also explains why the failure looked flaky: the same commit passed and failed
todoapp-avalonia / ios~26 minutes apart onmain/a PR run of #528, purely becausemacos-latestlanded on a different underlying image each time.What changed
Both
todoapp-avalonia / iosandtodoapp-maui / iosjobs now:runs-ontomacos-15(instead ofmacos-latest) so the Xcode version available on the runner is deterministic during themacos-latestmigration window, rather than randomly landing on macOS-15 or macOS-26.sudo xcode-select -s /Applications/Xcode_26.3.app. Xcode 26.3 is already installed on themacos-15image, just not the default (16.4).10.0.107viadotnet workload install ios/maui-ios --version 10.0.107, scoped only to that job's env/steps (not a repo-wideglobal.json).10.0.107is the last workload set before the iOS/MacCatalyst/macOS/tvOS manifest moved to the 26.4/26.5 pack line, resolving toMicrosoft.iOS.Sdk.net10.0_26.2(26.2.10233), which requires exactly Xcode 26.3 - matching step 2. It keeps other manifests (Android, MAUI) at their latest versions, so those jobs are unaffected.Why not a per-project
TargetPlatformVersion/ValidateXcodeVersionoverride, or a repo-rootglobal.json?TodoApp.Avalonia.iOS.csproj,TodoApp.MAUI.csproj, and (once #506 is resolved)TodoApp.Uno.csproj- and wouldn't protect any future mobile sample from hitting the same issue.global.jsonpinningsdk.workloadVersionwas tried first, but it forces everydotnet build/restorein the whole repo (viaMicrosoft.NET.Sdk.ImportWorkloads.props) to require that exact workload version to already be installed - even for projects with zero workload dependency. This broketodoapp-mvc,todoapp-blazor-wasm,datasync-server, etc. on a fresh runner (confirmed via a real run).dotnet workload install ... --versionscoped to just theiosjob's own steps avoids this entirely.10.0.100(2025-11-11): none currently declare an iOS_RecommendedXcodeVersionanywhere near 16.4 (they range from 26.0 through 26.5), so pinning the workload version alone isn't sufficient - the explicitxcode-selectstep is required too. This was confirmed by first testing the workload pin alone, which failed the same way against26.2.10233requiring Xcode 26.3.Validation
Ran the full
build-samples.ymlviaworkflow_dispatchon this branch twice to confirm the fix is deterministic, not a flaky pass:todoapp-avalonia / iosin 13m49s,todoapp-maui / iosin 10m29s.todoapp-avalonia / iosin 15m33s,todoapp-maui / iosin 9m44s.Both
androidjobs (unpinned, unaffected by theios-job-scoped changes) passed in both runs, confirming no regression there.todoapp-unois intentionally left untouched - it's not wired intobuild-samples.ymlyet (blocked by #506), and will need the same treatment when it's re-enabled.Follow-up
Revisit both
iosjobs once we deliberately upgrade to a newer, Xcode-26-compatible workload set (both theruns-on: macos-15pin and thexcode-selectstep are called out inline as things to revisit then).