CI: Unify CI jobs to reduce machine count#6332
Conversation
c15cc7a to
bb603a5
Compare
| spm-release-build-xcode-14: | ||
| executor: | ||
| name: macos-executor | ||
| xcode_version: "14.3.1" | ||
|
|
||
| steps: | ||
| - checkout | ||
| - run: | ||
| name: SPM Release Build | ||
| command: swift build -c release --target RevenueCat | ||
| no_output_timeout: 30m | ||
| - slack-notify-on-fail |
There was a problem hiding this comment.
This is now part of the new run-test-ios-15-and-14 job
| - run: | ||
| name: SPM Release Build | ||
| command: swift build -c release --target RevenueCat | ||
| no_output_timeout: 30m |
There was a problem hiding this comment.
This step is now part of the new run-test-ios-18-and-17 job
| - run: | ||
| name: SPM RevenueCatUI Release Build | ||
| command: swift build -c release --target RevenueCatUI | ||
| no_output_timeout: 30m |
There was a problem hiding this comment.
This step is now part of the new run-revenuecat-ui-ios-18-and-17 job
Merge several pairs of CI jobs that run on the same Xcode version into single jobs that execute tests sequentially, reducing the total number of macOS machines needed per CI run. Unified jobs: - run-test-ios-14-and-15 (Xcode 14.3.1, includes background iOS 14 sim install) - run-test-ios-16-and-17 (Xcode 15.4.0) - run-test-ios-18-and-26 (Xcode 26.3) - run-test-tvos-and-macos (Xcode 16.4) - run-revenuecat-ui-ios-17-and-18 (Xcode 16.4) Each unified job also runs an SPM release build as a preceding step, absorbing the standalone spm-release-build jobs. Other changes: - compress_result_bundle guards against missing .xcresult directories - push_snapshot_pr in Fastfile saves/restores the original branch Co-authored-by: Cursor <cursoragent@cursor.com>
bb603a5 to
fed250a
Compare
PR #6303 updated Package.swift to use exact: "1.18.9" but the Tuist/Package.swift was left on the old revision pin. Co-authored-by: Cursor <cursoragent@cursor.com>
…ify-some-xcode-14-jobs
…719) iOS 18 SK1 tests fail under Xcode 26 due to an Apple bug where SKProductsRequest cannot parse the price field (missingValue for StoreKit.ProductResponse.Key.price). Restructure jobs so iOS 18 runs under Xcode 16 instead: - run-test-ios-26: standalone on Xcode 26 (iOS 26 only) - run-test-ios-17-and-18: Xcode 16.4 (iOS 17 + 18) - run-test-ios-14-15-and-16: Xcode 14.3.1 (iOS 14 + 15 + 16) Co-authored-by: Cursor <cursoragent@cursor.com>
Rename and reorder unified jobs so the highest iOS version runs first: - run-test-ios-18-and-17 (was 17-and-18) - run-test-ios-16-15-and-14 (was 14-15-and-16) - run-revenuecat-ui-ios-18-and-17 (was 17-and-18) iOS 14 still runs last since its runtime needs to be downloaded first. Co-authored-by: Cursor <cursoragent@cursor.com>
… exception-safe - Remove test-all-unified workflow and action parameter (was temporary) - Wrap push_snapshot_pr git operations in begin/ensure to guarantee the original branch is restored even if push or PR creation fails Co-authored-by: Cursor <cursoragent@cursor.com>
The standalone spm-release-build-xcode-15 was removed during unification but no other Xcode 15 job picked up the RevenueCat release build. Add it to the only remaining Xcode 15 job. Co-authored-by: Cursor <cursoragent@cursor.com>
…e-swift with swift package describe - Extract iOS 16 tests from run-test-ios-16-15-and-14 into a standalone run-test-ios-16 job on Xcode 15.4.0 with SPM release build - Rename remaining job to run-test-ios-15-and-14 (Xcode 14.3.1) - Add `swift package describe` as first step in all run-test jobs, making the validate-package-swift job redundant - Remove validate-package-swift job and all workflow references - Remove SPM RevenueCat build from spm-revenuecat-ui-ios-16 (now covered by run-test-ios-16) Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The iOS test jobs already cover all 4 Xcode versions (14, 15, 16, 26), so tvOS, macOS and watchOS jobs don't need to duplicate the validation. Co-authored-by: Cursor <cursoragent@cursor.com>
8f14708 to
679e14e
Compare
…ots workflow Co-authored-by: Cursor <cursoragent@cursor.com>
The old pattern `../*/__Snapshots__/*` only matched one directory level on each side of __Snapshots__, but snapshot files are 3+ levels deep (e.g. Tests/UnitTests/Misc/__Snapshots__/AnyEncodableTests/file.json). Use `**` for recursive matching in the git pathspec. Co-authored-by: Cursor <cursoragent@cursor.com>
…ts__ dirs" This reverts commit 7cf475f.
…sage snapshots Co-authored-by: Cursor <cursoragent@cursor.com>
2a39c12 to
3fef904
Compare
| spm-release-build-xcode-15: | ||
| executor: | ||
| name: macos-executor | ||
| xcode_version: "15.4.0" | ||
|
|
||
| steps: | ||
| - checkout | ||
| - run: | ||
| name: SPM Release Build | ||
| command: swift build -c release --target RevenueCat | ||
| no_output_timeout: 30m | ||
| - slack-notify-on-fail |
There was a problem hiding this comment.
This is now part of the run-test-ios-16 job
tvOS was falling through to the #else branch in osVersionAndTestName, generating snapshots with the iOS prefix (e.g. iOS18-testFoo.1.json). This meant tvOS snapshots were indistinguishable from iOS snapshots. Add a #elseif os(tvOS) branch to produce tvOS-prefixed snapshot files (e.g. tvOS18-testFoo.1.json), enabling independent tvOS snapshot generation and validation. Co-authored-by: Cursor <cursoragent@cursor.com>
…tion" This reverts commit c06e438.
| validate-package-swift: | ||
| parameters: | ||
| xcode_version: | ||
| type: string | ||
| mac_os_executor_name: | ||
| type: string | ||
| executor: | ||
| name: << parameters.mac_os_executor_name >> | ||
| xcode_version: << parameters.xcode_version >> | ||
| steps: | ||
| - checkout | ||
| - run: | ||
| name: Validate Package.swift | ||
| command: swift package describe |
There was a problem hiding this comment.
Added as part of each of the run-test-ios-* jobs, so now this is run on every Xcode version
| - create-snapshot-pr-if-needed: | ||
| condition: << pipeline.parameters.generate_snapshots >> | ||
| job: "create_snapshot_pr" | ||
| version: "tvos" |
There was a problem hiding this comment.
This is new to this PR. Now we'll have tvOS-specific snapshot generation as well
| ) | ||
| end | ||
| ensure | ||
| sh("git", "checkout", original_branch) |
There was a problem hiding this comment.
Since we're now potentially running multiple tests in the same job, now push_snapshot_pr checkouts the original branch
Generated by 🚫 Danger |
tonidero
left a comment
There was a problem hiding this comment.
I think this looks great! Let's hope this improves CI 🙏
| version: "revenuecatui-18" | ||
| - create-snapshot-pr-if-needed: | ||
| condition: << pipeline.parameters.generate_revenuecatui_snapshots >> | ||
| job: "create_snapshots_repo_pr" |
There was a problem hiding this comment.
I would say, these 2 steps are quite confusing, one executing the create_snapshot_pr and this one create_snapshots_repo_pr... Might be worth documenting the difference?
Not a problem from this PR I would say though.
| # === iOS 17 tests === | ||
| - run: | ||
| name: Run tests | ||
| name: Run iOS 17 tests |
There was a problem hiding this comment.
I guess this won't be executed if the iOS 18 tests fail right? I was wondering whether it was worth to execute them anyways... But after thinking about it, it would complicate things and make the results harder to read IMO... So I think it's ok as it is :)
There was a problem hiding this comment.
Right. Actually this exact thing I'll tackle separately in #6333
| fi | ||
| } & | ||
| disown | ||
| echo "Started iOS 14.5 runtime installation in background" |
There was a problem hiding this comment.
I do wonder if we should try to move most of this logic to fastlane... But I'm ok keeping it here for now.
There was a problem hiding this comment.
Right. I see the point. I'll check how to achieve that
There was a problem hiding this comment.
I think I'm going to keep this for now, as it deals with the background process and it's mostly CI orchestration rather than test execution/artifact handling, which should be in fastlane grounds. Happy to discuss further or to iterate though!
The existing no_output_timeout doesn't apply because the loop prints periodic "Still waiting..." messages. Add an explicit elapsed-time check so the step fails cleanly instead of waiting indefinitely. Co-authored-by: Cursor <cursoragent@cursor.com>
The loop prints output every 10 seconds, so no_output_timeout never triggers. The explicit 30-minute elapsed-time check is sufficient. Co-authored-by: Cursor <cursoragent@cursor.com>
Checklist
Motivation
Each CI job spins up a separate macOS machine. Many jobs that share the same Xcode version can run sequentially on a single machine, reducing the number of billable machines per CI run.
Additionally, an Apple bug (FB22032719) causes SKProductsRequest to fail on iOS 18.6 simulators under Xcode 26 (
missingValue for StoreKit.ProductResponse.Key.price). This forces iOS 18 tests to run under Xcode 16 instead of Xcode 26.Description
Merges several CI jobs that share an Xcode version into single jobs, and removes standalone jobs that are now redundant:
run-test-ios-15-and-14run-test-ios-14+run-test-ios-15+spm-release-build-xcode-14+validate-package-swift-5.8run-test-ios-16run-test-ios-16+spm-release-build-xcode-15run-test-ios-18-and-17run-test-ios-17+run-test-ios-18run-test-ios-26run-test-ios-26run-test-tvos-and-macosrun-test-tvos+run-test-macos+spm-release-buildrun-revenuecat-ui-ios-18-and-17run-revenuecat-ui-ios-17+run-revenuecat-ui-ios-18Removed standalone jobs (absorbed into the unified jobs above):
spm-release-buildrun-test-tvos-and-macos(Xcode 16 SPM build)spm-release-build-xcode-14run-test-ios-15-and-14(Xcode 14 SPM build)spm-release-build-xcode-15run-test-ios-16(Xcode 15 SPM build)validate-package-swift-5.8run-test-ios-*jobs runswift package describe(Xcode 14, 15, 16, 26)Grouping rationale:
Within each unified job, tests run from newest to oldest iOS version. Each
run-test-ios-*job also runs an SPM release build as its first step, absorbing the standalonespm-release-build*jobs.Other changes:
tvOS{version}-) inCurrentTestCaseTracker.osVersionAndTestNameand enabled snapshot generation support in thetest_tvosFastlane lane and CI job. Previously, tvOS snapshots were silently merged with iOS snapshots due to sharing the sameiOSfile prefix.Known tradeoffs
Diff
The only changes are done in CircleCI's
config.ymlandfastfile. The rest of the diff are the new tvOS snapshot filesNote
Medium Risk
CI-only but broad workflow refactoring: combining previously parallel jobs into sequential runs and changing artifact/snapshot handling could cause missed coverage on early failures or break CI expectations until validated.
Overview
Reduces CircleCI macOS machine usage by merging multiple platform/version test jobs into a few sequential “combo” jobs (e.g.
run-test-ios-18-and-17,run-test-ios-15-and-14,run-test-tvos-and-macos,run-revenuecat-ui-ios-18-and-17) and removing now-redundant standalonevalidate-package-swift/spm-release-build*jobs while keeping an SPM release build +swift package describeat the start of the unified jobs.Improves CI artifact handling by making
compress_result_bundlesafe when the.xcresultdirectory is missing, cleaningfastlane/test_outputbetween sequential runs, and preserving per-OS-version.xcresulttarballs with distinct names/artifact destinations.Adds new tvOS 18 snapshot baselines under
Tests/UnitTests/**/__Snapshots__to support tvOS snapshot generation in CI.Written by Cursor Bugbot for commit 671831f. This will update automatically on new commits. Configure here.