303 Commits
Author SHA1 Message Date
RevenueCat Git BotandAntonio Pallares 56b2ebff25 Version bump for 5.102.3 (#8233)
Co-authored-by: Antonio Pallares <ajpallares@users.noreply.github.com>
2026-11-06 16:48:54 +01:00
RevenueCat Git Bot 94746e3949 Version bump for 5.102.2 (#8228) 2026-11-05 11:30:29 -06:00
RevenueCat Git Bot 8c5774300e Version bump for 5.102.1 (#8212) 2026-11-05 03:36:28 -06:00
Rosie Watson 28e209aa0e WFL-822 | Add Maestro tests for workflow branch routing (#8210)
* test(workflows): add Maestro tests for workflow branch routing

Covers the default route (Testimonials 1 to paywall) and an es-ES locale audience routing to Testimonials 3.

* test(workflows): trim branch test comments
2026-11-05 09:09:05 +00:00
Facundo MenzellaandClaude Opus 5.5 afd06bf825 Move rc-maestro to Projects and rename it AutomatedSDKTestsApp (#8190)
* other: move PurchaseTester to Projects

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* other(ci): add a PurchaseTester smoke build with Tuist

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* other: move rc-maestro to Projects

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* other: rename rc-maestro to AutomatedSDKTestsApp

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 15:21:45 +00:00
RevenueCat Git Bot 3b54af8f8a [AUTOMATIC] Release/5.102.0 (#8191)
* Version bump for 5.102.0

* Update RevenueCat-Swift.h for version 5.102.0
2026-11-03 15:50:43 +01:00
Facundo MenzellaandClaude Opus 5.5 e59f0f3251 Move PurchaseTester to Projects (#8189)
* other: move PurchaseTester to Projects

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* other(ci): add a PurchaseTester smoke build with Tuist

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 12:02:57 +01:00
Facundo MenzellaandClaude Opus 5.5 8205ba615f other: move the checkpoint samples to SampleCat and delete CheckpointTester (#8162)
* other(samplecat): add a Checkpoints tab with 4 samples

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* other: delete CheckpointTester

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* other: point agents to SampleCat for integration examples

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* other(samplecat): use result.hasEntitlement in checkpoint callbacks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* other(ci): add a SampleCat smoke build with Tuist (#8163)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 10:34:19 +00:00
RevenueCat Git Bot 609532bd04 [AUTOMATIC] Release/5.101.0 (#8174)
* Version bump for 5.101.0

* Update RevenueCat-Swift.h for version 5.101.0
2026-11-02 10:57:25 +01:00
RevenueCat Git Bot 8718d1cdc2 Version bump for 5.100.0 (#8161) 2026-10-30 18:02:37 +01:00
Facundo MenzellaandClaude Opus 5.5 bdd049247f other(maestro): add checkpoint purchase flows with the SDK presenter (#8132)
* other(maestro): add checkpoint purchase flows with the SDK presenter

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* other(rc-maestro): close the checkpoint paywall with its close button

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-29 15:01:05 +00:00
RevenueCat Git Bot dfaa530def Version bump for 5.99.2 (#8138) 2026-10-29 15:38:30 +01:00
RevenueCat Git Bot 834e93599e Version bump for 5.99.1 (#8133) 2026-10-29 12:14:45 +01:00
Facundo MenzellaandClaude Opus 5.5 e3ebb0336b other(maestro): add checkpoint resolution screen (#8088)
* other(maestro): add checkpoint resolution screen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* other(maestro): drop the unused app user id label

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* other(maestro): drive the checkpoint screen from launch arguments

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* other(maestro): read the flow result from CheckpointResult

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* other(maestro): add checkpoint flows (#8089)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-28 15:49:27 +01:00
RevenueCat Git Bot 039fea571a [AUTOMATIC] Release/5.99.0 (#8119)
* Version bump for 5.99.0

* Update RevenueCat-Swift.h for version 5.99.0
2026-10-26 12:42:34 +01:00
Dave DeLong 6ed515865a Simplify HTTP path types (#7987) 2026-10-23 11:11:52 -06:00
RevenueCat Git Bot 4dbf35ec80 [AUTOMATIC] Release/5.98.0 (#8105)
* Version bump for 5.98.0

* Update RevenueCat-Swift.h for version 5.98.0
2026-10-22 17:21:03 +02:00
RevenueCat Git Bot 1f5814efd7 [AUTOMATIC] Release/5.97.0 (#8097)
* Version bump for 5.97.0

* Update RevenueCat-Swift.h for version 5.97.0
2026-10-21 20:57:23 +02:00
RevenueCat Git Bot 3b75fbda1f Version bump for 5.96.1 (#8069) 2026-10-20 21:25:40 +02:00
RevenueCat Git Bot 3a55c70e50 [AUTOMATIC] Release/5.96.0 (#8051)
* Version bump for 5.96.0

* Update RevenueCat-Swift.h for version 5.96.0
2026-10-16 21:24:56 +02:00
Facundo MenzellaandClaude Opus 5.5 f1113bf6d9 other(magic-weather): link RevenueCatUI in the MagicWeatherSwiftUI Xcode project (#8039)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 11:53:45 +00:00
Rick f11a6bc146 feat(checkpoints): add CheckpointResult result container (#8035)
* feat(checkpoints): add checkpoint result container

* fix(checkpoints): satisfy line length lint

* fix(checkpoints): align checkpoint result parity

* test(checkpoints): preserve flow result API coverage
2026-10-16 11:26:17 +02:00
Rick 02a4c3edac refactor(checkpoints): simplify error presenter completion (#8012)
* refactor(checkpoints): simplify error presenter completion

* fix(checkpoints): update test apps for simplified error presenter

* test(checkpoints): update error presenter API coverage

* refactor(checkpoints): describe error presenter failure kinds

* fix(checkpoints): classify workflow presentation errors

* fix(checkpoints): resolve global error presenter lazily

* docs(checkpoints): clarify error presentation API
2026-10-15 18:36:08 +02:00
Facundo MenzellaandClaude Opus 5.5 c7d755c3e6 fix(customer-center): stop the hang on iOS 16 and 17 when the single-purchase screen opens purchase history (#7993)
* test(maestro): open purchase history from the single-purchase Customer Center screen

Maestro cannot create an expired subscription during a run, so the app shows
Customer Center with a fixed history (one active and one expired subscription).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(customer-center): stop the hang on iOS 16 and 17 when the single-purchase screen opens purchase history

The screen read `openURL` from the environment. On iOS 16 and 17 that value
changes on every layout pass once a screen is pushed on top, so the screen
redrew forever and the main thread stalled. Below iOS 18 the Contact support
button now opens the URL through `URLUtilities`. iOS 18 and later keep the
environment action.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 12:12:28 +02:00
RevenueCat Git Bot a1e4b85346 [AUTOMATIC] Release/5.95.0 (#7991)
* Version bump for 5.95.0

* Update RevenueCat-Swift.h for version 5.95.0
2026-10-12 14:45:09 +02:00
Facundo MenzellaandClaude Opus 5.5 3bd8854c92 other(workflows): maestro flow for the experiment variant after a log in (#7922)
An anonymous user sees their variant, then logs in as the pinned user on the
other variant and must see that user's variant. rc-maestro gets one log in
button per id in the log_in_app_user_ids launch argument.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 16:17:40 +00:00
RevenueCat Git Bot 535a9ba8b4 Version bump for 5.94.0 (#7965) 2026-10-08 20:19:09 +02:00
Facundo MenzellaandClaude Opus 5 8ea8e74bde feat(workflows): turn on workflow branch routing (#7908)
Deletes `ENABLE_WORKFLOW_BRANCHING` and the `SystemInfo.branchingEnabled` it
gated, so a branch resolves its audiences whenever remote config is on.
`DisabledBranchResolver` stays for the remote-config-off path, where there is no
audiences topic to read.

Adds the Maestro flow that covers it end to end: a workflow whose first step is
an audience-routed experiment, asserting the routed variant renders and the
fallback's screen does not.

`Purchases.workflow(forWorkflowIdentifier:)` lets the tester open one workflow
directly, so the flow does not depend on the offering to workflow mapping.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-08 10:08:36 +02:00
RevenueCat Git Bot 8d14a018f2 Version bump for 5.93.0 (#7944) 2026-10-07 22:35:47 +02:00
Toni RicoandClaude Fable 5.1 c227423581 Add Maestro flow for developer-provided offering filtering packages (#7934)
Presents the current offering with $rc_monthly removed and asserts only
the annual card renders and is the package the purchase targets.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 12:23:57 +02:00
Rick 8144cedfd8 feat(checkpoints): add error presenter API (#7901)
* feat: add checkpoint error presenter types

* feat: expose checkpoint error presenter configuration

* feat: select checkpoint error presenter

* feat: route checkpoint errors to presenters

* Align checkpoint error handling with Android

* Handle checkpoint error presentation results

* Add default checkpoint error presenter

* Add error presenter checkpoint demo

* Add default error presenter to Xcode target

* Keep workflow errors active after retry

* Queue checkpoint back navigation during transitions

* Fix checkpoint error presenter lint violations

* Add default error presenter tests to Xcode project

* Group active paywall presentation state

* Simplify workflow back navigation requests

* Rename workflow back navigation bridge

* Preserve terminal workflow error presentations

* test(checkpoints): cover purchase error after restore

* Fix checkpoint parameter forwarding

* Fix default error presenter actor isolation
2026-10-06 10:51:20 +02:00
Rick d43036f334 feat(checkpoints): add presentation modes to checkpoint flows (#7894)
* feat(checkpoints): add presentation modes

* test(checkpoints): add presentation mode controls

* fix: include checkpoint presentation mode source

* fix: support checkpoint sheets on tvOS

* fix: register checkpoint presentation source

* fix: exclude checkpoint modal style on watchOS

* refactor(checkpoints): rename flow presentation mode

* test(checkpoints): rename tester presentation modes
2026-10-05 13:36:34 +00:00
Facundo Menzella fc8cd36780 other(workflows): pin each user to a variant in the experiment maestro flow (#7896) 2026-10-05 14:49:35 +02:00
Facundo MenzellaandClaude Opus 5.5 e3923df148 Add Maestro flow for a workflow screen without text (#7899)
* Add Maestro flow for a workflow screen without text

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* quote the offering id so the launch arg reaches the app

An unquoted value starting with [ is dropped by plist parsing, so the app
opened default_workflows and never reached Buy.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 17:20:49 +02:00
RevenueCat Git Bot 0a5ebdce4b Version bump for 5.92.0 (#7882) 2026-09-30 20:58:37 +02:00
Rick c17a4ffe1a refactor(checkpoints): rename invite-only API SPI (#7852) 2026-09-28 15:29:25 +02:00
RevenueCat Git Bot f8e132b13d Version bump for 5.91.0 (#7817) 2026-09-23 21:31:39 +02:00
Facundo Menzella 278f3d2d7b other(workflows): maestro flows for workflow experiments (#7805)
* other(workflows): maestro flows for workflow experiments

Adds an app_user_id launch argument so enrollment is deterministic per run. The
backend resolves the experiment combo from that id, so pinning it makes a run
repeatable.

Two flows against a workflow whose third step is an experiment. One asserts a
started experiment lands on a variant paywall, the other asserts an experiment
that was never started serves the holdout. Both exist because khepri was
publishing the experiment step unpruned, so the SDK walked into a step with no
screen and rendered nothing.

* fix the flows against a real run

The Continue buttons are labelled Continue 1/3 and 2/3, and Maestro matches text
in full, so plain Continue never matched. Env variables also do not interpolate
inside launchApp arguments, so the offering and app user id are inline now.

Verified on the simulator: four runs of the assigns-variant flow, all green, all
resolving variant A for the same app user id.

* assert the variant, and hold the holdout flow back

The generic Restore Purchases assertion did not identify a variant, and the two
conditional screenshot blocks assert nothing, so a wrong paywall (including the
SDK default fallback, which also shows a restore control) would have passed.
Match on both variant titles instead.

Exact Continue 1/3 and 2/3 labels now, matching the sibling flows.

The holdout flow moves to a follow-up: it needs a workflow whose experiment was
never started, and fastlane runs the whole workflows directory, so shipping it
against a missing offering would fail the all-tasks-passed gate.

* add the holdout flow

Against [experiment-unstarted] (offering 'experiments unstarted'), a duplicate
whose experiment was never started. The backend collapses the experiment step to
its fallback, so the served graph is screen 1 to screen 2 to variant A and the
variant B step is pruned out.

Three green runs. This workflow's buttons are plain Continue, not the numbered
labels the other one uses.
2026-09-22 17:46:18 +02:00
652c1fae98 other(CI): introduce iOS 27 CI jobs (#7705)
* introduce ios27 CI jobs

* add iOS 27 to OSVersionEquivalent

* Generating new test snapshots (#7706)

* Generating new test snapshots (#7711)

* skip tests where storefront changing doesn't work (#7712)

* fix: preserve optional callback results with Xcode 27 (#7714)

* test: use consumables for custom transaction listener streams (#7715)

* Fix orchestrator cancellation test coverage on iOS 27 (#7717)

* Fix orchestrator cancellation test coverage on iOS 27

* Preserve cancellation test and mock availability on older SDKs

* Stabilize StoreKit transaction fetcher test fixtures on iOS 27 (#7716)

* test: stabilize StoreKit transaction fetcher fixtures on iOS 27

* Limit StoreKit fixture workaround to OS 27

* Wait for StoreKitTest intro eligibility reset on OS 27 (#7718)

* Wait for StoreKitTest intro eligibility reset on OS 27

* Give intro eligibility reset a 30-second timeout

* Avoid OS 27 product lookup in custom listener fixtures

Create custom-stream consumable transactions directly through SKTestSession on OS 27, avoiding the empty Product.products response seen in CI job 786483. Preserve the older-OS purchase path and all listener assertions. Test-only; no SDK or public API changes.

Validation: custom-stream tests passed 20/20 on iOS 27 and 6/6 on iOS 26.3.1; broader listener suites passed on iOS 27. SwiftLint and git diff --check passed.

* Retry transient empty StoreKitTest fixture lookups on OS 27

CI 786512 failed renewal diagnostics before purchasing because Product.products returned no fixture product. Retry only empty shared fixture lookups for up to 10 seconds on OS 27; keep earlier OS behavior, propagate errors/cancellation, and still fail on persistently missing products. No SDK or public API changes.

Add regression coverage for recovery, immediate success, bounded empty results, zero-timeout behavior, and error propagation. Validation: 186/186 selected iOS 27 runs and 63/63 iOS 26.3.1 runs; final helper tests 15/15 on each OS. SwiftLint and diff checks passed. UI failures remain covered by separate PR #7720.

* Un-skip the StaticString tests that still pass on Swift 6.4 (#7722)

* Un-skip the StaticString tests that still pass on Swift 6.4

`@_disfavoredOverload` is only ignored for labeled and closure-taking
calls, so the unlabeled `logIn(_:)` and the `String?`-sibling Builder
API still emit the warning. Both tests pass on Xcode 27.0.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Restore why the StaticString/String overload pair exists

The rewritten comment explained which call shapes @_disfavoredOverload
still steers, but dropped the reason we rely on it at all: the
StaticString overloads are deprecated yet typechecker-favored so that a
hardcoded app user ID warns at compile time. Without that, a future
reader can't tell what the broken behavior costs us.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>

* Initialize StoreKitTest before observing transaction updates

Start the shared fixture listener after SKTestSession configuration instead of class setup. CI logs showed the early listener using Sandbox before XcodeTest initialization, with subsequent fixture product requests staying in Sandbox.

Test-only; no SDK or public API changes. Validated cache tests on two fresh iOS 27 simulators, 90 focused executions on the existing iOS 27 simulator, and 70 on iOS 26.3.1. A broader first-launch run timed out in testOnePurchasedProduct; its suite passed all 12 executions on rerun. SwiftLint passed.

* Fix paywall URL callback delivery across session resets (#7720)

* Fix paywall URL callback delivery across session resets

* Release audio-session handler after configuration test

Balance registration in testSetsPlaybackCategoryWithMixing so the static session registry cannot retain stale state and affect a later mock reusing the same ObjectIdentifier. Test-only cleanup; no production or public API changes.

Reproduced the failing suite on iOS 26.5 before the fix. All 7 audio-session tests passed 20 repetitions (140/140) after cleanup. SwiftLint and git diff --check passed.

* Preserve Sendable isolation when registering paywall callbacks

Forward URL and web-checkout callbacks through explicitly MainActor Sendable closures. Avoid the older-compiler function-conversion warnings rejected by CocoaPods lint without changing public declarations or suppressing warnings.

Validation: Xcode 16.4 RC Release simulator build passed for arm64 and x86_64. Callback and audio-session tests passed 81/81 on iOS 26.5 and 81/81 on iOS 27. SwiftLint and diff checks passed. Full pod lib lint remains for CI because local Bundler 2.6.6 is unavailable.

---------

Co-authored-by: Josh Holtz <me@joshholtz.com>

* Create observer-mode transaction fixtures through StoreKitTest on iOS 27

The first CI purchase attempted interactive Sandbox authentication despite product lookup using XcodeTest. Avoid Product.purchase for these detector fixtures on OS 27, read back the verified transaction and JWS, and preserve the existing callback and deduplication assertions. Older OS versions keep the original setup.

Test-only; no SDK or public API changes. Observer suite passed 30/30 executions on a fresh iOS 27 simulator and 30/30 on iOS 26.3.1. SwiftLint passed.

* Initialize StoreKitTest in a separate process before iOS 27 CI tests

The first test host can keep its purchase connection in Sandbox even while product lookup uses XcodeTest. Configure the local StoreKit session in a preflight process, then run the unfiltered suite on the same simulator without erasing or reinstalling it. Fail the job if preflight fails. Enable only for the iOS 27 core job.

CI/test-only workaround; no production or public API changes. Fresh simulator preflight followed by the full StoreKit target: 491 passed, 23 skipped, zero failures. Second fresh simulator: preflight then the previously hanging purchase test passed 10/10. iOS 26 compatibility: 14 passed. SwiftLint, Ruby/YAML syntax and four lane-control checks passed. Validated via xcodebuild; the complete Fastlane lane awaits CI.

* other: restore Result-based continuation now that #7723 is merged (#7727)

* fix: preserve errors when Result's Success is inferred as optional (#7723)

* fix: preserve errors when Result's Success is inferred as optional

`Result.init(_:_:)` takes `Success?`, so when `Success` is itself optional the
argument is promoted into a second optional layer where an absent value is
indistinguishable from a present one, and the error is never read. Built with
Xcode 27 this makes `syncAttributesAndOfferingsIfNeeded()` return `nil` rather
than throwing, since `Success` is inferred as `Offerings?` inside
`continuation.resume(with:)`.

Add an overload constrained to an optional `Success` that takes `Success`
directly and checks the error first, so `nil` remains a valid success. Both
overloads now yield a `.failure` regardless of which one is selected.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: cover both continuation return shapes for Result init selection

Most of the SDK's completion-handler-to-`async` wrappers return a non-optional
value, where `Success` can only be inferred one way. Cover that shape alongside
the optional one, and drop the two cases that duplicated existing coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: cover a nil value and nil error through an async continuation

The two initializers diverge here: the preserving one treats it as a valid
success while the unwrapping one traps, so pin which one an optional `Success`
reaches.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>

* Restore Result-based continuation in syncAttributesAndOfferingsIfNeededAsync

#7714 split this into an explicit if-let because Result(offerings, error)
inferred Success as Offerings?, promoted the absent value into the outer
layer and never read the error. #7723 fixed that in the initializer, so the
workaround is no longer needed.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>

* [1/7] Support current and older Xcode toolchains (#7736)

* Support current and older Xcode toolchains [skip ci]

* Use compiler guards and shared StoreKit fixture helper [skip ci]

* Clarify StoreKit 27 presentation and refund errors [skip ci]

* Account for the standard refund error description prefix [skip ci]

* Avoid an unknown-error warning for recognized StoreKit errors [skip ci]

* Exercise the public error conversion in the logging regression test [skip ci]

* [2/7] Synchronize event tests without changing background scheduling (#7740)

* Synchronize event tests without changing background scheduling [skip ci]

* Await event storage directly in backend integration coverage [skip ci]

* Own the events manager in backend integration tests [skip ci]

* Configure the integration test backend explicitly [skip ci]

* Explain direct event manager integration testing [skip ci]

* [3/7] Isolate asynchronous test work with a debug-only warmup hook (#7741)

* Isolate asynchronous test work with a debug-only warmup hook [skip ci]

* Drain eligibility warmups even when the leak check fails [skip ci]

* Await eligibility warmup tasks during test teardown

* [4/7] Stabilize StoreKit integration fixtures and scope OS 27 exceptions (#7742)

* Stabilize StoreKit integration fixtures and scope OS 27 exceptions [skip ci]

* Verify recovered purchase completion through unfinished transactions [skip ci]

* Use consumable fixtures for purchase event tests [skip ci]

* Quarantine known SK1 receipt deduplication race on iOS 27 [skip ci]

* Verify each consumable transaction after switching users [skip ci]

* Scope finish assertions to each test purchase [skip ci]

* Allow backend attribution posting to finish in integration test

* Wait for unfinished StoreKit fixture transactions before fetching

* Quarantine deferred late-identifier SK1 finishing case on iOS 27

* Scope missing unfinished fixture exception to iOS and tvOS 27

* Allow persisted ad events to finish posting in integration test

* Clarify async test failure handling comment [skip ci]

* Centralize StoreKit test exceptions and transaction helpers

* Check live StoreKit identifiers when waiting for queue removal [skip ci]

* Verify virtual currency purchases finish with their StoreKit identifiers

* [5/7] Prepare local StoreKit sessions for Maestro tests (#7743)

* Prepare local StoreKit sessions for Maestro tests [skip ci]

* Wait for StoreKit warmup before Maestro purchase flows

* Pass Maestro warmup flags as UserDefaults launch arguments [skip ci]

* [6/7] Update tvOS and backend snapshot references (#7744)

* Add tvOS 27 snapshot references [skip ci]

* Update load-shedder snapshot for price variable compatibility

* [7/7] Extend Xcode 27 validation across CI jobs (#7745)

* Extend Xcode 27 validation across CI jobs

* Align backend test device default with iOS 27

* Keep CI cleanup running when simulator environment restoration fails

* Address Bugbot findings on the Xcode 27 CI jobs

- Wait for eligibility warmups before asserting Purchases does not leak.
  Teardown blocks run LIFO, so the leak check was running first while
  in-flight warmup work could still retain the instances.
- Let the RevenueCatUI lane opt out of test diagnostics collection via
  RC_COLLECT_TEST_DIAGNOSTICS, and set it on the iOS 27 UI job. That lane
  uses xcodebuild directly, so it never picked up SCAN_XCARGS like the
  other Xcode 27 jobs, and can hang in simctl diagnose after tests pass.
- Skip the StoreKitTest preflight when generating snapshots on iOS, as
  tvOS already does. run-test-ios-27 sets RC_STOREKIT_TEST_PREFLIGHT
  unconditionally and also runs in the generate-snapshot workflow.
- Apply the Xcode 27 validation xcconfig to installation-tests-carthage.
  It defaults to Xcode 27 but was the only source-building job missing
  the supported deployment targets.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Clear the singleton before waiting on eligibility warmups

The previous commit reordered the teardown blocks so warmups drained
before the leak check. That timed out after 60s in the backend
integration tests: the warmup tasks only finish once
`Purchases.clearSingleton()` runs, so waiting on them first deadlocks.

Collapse both into a single teardown block with the steps in the order
they actually depend on: clear the singleton, drain the warmups, then
assert nothing leaked. This still keeps the leak assertion after the
warmups, which is what the original ordering got wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* other: re-enable storefront tests on iOS 27.2+ (#7797)

* re-enable storefront tests on iOS 27.2+

* copy update

* Restore the original eligibility warmup teardown order

Bugbot flagged the LIFO teardown ordering here as a bug, but its premise
does not hold: the warmup tasks capture `PaywallCacheWarming`, which
`Purchases` owns, so they never retain a `Purchases` instance and cannot
make the leak check fail.

Both reorderings tried in this branch made the backend integration tests
time out after 60s waiting on warmups that only drain once the instance
is torn down. Restore the original order and document why it is the way
it is, so the next reader does not make the same change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Wait for finish() to settle in testFiltersOutFinishedTransaction

`run-test-ios-27` flaked here: the fetcher reported both the finished and
the unfinished fixture. `finish()` is eventually consistent on OS 27, so
the finished transaction can still be listed in `Transaction.unfinished`
after it returns.

Wait for the unfinished queue to settle before reading the fetcher, the
same way the sibling fixtures in this file already do.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Retry failing macOS unit tests, like the iOS and tvOS lanes do

`run-test-tvos-and-macos` moves to Xcode 27 in this branch and the macOS
step has been failing intermittently since. It is a different test each
time (the plan runs in a random order) and the failures are timing ones:
"main run loop was unresponsive", a redirect returning no response.

The iOS and tvOS lanes already absorb this with `scan`'s 5 retries. This
lane drives xcodebuild directly and had none, which is why it is the only
one that goes red. Ask xcodebuild to retry the failing tests instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Don't fail backend integration tests on stalled OS 27 eligibility warmups

This branch moves the backend integration jobs to Xcode 27 / iOS 27, and
since then a different test goes red on most runs with "Eligibility cache
warmup did not finish after 60s". Intro eligibility under StoreKitTest is
already known to misbehave on OS 27 (PR #7718, and the OS 27 exceptions in
AvailabilityChecks), and because the paywall cache is an actor, one stalled
check blocks every warmup queued behind it -- hence the count never being 1.

The wait is isolation hygiene, not a product assertion, so on OS 27 it now
warns with the pending count instead of failing an unrelated test. Every
other OS keeps the hard assertion, as do the unit tests that use the
tracker directly: leniency is opt-in via `failOnTimeout`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
Co-authored-by: Josh Holtz <me@joshholtz.com>
Co-authored-by: Antonio Pallares <ajpallares@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 14:34:04 -05:00
RevenueCat Git Bot 9416e92e14 Version bump for 5.90.2 (#7768) 2026-09-18 12:04:12 +02:00
Rick a3dc5f14cc feat(checkpoints): add app-owned offering presenter API (#7626)
* feat(checkpoints): add app-owned offering presenter API

* refactor(checkpoints): rename offering presenter to paywall presenter

* Add paywall presenter API for checkpoint offerings

* Fix paywall presenter linting

* Map paywall presenter outcomes to checkpoint results

* Add local checkpoint paywall presenter overrides

* Add checkpoint paywall presenter demo to tester

* Fix paywall presenter integration after rebase

* Pass purchase results through custom paywall presenters

* Add checkpoint presenter files to Xcode project

* Align checkpoint tester with FlowResult API

* Remove legacy checkpoint result APIs

* Synchronize customer info after custom paywall presentation

* Refine checkpoint paywall presentation handling

* Merge checkpoint workflow execution into presenter

* Centralize checkpoint paywall presenter selection

* Fix checkpoint tester paywall presentation lifecycle

* Release checkpoint presentation before syncing

* Rename global checkpoint paywall presenter

* Internalize paywall presentation params initializer

* Capture paywall presenter before checkpoint resolution

* Make paywall presentation result forward compatible

* Cover stale checkpoint presentation completions

* Extract checkpoint presentation slot

* Unify checkpoint presentation coordination

* Simplify checkpoint manager dependencies

* Simplify checkpoint presentation outcomes

* Internalize checkpoint workflow state

* Clarify checkpoint presentation naming

* Align presenter API with callback-only checkpoints

* Simplify checkpoint presentation internals

* Handle terminal offering steps in paywall resolution

* Disable exit offers for checkpoint paywalls

* Clarify obtained entitlement semantics

* Complete cancellation for detached checkpoint paywalls

* Update checkpoint files in Xcode project

* Avoid Swift if expression in checkpoint presenter

* Guard workflow presenter execution tests by platform

* Support older Swift checkpoint presenter builds

* Clarify checkpoint presentation type naming

* Clarify continued paywall result documentation

* Preserve completed default paywall outcomes

* Move checkpoint exit-offer opt-out to follow-up

* Remove cancellation handling for the retired async checkpoint API
2026-09-18 10:01:36 +02:00
RevenueCat Git Bot 97bac28bcb Version bump for 5.90.1 (#7766) 2026-09-17 16:15:17 +02:00
RevenueCat Git Bot d70fc0cdd7 Version bump for 5.90.0 (#7759) 2026-09-17 13:03:38 +02:00
Rick ed3827071d feat(checkpoints): add gate-focused checkpoint API (#7621)
* Adapt checkpoint callback API to completion model

* Preserve successful checkpoint outcomes

* Test concurrent checkpoint callback suppression

* Test restored checkpoint back navigation

* Add checkpoint call store tests to Xcode project

* Address checkpoint callback review feedback

* Fix checkpoint tester back-out handling

* Fix checkpoint tester result handling

* Align checkpoint result types with Android

* Simplify checkpoint tester onboarding completion

* Align checkpoint entitlement mapping with Android

* Require checkpoint completion callback

* Rename cached customer info provider
2026-09-15 12:00:24 +02:00
Rick dc7ee0a7c7 feat(checkpoints): distinguish back navigation from close actions (#7685)
* Tell back navigation apart from close actions in checkpoint paywalls

* fix: keep sheet dismissals distinct from checkpoint back navigation

* refactor: model checkpoint completion explicitly

* refactor: clarify workflow dismissal handling

* refactor: clarify checkpoint execution result

* refactor: clarify back navigation resolution

* test: fix checkpoint execution test setup

* fix: preserve checkpoint back navigation through exit offers

* fix: dismiss bottom sheets locally from workflows

* Restrict workflow error handling to supported platforms

* refactor: split workflow offering resolution

* fix: compile workflow offering resolution

* Resolve offerings per checkpoint workflow step

* Fix duplicate workflow error handler initializer

* refactor: unify workflow dismissal resolution

* refactor: stage checkpoint dismissal reasons

* test: cover workflow sheet back navigation

* fix: compile checkpoint dismissal state on tvOS
2026-09-15 12:00:24 +02:00
Rick 80a6922626 refactor(checkpoints): remove checkpoint listener API (#7672)
* Resolve offerings per checkpoint workflow step

* Remove checkpoint listener API

* test: preserve checkpoint result API coverage

* Fix duplicate workflow error handler initializer

* Use workflow offering resolver for checkpoints
2026-09-14 15:30:26 +02:00
RevenueCat Git Bot a999dc182b Version bump for 5.89.0 (#7678) 2026-09-09 22:53:43 +02:00
Rick 8b024e8009 feat(remote-config): remove the remote config session kill switch (#7524)
* Remove remote config kill switch

# Conflicts:
#	Sources/Checkpoints/CheckpointWorkflowResolver.swift
#	Tests/UnitTests/Checkpoints/CheckpointWorkflowResolverTests.swift

* Improve remote config retry tests

* feat(remote-config): stop decoding offering paywall components

* test(remote-config): align workflow integration test naming

* refactor(remote-config): limit offerings preview APIs to debug builds

* refactor(remote-config): address review cleanup

* fix(remote-config): propagate workflow fetch failures

* refactor(remote-config): derive paywall components from decoding mode

* Remove offerings paywall component decoding

* Update offerings component decoding tests

* Fix CI test fixture compilation

* Fix offerings initializer argument order

* Preserve default offerings component marker
2026-09-08 07:06:04 +02:00
Peter PorfyandRevenueCat Git Bot a272220244 feat(ads): ad tracking and rewarded ad grants beta (#7490)
* chore(ads): remove ads experimental annotations

* fix: remove duplicate import

* fix: regenerate api baseliens

* fix: os gate for public apis

* fix(ads): add api documentation

* fix(ads): doc was outdated

* fix(ads): val to let

* fix(ads): restore documentation

* fix: remove objc support

* fix: remove objc support

* Update baseline swiftinterface files (#7625)

---------

Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
2026-09-07 14:02:35 +02:00
Rick 7fae08abfc feat(Checkpoints): namespace checkpoint result and context types (#7570)
* Namespace checkpoint result types

* Namespace checkpoint context types
2026-09-07 09:25:32 +02:00