From 18bc9c3de00dbfc2b0e88de5b21dc97323706044 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 20 Apr 2026 15:45:25 -0700 Subject: [PATCH 1/3] Download simulators for every non-macOS platform in spm-16 Runner images stopped shipping iOS 18.5 (and likely other) simulators pre-installed, so the Build Xcode 16 (iOS_18,watchOS_11) job failed with "Unable to find a device matching the provided destination specifier". The previous step only downloaded visionOS. Mirror the SafeDI pattern: iterate over each comma-separated matrix entry, strip the version suffix, and invoke -downloadPlatform for any entry that targets a simulator-bearing OS. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8c9f3f..64e0480 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,13 +55,19 @@ jobs: bundler-cache: true - name: Select Xcode Version run: sudo xcode-select --switch /Applications/Xcode_16.4.app/Contents/Developer - - name: Download visionOS - if: matrix.platforms == 'visionOS_2' + - name: Download Platforms run: | sudo xcodebuild -runFirstLaunch sudo xcrun simctl list - sudo xcodebuild -downloadPlatform visionOS - sudo xcodebuild -runFirstLaunch + IFS=',' read -ra ENTRIES <<< "${{ matrix.platforms }}" + for entry in "${ENTRIES[@]}"; do + PLATFORM="${entry%%_*}" + case "$PLATFORM" in + iOS|tvOS|watchOS|visionOS) + sudo xcodebuild -downloadPlatform "$PLATFORM" + ;; + esac + done - name: Build and Test Framework run: Scripts/build.swift ${{ matrix.platforms }} - name: Prepare Coverage Reports From 4758aa53901c2780bd377af7d3987bef3379e678 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 20 Apr 2026 15:47:49 -0700 Subject: [PATCH 2/3] Fan out spm-16 matrix to one platform per runner Splitting the paired entries (iOS+watchOS, macOS+tvOS) into individual runners increases parallelism and shortens end-to-end CI time at the cost of more runner minutes. Scripts/build.swift already accepts a single-platform input since it splits on commas. With one platform per entry, the Download step collapses back to the SafeDI shape: guard macOS/macCatalyst with an if, strip the version suffix, and call -downloadPlatform once. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64e0480..943630a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,9 +38,11 @@ jobs: strategy: matrix: platforms: [ - 'iOS_18,watchOS_11', - 'macOS_15,tvOS_18', + 'iOS_18', + 'tvOS_18', + 'macOS_15', 'macCatalyst_15', + 'watchOS_11', 'visionOS_2' ] fail-fast: false @@ -55,19 +57,13 @@ jobs: bundler-cache: true - name: Select Xcode Version run: sudo xcode-select --switch /Applications/Xcode_16.4.app/Contents/Developer - - name: Download Platforms + - name: Download Platform + if: matrix.platforms != 'macOS_15' && matrix.platforms != 'macCatalyst_15' run: | sudo xcodebuild -runFirstLaunch sudo xcrun simctl list - IFS=',' read -ra ENTRIES <<< "${{ matrix.platforms }}" - for entry in "${ENTRIES[@]}"; do - PLATFORM="${entry%%_*}" - case "$PLATFORM" in - iOS|tvOS|watchOS|visionOS) - sudo xcodebuild -downloadPlatform "$PLATFORM" - ;; - esac - done + PLATFORM="${{ matrix.platforms }}" + sudo xcodebuild -downloadPlatform "${PLATFORM%%_*}" - name: Build and Test Framework run: Scripts/build.swift ${{ matrix.platforms }} - name: Prepare Coverage Reports From 93c22ff2ef7f25c53da5e9ad928287e98ba9baac Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 20 Apr 2026 16:06:32 -0700 Subject: [PATCH 3/3] Skip coverage upload for watchOS_11 prepare-coverage-reports.sh explicitly skips watchOS (watchOS profile artifacts aren't produced by the toolchain), so the codecov upload step has nothing to find and fails with "No coverage reports found" under fail_ci_if_error: true. Previously the iOS_18,watchOS_11 pairing masked this because iOS's reports satisfied the uploader. Now that watchOS runs alone, skip the two coverage steps for that matrix entry. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 943630a..9d47842 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,9 +67,10 @@ jobs: - name: Build and Test Framework run: Scripts/build.swift ${{ matrix.platforms }} - name: Prepare Coverage Reports + if: matrix.platforms != 'watchOS_11' run: ./Scripts/prepare-coverage-reports.sh - name: Upload Coverage Reports - if: success() + if: success() && matrix.platforms != 'watchOS_11' uses: codecov/codecov-action@v5 with: fail_ci_if_error: true