Skip to content

Migrates PostHog attribution from PHC to kn-core#840

Merged
JayShortway merged 1 commit into
3.0.0-devfrom
migrate-posthog
May 6, 2026
Merged

Migrates PostHog attribution from PHC to kn-core#840
JayShortway merged 1 commit into
3.0.0-devfrom
migrate-posthog

Conversation

@JayShortway

Copy link
Copy Markdown
Member

Description

Migrates #837 to 3.0.0.

@JayShortway JayShortway self-assigned this May 6, 2026
@JayShortway JayShortway requested a review from a team as a code owner May 6, 2026 12:04

@vegaro vegaro left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you!

@JayShortway JayShortway merged commit a195adb into 3.0.0-dev May 6, 2026
12 checks passed
@JayShortway JayShortway deleted the migrate-posthog branch May 6, 2026 12:28
tonidero pushed a commit that referenced this pull request May 7, 2026
* Adds facade Gradle modules for Swift packages (#714)

* Migrates iOS from PHC to kn-core and kn-ui (#723)

* Migrates more iOS features from PHC to kn-core and kn-ui (#767)

* Migrates Android from PHC to purchases-android (#768)

* Deletes the deprecated datetime module (#769)

* Fixes release automations (#770)

* Updates Kotlin to 2.3.20 and Gradle to 9.4.1 (#771)

* Updates Compose Multiplatform to 1.9.3 (#778)

* Removes dead code (#779)

* Fixes caching of the Swift build tasks (#780)

* Adds iosApp run config (#785)

* Adds 3.0.0 migration guide (#793)

* Updates purchases-android to 10.0.0 (#797)

* Updates Fastlane README.md (#798)

Fastlane consistency updates

* No longer tries to update podspec files during release (#799)

* Release/3.0.0-beta.1 (#800)

* Version bump for 3.0.0-beta.1

* Updates VERSIONS.md

* Adds datetime module removal to migration guide (#802)

* Updates purchases-android to 10.0.2 (#801)

* Adds Amazon instructions to migration doc (#807)

* Removes unnecessary CI steps (#810)

* Add maestro E2E test app (#824)

* Add maestro E2E test app for 3.0.0

Adds a minimal Kotlin Multiplatform Compose app under e2e-tests/MaestroTestApp
for running Maestro E2E tests against the RevenueCat SDK.

Adapted for the 3.0.0 architecture:
- No CocoaPods dependency — iOS builds via Gradle + purchases-ios submodule
- Uses projects.knUi for native iOS paywall types
- Paywall presented as a native modal on iOS to work around Compose
  Multiplatform's UIKitViewController accessibility bridge limitation
  that prevents Maestro from seeing embedded SwiftUI content
- Android uses inline Compose Paywall which works with Maestro
- Uses RCPaywallViewControllerDelegateProtocol (not the removed PaywallProxy)

Made-with: Cursor

* Fix build.gradle.kts for Kotlin 2.3.20

Remove deprecated kotlinOptions { jvmTarget } block — the android {}
compileOptions block already sets Java compatibility, and Kotlin 2.3.20
no longer supports the old KotlinCommonOptions.jvmTarget accessor.

Made-with: Cursor

* Exclude MaestroTestApp from binary compatibility validation

The E2E test app is an application, not a library — it has no public
API surface to validate.

Made-with: Cursor

* Use SDK's Paywall composable directly instead of custom PaywallPresenter

Replace the expect/actual PaywallPresenter with the SDK's own
Paywall(options) composable — the E2E app should test the KMP public
API, not a custom native presentation layer.

Made-with: Cursor

* Skip test cases list in maestro tests using launch arguments

Pass e2e_test_flow as a launchApp argument so the app navigates
directly to the target test case screen, making tests faster.
The Test Cases list is preserved for manual/local usage.

Made-with: Cursor

* Refactor test case routing to use a central registry

Extract TEST_CASES registry to a dedicated TestCases.kt file, matching
the pattern used by purchases-capacitor and purchases-flutter. The
TestCasesScreen now dynamically builds from the registry, and App.kt
routes by flow key instead of a hardcoded Screen enum.

Made-with: Cursor

* Use version catalog for MaestroTestApp minSdk

Match the SDK's minSdk (21) instead of hardcoding 24.

Made-with: Cursor

* Document launch arguments and how to add new test cases

Made-with: Cursor

* Revert MaestroTestApp minSdk to 24 (required by revenuecatui)

The revenuecatui module has minSdk 24, which is higher than the SDK's
global android-minSdk of 21. Since MaestroTestApp depends on
revenuecatui, it must use minSdk 24.

Made-with: Cursor

* Simplify customer info fetching, remove delegate

Re-fetch customer info when the paywall is dismissed instead of
maintaining a global delegate. Also add a comment explaining the
minSdk 24 requirement.

Made-with: Cursor

* Review feedback: fix build phase and update README

- Remove reference to non-existent disable-x64.init.gradle.kts from the
  Xcode build phase (ARCHS/EXCLUDED_ARCHS env vars already handle this)
- Update README to reflect that Xcode handles the Kotlin framework build
  via its build phase, and clarify the CI vs local build flow

Made-with: Cursor

* Add .gitignore for MaestroTestApp

Covers Xcode build output and user-specific project data.

Made-with: Cursor

* Update README API key section with lane name and local run instructions

Made-with: Cursor

* Move API key commit warning to apply to both local run methods

Made-with: Cursor

* Remove unused testTag modifiers from PurchaseThroughPaywallScreen

Maestro uses visible text, not Compose test tags.

Made-with: Cursor

* Add maestro E2E test for purchase through paywall (#825)

* Add maestro E2E test app for 3.0.0

Adds a minimal Kotlin Multiplatform Compose app under e2e-tests/MaestroTestApp
for running Maestro E2E tests against the RevenueCat SDK.

Adapted for the 3.0.0 architecture:
- No CocoaPods dependency — iOS builds via Gradle + purchases-ios submodule
- Uses projects.knUi for native iOS paywall types
- Paywall presented as a native modal on iOS to work around Compose
  Multiplatform's UIKitViewController accessibility bridge limitation
  that prevents Maestro from seeing embedded SwiftUI content
- Android uses inline Compose Paywall which works with Maestro
- Uses RCPaywallViewControllerDelegateProtocol (not the removed PaywallProxy)

Made-with: Cursor

* Fix build.gradle.kts for Kotlin 2.3.20

Remove deprecated kotlinOptions { jvmTarget } block — the android {}
compileOptions block already sets Java compatibility, and Kotlin 2.3.20
no longer supports the old KotlinCommonOptions.jvmTarget accessor.

Made-with: Cursor

* Exclude MaestroTestApp from binary compatibility validation

The E2E test app is an application, not a library — it has no public
API surface to validate.

Made-with: Cursor

* Use SDK's Paywall composable directly instead of custom PaywallPresenter

Replace the expect/actual PaywallPresenter with the SDK's own
Paywall(options) composable — the E2E app should test the KMP public
API, not a custom native presentation layer.

Made-with: Cursor

* Skip test cases list in maestro tests using launch arguments

Pass e2e_test_flow as a launchApp argument so the app navigates
directly to the target test case screen, making tests faster.
The Test Cases list is preserved for manual/local usage.

Made-with: Cursor

* Refactor test case routing to use a central registry

Extract TEST_CASES registry to a dedicated TestCases.kt file, matching
the pattern used by purchases-capacitor and purchases-flutter. The
TestCasesScreen now dynamically builds from the registry, and App.kt
routes by flow key instead of a hardcoded Screen enum.

Made-with: Cursor

* Use version catalog for MaestroTestApp minSdk

Match the SDK's minSdk (21) instead of hardcoding 24.

Made-with: Cursor

* Document launch arguments and how to add new test cases

Made-with: Cursor

* Revert MaestroTestApp minSdk to 24 (required by revenuecatui)

The revenuecatui module has minSdk 24, which is higher than the SDK's
global android-minSdk of 21. Since MaestroTestApp depends on
revenuecatui, it must use minSdk 24.

Made-with: Cursor

* Simplify customer info fetching, remove delegate

Re-fetch customer info when the paywall is dismissed instead of
maintaining a global delegate. Also add a comment explaining the
minSdk 24 requirement.

Made-with: Cursor

* Review feedback: fix build phase and update README

- Remove reference to non-existent disable-x64.init.gradle.kts from the
  Xcode build phase (ARCHS/EXCLUDED_ARCHS env vars already handle this)
- Update README to reflect that Xcode handles the Kotlin framework build
  via its build phase, and clarify the CI vs local build flow

Made-with: Cursor

* Add .gitignore for MaestroTestApp

Covers Xcode build output and user-specific project data.

Made-with: Cursor

* Update README API key section with lane name and local run instructions

Made-with: Cursor

* Move API key commit warning to apply to both local run methods

Made-with: Cursor

* Remove unused testTag modifiers from PurchaseThroughPaywallScreen

Maestro uses visible text, not Compose test tags.

Made-with: Cursor

* Add maestro E2E test flows

Adds Maestro YAML test flows under e2e-tests/maestro/:
- purchase_through_paywall: navigates to the paywall screen, waits for
  the V2 paywall to render, confirms the test-store purchase, and
  verifies the "pro" entitlement is active
- confirm_purchase: reusable subflow for the sandbox purchase dialog
- config.yaml: sets the app ID for all flows

Made-with: Cursor

* Use launch arguments to skip test cases list in maestro tests

Navigate directly to the target test case screen via e2e_test_flow
launch argument instead of tapping through the test cases list.

Made-with: Cursor

* Use exact strings in confirm_purchase instead of regex

Both iOS and Android now show the same text, so regex patterns
are no longer needed. Matches the Capacitor approach.

Made-with: Cursor

* Remove redundant appId from confirm_purchase subflow

The parent flow already sets appId, so the subflow doesn't need it.

Made-with: Cursor

* Restore appId in confirm_purchase subflow

Maestro requires appId in any flow file that has a config section (---
separator). This is not redundant - without it Maestro fails with
"Either 'url' or 'appId' must be specified in the config section."

Made-with: Cursor

* Bypass Test Store Release-build crash in purchases-ios (#829)

* Bypass Test Store Release-build crash in purchases-ios

In v3.0.0 (currently in beta), purchases-ios ships as a pre-compiled
static library inside the published Kotlin/Native artifacts, always
built in Release. As a result, any app using purchases-kmp v3 with a
Test Store API key crashes at `configure` time on iOS (see #823).

Define the `BYPASS_SIMULATED_STORE_RELEASE_CHECK` Swift compilation
flag introduced in RevenueCat/purchases-ios#6710
when building the bundled `RevenueCat` target so the safeguard is
skipped.

Trade-off: apps shipped to production with a Test Store API key won't
be caught at runtime. We plan to revisit a smarter detection (e.g.
sandbox vs. production) in a follow-up.

Also bumps the upstream/purchases-ios submodule to the tip of the
companion PR branch. This needs to be re-bumped to a released
purchases-ios version once the upstream PR is merged.

Made-with: Cursor

* Revert upstream/purchases-ios bump

Drops the submodule bump from this PR. The bypass flag is being
introduced in purchases-ios via a separate PR and will be propagated
to this repo automatically by Renovate once a new purchases-ios
version including it is released.

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

---------

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

* Add Xcode 26 compatibility (#828)

* Fix cinterop header generation for Xcode 26 compatibility

Two issues caused cinterop to fail with Xcode 26 / Swift 6.2:

1. Shared SPM scratch directory: -Xswiftc -emit-objc-header-path applies
   to ALL swiftc invocations during `swift build`, so a dependency module's
   header could overwrite the target module's header. Fix: use per-target
   scratch directories.

2. Forward-declared dependency types: the correct target header uses @Class
   forward declarations for dependency types (e.g. RCCustomerInfo from
   RevenueCat), which cinterop turns into unresolvable stubs. Fix: include
   dependency headers in the target's modulemap so the full @interface
   definitions are available, and remove dependency -I paths from cinterop
   so -fmodules doesn't attribute those types to a foreign module.

Made-with: Cursor

* Restore dependency -I paths for cinterop Xcode 16 compatibility

The previous commit removed dependency module paths from cinterop
compiler options. This broke Xcode 16 builds because -fmodules needs
the dependency -I paths to resolve @Class forward declarations from
the dependency module. With the dependency headers now also included
in the modulemap, both Xcode versions work: Xcode 16 resolves types
via -fmodules, Xcode 26 resolves them via the included header.

Made-with: Cursor

* Update all CI iOS jobs to Xcode 26.4.1

Rename the xcode16 executor to xcode26 and update all iOS CI jobs
to use Xcode 26.4.1 instead of 16.4.0.

Made-with: Cursor

* Add cross-project Swift dependency tests

Covers the multi-target Package.swift / cross-project cinterop wiring
introduced for Xcode 26 compatibility: per-target scratch directories,
dependency header copying, and modulemap inclusion of dependency headers.
Also corrects the `dependencyHeaders` docstring on `SwiftBuildTask` to
describe the actual modulemap-based mechanism.

Made-with: Cursor

* Restore removed comments in ConfigureSwiftDependencies

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

* Remove PR-specific wording from test comment

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

* Auto-derive evaluationDependsOn from target dependency graph

The MultiTargetPackageBuilder already knows which targets depend on
which, and the test context knows which subproject registered each
target. Derive evaluationDependsOn calls automatically instead of
requiring tests to pass dependsOnSubprojects explicitly. This closes
a footgun where alphabetically-sorted subproject names could mask
a missing dependency declaration.

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

* Remove accidental build artifacts and add bin/ to gitignore

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

* Return both handles from setUpCrossProjectScenario

Avoids a hardcoded path for the dep's scratch directory assertion;
both dep and consumer now use getScratchDir(projectDir) so the test
stays correct if the production layout changes.

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

* Assert scratch dirs are per-subproject, not just non-shared

The previous assertion checked that a root-level shared scratch dir
didn't exist, but that path would never exist anyway since the root
project has no Swift packages. Instead, assert that each scratch dir
lives under its own subproject's build directory and that they differ.

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

* Fail loudly when a wired dependency header is missing

Replace the silent `if (depHeader.exists())` guard with a `check`
assertion so a missing dependency header surfaces immediately instead
of deferring to a confusing cinterop "unresolved type" error.

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

* Remove redundant cross-project dependsOn on cinterop task

The cinterop task already depends on swiftBuildTask, which itself
depends on each cross-project compileSwift task. The explicit
dependsOn on the cinterop task was therefore redundant and duplicated
the wiring expressed on swiftBuildTask.

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

* Reuse taskSuffix instead of recomputing it in moduleDependencies loop

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

* Document direct-only dependency header wiring limitation

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

* Skip empty root build file write for subproject-only test setups

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

* Small cleanups: guard duplicate dep headers, use Set for eval deps, extract moduleDir helper

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

* Assorted nits: guard duplicate targets, drop spurious @optional, centralize task name, fix formatting

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

* Add negative test for duplicate target registration, mark targets internal

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

* Use check instead of require for duplicate header guard

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

---------

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

* Migrates PostHog attribution from PHC to kn-core (#840)

Migrates PostHog attribution from PHC to kn-core

* Sets version to 3.0.0-SNAPSHOT (#839)

---------

Co-authored-by: Antonio Pallares <ajpallares@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants