diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83e8b60c..868bec85 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,158 +43,158 @@ jobs: ci: if: github.event_name != 'pull_request' || !contains(github.event.pull_request.title, '[skip ci]') - name: ${{ matrix.platform[0] }} ${{ matrix.platform[1] }} - runs-on: ${{ matrix.os }} + name: ${{ matrix.runtime[0] }} ${{ matrix.runtime[1] }} + runs-on: macos-15 strategy: fail-fast: false matrix: - include: - - platform: [iOS, 15] - runtime: iOS 15.5 - os: macos-15 - xcode: 26.0 - - platform: [iOS, 16] - runtime: iOS 16.4 - os: macos-15 - xcode: 26.0 - - platform: [iOS, 17] - runtime: iOS 17.5 - os: macos-15 - xcode: 26.0 - - platform: [iOS, 18] - runtime: iOS 18.6 - os: macos-15 - xcode: 26.0 - - platform: [iOS, 26] - runtime: iOS 26.0 - os: macos-15 - xcode: 26.0 - - - platform: [tvOS, 15] - runtime: tvOS 15.4 - os: macos-15 - xcode: 26.0 - - platform: [tvOS, 16] - runtime: tvOS 16.4 - os: macos-15 - xcode: 26.0 - - platform: [tvOS, 17] - runtime: tvOS 17.5 - os: macos-15 - xcode: 26.0 - - platform: [tvOS, 18] - runtime: tvOS 18.5 - os: macos-15 - xcode: 26.0 - - platform: [tvOS, 26] - runtime: tvOS 26.0 - os: macos-15 - xcode: 26.0 - - - platform: [watchOS, 8] - runtime: watchOS 8.5 - os: macos-15 - xcode: 26.0 - - platform: [watchOS, 9] - runtime: watchOS 9.4 - os: macos-15 - xcode: 26.0 - - platform: [watchOS, 10] - runtime: watchOS 10.5 - os: macos-15 - xcode: 26.0 - - platform: [watchOS, 11] - runtime: watchOS 11.5 - os: macos-15 - xcode: 26.0 - - platform: [watchOS, 26] - runtime: watchOS 26.0 - os: macos-15 - xcode: 26.0 - - - platform: [macOS, 15] - runtime: macOS 15 - os: macos-15 - xcode: 26.0 - # - platform: [macOS, 26] - # runtime: macOS 26.0 - # os: macos-26 - # xcode: 26.0 - - - platform: [visionOS, 1] - runtime: visionOS 1.2 - os: macos-15 - xcode: 26.0 - - platform: [visionOS, 2] - runtime: visionOS 2.5 - os: macos-15 - xcode: 26.0 - - platform: [visionOS, 26] - runtime: visionOS 26.0 - os: macos-15 - xcode: 26.0 + runtime: + - [iOS, 15, 5] + - [iOS, 16, 4] + - [iOS, 17, 5] + - [iOS, 18, 6] + - [iOS, 26, 0] + + - [iPadOS, 15, 5] + - [iPadOS, 16, 4] + - [iPadOS, 17, 5] + - [iPadOS, 18, 6] + - [iPadOS, 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] + + - [macOS, 15, 0] + # - [macOS, 26, 0] + + - [visionOS, 1, 2] + - [visionOS, 2, 5] + - [visionOS, 26, 0] steps: - name: Git Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 + + - name: Set Environment Variables + run: | + set -euo pipefail + + PLATFORM="${{ matrix.runtime[0] }}" + MAJOR="${{ matrix.runtime[1] }}" + MINOR="${{ matrix.runtime[2] }}" + + if [ "$PLATFORM" = "iPadOS" ]; then + PLATFORM=iOS + FASTLANE_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 ;; + esac + fi - - name: Set environment variables - run: echo "SKIP_SLOW_FASTLANE_WARNING=1" >> $GITHUB_ENV + RUNTIME="$PLATFORM $MAJOR.$MINOR" - - if: ${{ matrix.platform[0] != 'macOS' }} - name: Check for ${{ matrix.runtime }} runtime + echo "PLATFORM=$PLATFORM" >> $GITHUB_ENV + echo "MAJOR=$MAJOR" >> $GITHUB_ENV + echo "MINOR=$MINOR" >> $GITHUB_ENV + echo "RUNTIME=$RUNTIME" >> $GITHUB_ENV + echo "FASTLANE_PLATFORM=$FASTLANE_PLATFORM" >> $GITHUB_ENV + + - if: ${{ env.PLATFORM != 'macOS' }} + name: Check for ${{ env.RUNTIME }} runtime run: | - if xcrun simctl list runtimes | grep -q "${{ matrix.runtime }}"; then + if xcrun simctl list runtimes | grep -q "$RUNTIME"; then echo "has_runtime=true" >> "$GITHUB_ENV" else echo "has_runtime=false" >> "$GITHUB_ENV" fi - - name: Select Xcode ${{ matrix.xcode }} - run: sudo xcodes select ${{ matrix.xcode }} + - name: Select Xcode 26.0 + uses: mxcl/xcodebuild@v3 + with: + xcode: ~26.0 + action: none + verbosity: xcbeautify - - if: ${{ matrix.xcode == '26.0' && matrix.platform[0] != 'macOS' }} - name: Install 2026 Runtime + - if: ${{ env.PLATFORM != 'macOS' }} + name: Download Required Runtime uses: nick-fields/retry@v3 with: timeout_minutes: 15 max_attempts: 3 - command: xcodebuild -downloadPlatform ${{ matrix.platform[0] }} + command: xcodebuild -downloadPlatform ${{ env.PLATFORM }} - if: env.has_runtime == 'false' - name: "List Downloadable Runtimes" + name: List Downloadable Runtimes run: xcodes runtimes --include-betas - if: env.has_runtime == 'false' - name: Install Required Runtime (${{ matrix.runtime }}) + name: Install Required Runtime (${{ env.RUNTIME }}) uses: nick-fields/retry@v3 with: timeout_minutes: 15 max_attempts: 3 - command: sudo xcodes runtimes install '${{ matrix.runtime }}' + command: sudo xcodes runtimes install "$RUNTIME" - - if: ${{ matrix.platform[0] != 'macOS' }} + - if: ${{ env.PLATFORM != 'macOS' }} name: Create Required Simulators run: | set -eo pipefail xcrun simctl delete all - fastlane create_simulators platform:${{ matrix.platform[0] }} version:${{ matrix.platform[1] }} + fastlane create_simulators platform:${{ env.FASTLANE_PLATFORM }} version:${{ env.MAJOR }} - name: List Available Runtimes, Simulators, and Destinations run: | xcrun simctl list xcodebuild -scheme "SwiftUIIntrospect" -showdestinations - - if: ${{ matrix.platform[0] != 'watchOS' }} + - if: ${{ env.PLATFORM != 'watchOS' }} name: Build Showcase - run: fastlane build platform:${{ matrix.platform[0] }} version:${{ matrix.platform[1] }} scheme:Showcase - - - if: ${{ matrix.platform[0] == 'watchOS' }} + uses: mxcl/xcodebuild@v3 + with: + xcode: ~26.0 + platform: ${{ env.PLATFORM }} + platform-version: ~${{ env.MAJOR }}.${{ env.MINOR }} + action: build + scheme: Showcase + configuration: Debug + verbosity: xcbeautify + + - if: ${{ env.PLATFORM == 'watchOS' }} name: Build Library - run: fastlane build platform:${{ matrix.platform[0] }} version:${{ matrix.platform[1] }} scheme:SwiftUIIntrospect - - - if: ${{ matrix.platform[0] != 'watchOS' }} + uses: mxcl/xcodebuild@v3 + with: + xcode: ~26.0 + platform: ${{ env.PLATFORM }} + platform-version: ~${{ env.MAJOR }}.${{ env.MINOR }} + action: build + scheme: SwiftUIIntrospect + configuration: Debug + verbosity: xcbeautify + + - if: ${{ env.PLATFORM != 'watchOS' }} name: Run Tests - run: fastlane test platform:${{ matrix.platform[0] }} version:${{ matrix.platform[1] }} scheme:SwiftUIIntrospectTests configuration:Debug + uses: mxcl/xcodebuild@v3 + with: + xcode: ~26.0 + platform: ${{ env.PLATFORM }} + platform-version: ~${{ env.MAJOR }}.${{ env.MINOR }} + action: test + scheme: SwiftUIIntrospectTests + configuration: Debug + verbosity: xcbeautify framework-archiving: if: github.event_name != 'pull_request' || !contains(github.event.pull_request.title, '[skip ci]') @@ -219,7 +219,7 @@ jobs: destination: "platform=macOS,variant=Mac Catalyst" steps: - name: Git Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Select Xcode version run: sudo xcodes select 16.4 diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 9b7f173d..9dc02ff4 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -2,38 +2,40 @@ skip_docs devices = { "ios" => { - 15 => ["iPhone 13 Pro (15.5)", "iPad Pro (11-inch) (3rd generation) (15.5)",], - 16 => ["iPhone 14 Pro (16.4)", "iPad Pro (11-inch) (4th generation) (16.4)"], - 17 => ["iPhone 15 Pro (17.5)", "iPad Pro 11-inch (M4) (17.5)"], - 18 => ["iPhone 16 Pro (18.6)", "iPad Pro 11-inch (M4) (18.6)"], - 26 => ["iPhone 17 Pro (26.0)", "iPad Pro 11-inch (M4) (26.0)"], + 15 => "iPhone 13 Pro (15.5)", + 16 => "iPhone 14 Pro (16.4)", + 17 => "iPhone 15 Pro (17.5)", + 18 => "iPhone 16 Pro (18.6)", + 26 => "iPhone 17 Pro (26.0)", + }, + "ipados" => { + 15 => "iPad Pro (11-inch) (3rd generation) (15.5)", + 16 => "iPad Pro (11-inch) (4th generation) (16.4)", + 17 => "iPad Pro 11-inch (M4) (17.5)", + 18 => "iPad Pro 11-inch (M4) (18.6)", + 26 => "iPad Pro 11-inch (M4) (26.0)", }, "tvos" => { - 15 => ["Apple TV (15.4)"], - 16 => ["Apple TV (16.4)"], - 17 => ["Apple TV (17.5)"], - 18 => ["Apple TV (18.5)"], - 26 => ["Apple TV (26.0)"], + 15 => "Apple TV (15.4)", + 16 => "Apple TV (16.4)", + 17 => "Apple TV (17.5)", + 18 => "Apple TV (18.5)", + 26 => "Apple TV (26.0)", }, "watchos" => { - 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)"], + 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)"], - 26 => ["Apple Vision Pro (26.0)"], + 1 => "Apple Vision Pro (at 2732x2048) (1.2)", + 2 => "Apple Vision Pro (at 2732x2048) (2.5)", + 26 => "Apple Vision Pro (26.0)", }, } -before_all do |lane, options| - next if lane == :create_simulators - create_simulators(platform: options[:platform], version: options[:version]) -end - lane :create_simulators do |options| require 'json' require 'set' @@ -41,6 +43,7 @@ lane :create_simulators do |options| # map Fastfile platform keys to display names used by CoreSimulator runtimes platforms_to_os = { "ios" => "iOS", + "ipados" => "iOS", "tvos" => "tvOS", "watchos" => "watchOS", "visionos" => "visionOS", @@ -110,11 +113,8 @@ lane :create_simulators do |options| os_name = platforms_to_os[platform] next if os_name.nil? - versions.values.flatten.each do |descriptor| - # descriptor examples: - # "iPhone 14 Pro (16.4)" - # "iPad Pro (11-inch) (4th generation) (16.4)" - # "Apple Vision Pro (2.5)" + 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/ @@ -147,75 +147,3 @@ lane :create_simulators do |options| end end end - -lane :build do |options| - platform = options[:platform].to_s.downcase - version = options[:version].to_i - scheme = options[:scheme].to_s - - unless scheme == "Showcase" || scheme == "SwiftUIIntrospect" - raise "Unsupported scheme: #{scheme}" - next - end - - if platform == "macos" - for destination in ["platform=macOS", "platform=macOS,variant=Mac Catalyst"] - build_app( - scheme: scheme, - destination: destination, - skip_archive: true, - skip_codesigning: true, - skip_package_ipa: true, - skip_profile_detection: true, - ) - end - else - run_tests( - configuration: "Debug", - build_for_testing: true, - scheme: scheme, - devices: devices[platform][version], - prelaunch_simulator: false, - ensure_devices_found: true, - force_quit_simulator: true, - disable_concurrent_testing: true, - ) - end -end - -lane :test do |options| - configuration = (options[:configuration] || "Debug").to_s - platform = options[:platform].to_s.downcase - version = options[:version].to_i - scheme = options[:scheme].to_s - - if platform == "macos" - run_tests( - configuration: configuration, - scheme: scheme, - destination: "platform=macOS", - catalyst_platform: "macos", - disable_slide_to_type: false, - prelaunch_simulator: false, - ensure_devices_found: true, - force_quit_simulator: false, - disable_concurrent_testing: true, - ) - else - unless ["SwiftUIIntrospectTests"].include?(scheme) - raise "Unsupported scheme: #{scheme}" - end - run_tests( - configuration: configuration, - scheme: scheme, - devices: devices[platform][version], - prelaunch_simulator: false, - ensure_devices_found: true, - force_quit_simulator: true, - reset_simulator: false, - disable_concurrent_testing: true, - result_bundle: true, - output_directory: Dir.pwd + "/test_output", - ) - end -end