From 08793e683481e0f7e8633c7f999f5d6e53a3bd4f Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Tue, 23 Sep 2025 15:18:41 +0100 Subject: [PATCH 01/10] WIP --- fastlane/Fastfile => script/create_simulators | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename fastlane/Fastfile => script/create_simulators (99%) diff --git a/fastlane/Fastfile b/script/create_simulators similarity index 99% rename from fastlane/Fastfile rename to script/create_simulators index 9dc02ff42..4cc01e79e 100644 --- a/fastlane/Fastfile +++ b/script/create_simulators @@ -1,4 +1,4 @@ -skip_docs +#!/usr/bin/env ruby devices = { "ios" => { From 7d3c9e9b5ba59cdb7b23146764ac02ff88e7a578 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Tue, 23 Sep 2025 15:23:17 +0100 Subject: [PATCH 02/10] WIP --- .github/workflows/ci.yml | 16 +-- script/create_simulators | 230 +++++++++++++++++++++++---------------- 2 files changed, 146 insertions(+), 100 deletions(-) mode change 100644 => 100755 script/create_simulators diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 868bec856..9a46a1192 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,14 +93,14 @@ jobs: if [ "$PLATFORM" = "iPadOS" ]; then PLATFORM=iOS - FASTLANE_PLATFORM=ipados + SCRIPT_PLATFORM=ipados else case "$PLATFORM" in - iOS) FASTLANE_PLATFORM=ios ;; - tvOS) FASTLANE_PLATFORM=tvos ;; - watchOS) FASTLANE_PLATFORM=watchos ;; - visionOS) FASTLANE_PLATFORM=visionos ;; - macOS) FASTLANE_PLATFORM=macos ;; + iOS) SCRIPT_PLATFORM=ios ;; + tvOS) SCRIPT_PLATFORM=tvos ;; + watchOS) SCRIPT_PLATFORM=watchos ;; + visionOS) SCRIPT_PLATFORM=visionos ;; + macOS) SCRIPT_PLATFORM=macos ;; esac fi @@ -110,7 +110,7 @@ jobs: echo "MAJOR=$MAJOR" >> $GITHUB_ENV echo "MINOR=$MINOR" >> $GITHUB_ENV echo "RUNTIME=$RUNTIME" >> $GITHUB_ENV - echo "FASTLANE_PLATFORM=$FASTLANE_PLATFORM" >> $GITHUB_ENV + echo "SCRIPT_PLATFORM=$SCRIPT_PLATFORM" >> $GITHUB_ENV - if: ${{ env.PLATFORM != 'macOS' }} name: Check for ${{ env.RUNTIME }} runtime @@ -153,7 +153,7 @@ jobs: run: | set -eo pipefail xcrun simctl delete all - fastlane create_simulators platform:${{ env.FASTLANE_PLATFORM }} version:${{ env.MAJOR }} + script/create_simulators --platform ${{ env.SCRIPT_PLATFORM }} --version ${{ env.MAJOR }} - name: List Available Runtimes, Simulators, and Destinations run: | diff --git a/script/create_simulators b/script/create_simulators old mode 100644 new mode 100755 index 4cc01e79e..210e3a325 --- a/script/create_simulators +++ b/script/create_simulators @@ -1,5 +1,13 @@ #!/usr/bin/env ruby +# frozen_string_literal: true +require 'json' +require 'set' +require 'optparse' +require 'open3' + +# Mapping of desired simulators per OS major to a human-friendly descriptor. +# Keep the descriptor's trailing (version) so we can parse the runtime. devices = { "ios" => { 15 => "iPhone 13 Pro (15.5)", @@ -23,38 +31,58 @@ devices = { 26 => "Apple TV (26.0)", }, "watchos" => { - 8 => "Apple Watch Series 7 (45mm) (8.5)", - 9 => "Apple Watch Series 8 (45mm) (9.4)", + 8 => "Apple Watch Series 7 (45mm) (8.5)", + 9 => "Apple Watch Series 8 (45mm) (9.4)", 10 => "Apple Watch Series 9 (45mm) (10.5)", 11 => "Apple Watch Series 10 (42mm) (11.5)", 26 => "Apple Watch Series 11 (42mm) (26.0)", }, "visionos" => { - 1 => "Apple Vision Pro (at 2732x2048) (1.2)", - 2 => "Apple Vision Pro (at 2732x2048) (2.5)", + 1 => "Apple Vision Pro (at 2732x2048) (1.2)", + 2 => "Apple Vision Pro (at 2732x2048) (2.5)", 26 => "Apple Vision Pro (26.0)", }, } -lane :create_simulators do |options| - require 'json' - require 'set' - - # map Fastfile platform keys to display names used by CoreSimulator runtimes - platforms_to_os = { - "ios" => "iOS", - "ipados" => "iOS", - "tvos" => "tvOS", - "watchos" => "watchOS", - "visionos" => "visionOS", - } - - # Build lookup tables from CoreSimulator for robust name→identifier mapping - begin - # Build a set of existing simulator name+runtime pairs to prevent duplicates across OS versions - devices_json = sh("xcrun simctl list -j devices", log: false) +# Map script platform keys to CoreSimulator OS display names +PLATFORMS_TO_OS = { + "ios" => "iOS", + "ipados" => "iOS", + "tvos" => "tvOS", + "watchos" => "watchOS", + "visionos" => "visionOS", +} + +options = { + platform: nil, + version: nil, +} + +OptionParser.new do |opts| + opts.banner = "Usage: create_simulators [--platform ios|ipados|tvos|watchos|visionos] [--version N]" + opts.on("--platform PLATFORM", String, "Limit to a single platform key") { |v| options[:platform] = v.downcase } + opts.on("--version N", Integer, "Limit to a single major version key under the chosen platform") { |v| options[:version] = v } + opts.on("-h", "--help", "Show help") { puts opts; exit 0 } +end.parse!(ARGV) + +# Helper to run a shell command and capture stdout. Returns "" on error. +def run(cmd) + stdout, status = Open3.capture2e(cmd) + unless status.success? + warn "Command failed (#{status.exitstatus}): #{cmd}\n#{stdout}" + end + stdout +rescue => e + warn "Failed to run: #{cmd} (#{e})" + "" +end + +# Build a set of existing simulator name+runtime pairs to prevent duplicates across OS versions +existing_pairs = Set.new +begin + devices_json = run("xcrun simctl list -j devices") + if !devices_json.empty? devices_list = JSON.parse(devices_json) - existing_pairs = Set.new (devices_list["devices"] || {}).each do |runtime_key, arr| Array(arr).each do |d| name = d["name"] @@ -62,88 +90,106 @@ lane :create_simulators do |options| existing_pairs.add("#{name}||#{runtime_key}") end end - - list_json = sh("xcrun simctl list -j", log: false) - list = JSON.parse(list_json) - devtypes = list["devicetypes"] || [] - runtimes = list["runtimes"] || [] - rescue => e - UI.message("Failed to read simctl lists: #{e}") - devtypes = [] - runtimes = [] - existing_pairs = Set.new end +rescue => e + warn "Failed to read existing devices: #{e}" +end - device_name_to_id = devtypes.each_with_object({}) do |dt, h| - name = dt["name"]; id = dt["identifier"] - h[name] = id if name && id - end +# Build lookup tables for device types and runtimes +begin + list_json = run("xcrun simctl list -j") + list = list_json.empty? ? {} : JSON.parse(list_json) + devtypes = list["devicetypes"] || [] + runtimes = list["runtimes"] || [] +rescue => e + warn "Failed to read simctl lists: #{e}" + devtypes = [] + runtimes = [] +end - runtime_name_to_id = runtimes.each_with_object({}) do |rt, h| - next unless rt["isAvailable"] - name = rt["name"]; id = rt["identifier"] - h[name] = id if name && id - end +device_name_to_id = devtypes.each_with_object({}) do |dt, h| + name = dt["name"]; id = dt["identifier"] + h[name] = id if name && id +end - # Fallback builders when exact matches are not present in the lookup tables - build_device_type_id = proc do |device_name| - s = device_name.gsub(/[()]/, '').gsub(/\s+/, '-').gsub(/[^A-Za-z0-9-]/, '') - "com.apple.CoreSimulator.SimDeviceType.#{s}" - end +runtime_name_to_id = runtimes.each_with_object({}) do |rt, h| + next unless rt["isAvailable"] + name = rt["name"]; id = rt["identifier"] + h[name] = id if name && id +end - build_runtime_id = proc do |os_name, version| - "com.apple.CoreSimulator.SimRuntime.#{os_name}-#{version.tr('.', '-')}" - end +# Fallback builders when exact matches are not present in the lookup tables +build_device_type_id = proc do |device_name| + s = device_name.gsub(/[()]/, '').gsub(/\s+/, '-').gsub(/[^A-Za-z0-9-]/, '') + "com.apple.CoreSimulator.SimDeviceType.#{s}" +end - platform_opt = options && options[:platform] ? options[:platform].to_s.downcase : nil - version_opt = options && options[:version] ? options[:version].to_i : nil +build_runtime_id = proc do |os_name, version| + "com.apple.CoreSimulator.SimRuntime.#{os_name}-#{version.tr('.', '-')}" +end - local_devices = if platform_opt && devices.key?(platform_opt) - subset_versions = devices[platform_opt] - if version_opt && subset_versions.key?(version_opt) - { platform_opt => { version_opt => subset_versions[version_opt] } } - else - { platform_opt => subset_versions } - end +# Filter the devices hash according to CLI options +local_devices = if options[:platform] && devices.key?(options[:platform]) + subset_versions = devices[options[:platform]] + if options[:version] && subset_versions.key?(options[:version]) + { options[:platform] => { options[:version] => subset_versions[options[:version]] } } else - devices + { options[:platform] => subset_versions } end +else + devices +end + +created = 0 +skipped = 0 + +local_devices.each do |platform, versions| + os_name = PLATFORMS_TO_OS[platform] + next if os_name.nil? + + versions.values.each do |descriptor| + begin + # Parse trailing "(x.y)" and derive device name + if descriptor =~ /\s*\(([^()]+)\)\s*\z/ + runtime_version = $1 + device_name = descriptor.sub(/\s*\([^()]+\)\s*\z/, '') + else + warn "Could not parse runtime version from '#{descriptor}', skipping" + skipped += 1 + next + end + + runtime_name = "#{os_name} #{runtime_version}" + + device_type_id = device_name_to_id[device_name] || build_device_type_id.call(device_name) + runtime_id = runtime_name_to_id[runtime_name] || build_runtime_id.call(os_name, runtime_version) + + # Use the device name without the version suffix as the simulator name + sim_name = device_name - local_devices.each do |platform, versions| - os_name = platforms_to_os[platform] - next if os_name.nil? - - versions.values.each do |descriptor| - # descriptor is a single string like "iPhone 14 Pro (16.4)" or "iPad Pro 11-inch (M4) (18.6)" - begin - # Parse trailing "(x.y)" and derive device name - if descriptor =~ /\s*\(([^()]+)\)\s*\z/ - runtime_version = $1 - device_name = descriptor.sub(/\s*\([^()]+\)\s*\z/, '') - else - UI.message("Could not parse runtime version from '#{descriptor}', skipping") - next - end - - runtime_name = "#{os_name} #{runtime_version}" - - device_type_id = device_name_to_id[device_name] || build_device_type_id.call(device_name) - runtime_id = runtime_name_to_id[runtime_name] || build_runtime_id.call(os_name, runtime_version) - - # Use the device name without the version suffix as the simulator name - sim_name = device_name - - pair_key = "#{sim_name}||#{runtime_id}" - if existing_pairs.include?(pair_key) - UI.message("Already exists: #{sim_name} (#{runtime_version}), skipping") - next - end - - sh(%(xcrun simctl create "#{sim_name}" "#{device_type_id}" "#{runtime_id}" || true)) + pair_key = "#{sim_name}||#{runtime_id}" + if existing_pairs.include?(pair_key) + puts "Already exists: #{sim_name} (#{runtime_version}), skipping" + skipped += 1 + next + end + + cmd = %(xcrun simctl create "#{sim_name}" "#{device_type_id}" "#{runtime_id}") + out = run(cmd) + if out.strip.empty? + # simctl returns the new UUID on success; if empty we assume failure was already reported + warn "Failed to create: #{sim_name} (#{runtime_version})" + skipped += 1 + else + puts "Created: #{sim_name} (#{runtime_version}) -> #{out.strip}" + created += 1 existing_pairs.add(pair_key) - rescue => e - UI.message("Skipping #{descriptor}: #{e}") end + rescue => e + warn "Skipping #{descriptor}: #{e}" + skipped += 1 end end end + +puts "Summary: created=#{created}, skipped=#{skipped}" From e36c9ef45a9982c0308917b4951ba121224f664f Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Tue, 23 Sep 2025 21:32:07 +0100 Subject: [PATCH 03/10] WIP --- .github/workflows/ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a46a1192..ef91bec03 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,7 +153,12 @@ jobs: run: | set -eo pipefail xcrun simctl delete all - script/create_simulators --platform ${{ env.SCRIPT_PLATFORM }} --version ${{ env.MAJOR }} + OUTPUT=$(script/create_simulators --platform ${{ env.SCRIPT_PLATFORM }} --version ${{ env.MAJOR }} | tee /dev/stderr) + FIRST_UDID=$(printf "%s\n" "$OUTPUT" | awk '/^Created: /{print $NF}' | head -n1) + if [ -n "$FIRST_UDID" ]; then + echo "SIM_UDID=$FIRST_UDID" >> "$GITHUB_ENV" + echo "Captured SIM_UDID=$FIRST_UDID" + fi - name: List Available Runtimes, Simulators, and Destinations run: | @@ -186,11 +191,12 @@ jobs: - if: ${{ env.PLATFORM != 'watchOS' }} name: Run Tests - uses: mxcl/xcodebuild@v3 + uses: davdroman/xcodebuild@destination with: xcode: ~26.0 platform: ${{ env.PLATFORM }} platform-version: ~${{ env.MAJOR }}.${{ env.MINOR }} + destination: ${{ env.SIM_UDID }} action: test scheme: SwiftUIIntrospectTests configuration: Debug From 03b671689f3b4d4e4591c84c6b7c450996ebe7d1 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Tue, 23 Sep 2025 21:40:34 +0100 Subject: [PATCH 04/10] WIP --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef91bec03..44366bafa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,7 +129,7 @@ jobs: verbosity: xcbeautify - if: ${{ env.PLATFORM != 'macOS' }} - name: Download Required Runtime + name: Download Default Runtime uses: nick-fields/retry@v3 with: timeout_minutes: 15 @@ -141,7 +141,7 @@ jobs: run: xcodes runtimes --include-betas - if: env.has_runtime == 'false' - name: Install Required Runtime (${{ env.RUNTIME }}) + name: Download Required Runtime (${{ env.RUNTIME }}) uses: nick-fields/retry@v3 with: timeout_minutes: 15 From 29c25158fb870518d0325ce8f5eb4c47fad60c30 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Tue, 23 Sep 2025 22:10:38 +0100 Subject: [PATCH 05/10] WIP --- .github/workflows/ci.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44366bafa..de206bf9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,14 +128,6 @@ jobs: action: none verbosity: xcbeautify - - if: ${{ env.PLATFORM != 'macOS' }} - name: Download Default Runtime - uses: nick-fields/retry@v3 - with: - timeout_minutes: 15 - max_attempts: 3 - command: xcodebuild -downloadPlatform ${{ env.PLATFORM }} - - if: env.has_runtime == 'false' name: List Downloadable Runtimes run: xcodes runtimes --include-betas From b1182e56857760ee34deece4ae5f8952b1afafed Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Wed, 24 Sep 2025 08:59:01 +0100 Subject: [PATCH 06/10] test --- .github/workflows/ci.yml | 42 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de206bf9d..818efecd4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,11 +49,11 @@ jobs: fail-fast: false matrix: runtime: - - [iOS, 15, 5] - - [iOS, 16, 4] - - [iOS, 17, 5] - - [iOS, 18, 6] - - [iOS, 26, 0] + # - [iOS, 15, 5] + # - [iOS, 16, 4] + # - [iOS, 17, 5] + # - [iOS, 18, 6] + # - [iOS, 26, 0] - [iPadOS, 15, 5] - [iPadOS, 16, 4] @@ -61,24 +61,24 @@ jobs: - [iPadOS, 18, 6] - [iPadOS, 26, 0] - - [tvOS, 15, 4] - - [tvOS, 16, 4] - - [tvOS, 17, 5] - - [tvOS, 18, 5] - - [tvOS, 26, 0] + # - [tvOS, 15, 4] + # - [tvOS, 16, 4] + # - [tvOS, 17, 5] + # - [tvOS, 18, 5] + # - [tvOS, 26, 0] - - [watchOS, 8, 5] - - [watchOS, 9, 4] - - [watchOS, 10, 5] - - [watchOS, 11, 5] - - [watchOS, 26, 0] + # - [watchOS, 8, 5] + # - [watchOS, 9, 4] + # - [watchOS, 10, 5] + # - [watchOS, 11, 5] + # - [watchOS, 26, 0] - - [macOS, 15, 0] - # - [macOS, 26, 0] + # - [macOS, 15, 0] + # # - [macOS, 26, 0] - - [visionOS, 1, 2] - - [visionOS, 2, 5] - - [visionOS, 26, 0] + # - [visionOS, 1, 2] + # - [visionOS, 2, 5] + # - [visionOS, 26, 0] steps: - name: Git Checkout uses: actions/checkout@v5 @@ -144,7 +144,7 @@ jobs: name: Create Required Simulators run: | set -eo pipefail - xcrun simctl delete all + # xcrun simctl delete all OUTPUT=$(script/create_simulators --platform ${{ env.SCRIPT_PLATFORM }} --version ${{ env.MAJOR }} | tee /dev/stderr) FIRST_UDID=$(printf "%s\n" "$OUTPUT" | awk '/^Created: /{print $NF}' | head -n1) if [ -n "$FIRST_UDID" ]; then From ed481e096e5720cdf6ab5060d2dd57565665c9e5 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:24:55 +0100 Subject: [PATCH 07/10] WIP --- .github/workflows/ci.yml | 2 +- script/create_simulators | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 818efecd4..7fff4f085 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -146,7 +146,7 @@ jobs: set -eo pipefail # xcrun simctl delete all OUTPUT=$(script/create_simulators --platform ${{ env.SCRIPT_PLATFORM }} --version ${{ env.MAJOR }} | tee /dev/stderr) - FIRST_UDID=$(printf "%s\n" "$OUTPUT" | awk '/^Created: /{print $NF}' | head -n1) + FIRST_UDID=$(printf "%s\n" "$OUTPUT" | awk '/^(Created:|Already exists:)/{print $NF}' | head -n1) if [ -n "$FIRST_UDID" ]; then echo "SIM_UDID=$FIRST_UDID" >> "$GITHUB_ENV" echo "Captured SIM_UDID=$FIRST_UDID" diff --git a/script/create_simulators b/script/create_simulators index 210e3a325..050e956d0 100755 --- a/script/create_simulators +++ b/script/create_simulators @@ -79,6 +79,7 @@ end # Build a set of existing simulator name+runtime pairs to prevent duplicates across OS versions existing_pairs = Set.new +existing_index = {} begin devices_json = run("xcrun simctl list -j devices") if !devices_json.empty? @@ -88,6 +89,7 @@ begin name = d["name"] next unless name && runtime_key existing_pairs.add("#{name}||#{runtime_key}") + existing_index["#{name}||#{runtime_key}"] = d["udid"] if d["udid"] end end end @@ -169,7 +171,7 @@ local_devices.each do |platform, versions| pair_key = "#{sim_name}||#{runtime_id}" if existing_pairs.include?(pair_key) - puts "Already exists: #{sim_name} (#{runtime_version}), skipping" + puts "Already exists: #{sim_name} (#{runtime_version}) -> #{existing_index[pair_key]}" skipped += 1 next end From 159a4c4e4fe04219ee8e883ec6929d582cf2e117 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:25:16 +0100 Subject: [PATCH 08/10] Revert "test" This reverts commit b1182e56857760ee34deece4ae5f8952b1afafed. --- .github/workflows/ci.yml | 42 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7fff4f085..ce61a5c7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,11 +49,11 @@ jobs: fail-fast: false matrix: runtime: - # - [iOS, 15, 5] - # - [iOS, 16, 4] - # - [iOS, 17, 5] - # - [iOS, 18, 6] - # - [iOS, 26, 0] + - [iOS, 15, 5] + - [iOS, 16, 4] + - [iOS, 17, 5] + - [iOS, 18, 6] + - [iOS, 26, 0] - [iPadOS, 15, 5] - [iPadOS, 16, 4] @@ -61,24 +61,24 @@ jobs: - [iPadOS, 18, 6] - [iPadOS, 26, 0] - # - [tvOS, 15, 4] - # - [tvOS, 16, 4] - # - [tvOS, 17, 5] - # - [tvOS, 18, 5] - # - [tvOS, 26, 0] + - [tvOS, 15, 4] + - [tvOS, 16, 4] + - [tvOS, 17, 5] + - [tvOS, 18, 5] + - [tvOS, 26, 0] - # - [watchOS, 8, 5] - # - [watchOS, 9, 4] - # - [watchOS, 10, 5] - # - [watchOS, 11, 5] - # - [watchOS, 26, 0] + - [watchOS, 8, 5] + - [watchOS, 9, 4] + - [watchOS, 10, 5] + - [watchOS, 11, 5] + - [watchOS, 26, 0] - # - [macOS, 15, 0] - # # - [macOS, 26, 0] + - [macOS, 15, 0] + # - [macOS, 26, 0] - # - [visionOS, 1, 2] - # - [visionOS, 2, 5] - # - [visionOS, 26, 0] + - [visionOS, 1, 2] + - [visionOS, 2, 5] + - [visionOS, 26, 0] steps: - name: Git Checkout uses: actions/checkout@v5 @@ -144,7 +144,7 @@ jobs: name: Create Required Simulators run: | set -eo pipefail - # xcrun simctl delete all + xcrun simctl delete all OUTPUT=$(script/create_simulators --platform ${{ env.SCRIPT_PLATFORM }} --version ${{ env.MAJOR }} | tee /dev/stderr) FIRST_UDID=$(printf "%s\n" "$OUTPUT" | awk '/^(Created:|Already exists:)/{print $NF}' | head -n1) if [ -n "$FIRST_UDID" ]; then From efdde26383c83378ad14373af3bb3d5eddc48dd0 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:31:51 +0100 Subject: [PATCH 09/10] WIP --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce61a5c7b..c55739840 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -159,11 +159,12 @@ jobs: - if: ${{ env.PLATFORM != 'watchOS' }} name: Build Showcase - uses: mxcl/xcodebuild@v3 + uses: davdroman/xcodebuild@destination with: xcode: ~26.0 platform: ${{ env.PLATFORM }} platform-version: ~${{ env.MAJOR }}.${{ env.MINOR }} + destination: ${{ env.SIM_UDID }} action: build scheme: Showcase configuration: Debug @@ -171,11 +172,12 @@ jobs: - if: ${{ env.PLATFORM == 'watchOS' }} name: Build Library - uses: mxcl/xcodebuild@v3 + uses: davdroman/xcodebuild@destination with: xcode: ~26.0 platform: ${{ env.PLATFORM }} platform-version: ~${{ env.MAJOR }}.${{ env.MINOR }} + destination: ${{ env.SIM_UDID }} action: build scheme: SwiftUIIntrospect configuration: Debug From 3058a47a3c01684d87b6ce177372870b5dbae361 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Wed, 24 Sep 2025 13:28:55 +0100 Subject: [PATCH 10/10] WIP [skip ci] --- Tests/Tests/WeakTests.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Tests/Tests/WeakTests.swift b/Tests/Tests/WeakTests.swift index 7fead49cc..8de3b597b 100644 --- a/Tests/Tests/WeakTests.swift +++ b/Tests/Tests/WeakTests.swift @@ -7,49 +7,49 @@ struct WeakTests { var strongFoo: Foo? = Foo() - @Test func Init_nil() { + @Test func init_nil() { @Weak var weakFoo: Foo? #expect(weakFoo == nil) } - @Test func Init_nonNil() { + @Test func init_nonNil() { @Weak var weakFoo: Foo? = strongFoo #expect(weakFoo === strongFoo) } - @Test func Assignment_nilToNil() { + @Test func assignment_nilToNil() { @Weak var weakFoo: Foo? weakFoo = nil #expect(weakFoo == nil) } - @Test func Assignment_nilToNonNil() { + @Test func assignment_nilToNonNil() { @Weak var weakFoo: Foo? let otherFoo = Foo() weakFoo = otherFoo #expect(weakFoo === otherFoo) } - @Test func Assignment_nonNilToNil() { + @Test func assignment_nonNilToNil() { @Weak var weakFoo: Foo? = strongFoo weakFoo = nil #expect(weakFoo == nil) } - @Test func Assignment_nonNilToNonNil() { + @Test func assignment_nonNilToNonNil() { @Weak var weakFoo: Foo? = strongFoo let otherFoo = Foo() weakFoo = otherFoo #expect(weakFoo === otherFoo) } - @Test mutating func IndirectAssignment_nonNilToNil() { + @Test mutating func indirectAssignment_nonNilToNil() { @Weak var weakFoo: Foo? = strongFoo strongFoo = nil #expect(weakFoo == nil) } - @Test mutating func IndirectAssignment_nonNilToNonNil() { + @Test mutating func indirectAssignment_nonNilToNonNil() { @Weak var weakFoo: Foo? = strongFoo strongFoo = Foo() #expect(weakFoo == nil)