Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
36a9352
feat(dart): add v6 cross-platform façade
kherembourg May 28, 2026
218e59e
feat(dart): export v6 facade from purchasely_flutter.dart
kherembourg May 28, 2026
d164581
feat(android): wire Flutter bridge to Purchasely Android v6
kherembourg May 28, 2026
7dbd052
feat(ios): wire Flutter bridge to Purchasely iOS v6 with contract wor…
kherembourg May 28, 2026
7afdce7
chore(example): update Flutter example to v6 contract
kherembourg May 28, 2026
04000d5
docs: add v6 migration guide and changelog
kherembourg May 28, 2026
2f93cd8
chore(dart): apply dart format to action_interceptor.dart
kherembourg May 28, 2026
48a08a7
feat(dart): wire MethodChannel/EventChannel dispatcher for v6 façade
kherembourg May 28, 2026
728702d
test(bridge): add v6 integration tests for outcome + interceptor + li…
kherembourg May 28, 2026
e65d4ce
fix: address Greptile review comments on v6 bridge
claude May 28, 2026
92e1e7d
fix(android): map inlinePaywall transition in PurchaselyV6Bridge
kherembourg May 29, 2026
d5d2f81
chore(dart): apply dart format to v6 demo screen and bridge test
kherembourg May 29, 2026
0d8e04f
chore(android): add mavenLocal() first for unpublished v6 native SDK …
kherembourg May 29, 2026
2fb95b8
feat(v6)!: presentation & interceptor are v6-only; remove legacy v5 s…
kherembourg May 29, 2026
9c59614
Revert "feat(v6)!: presentation & interceptor are v6-only; remove leg…
kherembourg Jun 1, 2026
bccb1e0
refactor: adapt the plugin to the Purchasely 6.0 native SDK (single p…
kherembourg Jun 1, 2026
886ceaf
docs: add 6.0 migration guide and public integration doc
kherembourg Jun 1, 2026
4153965
feat: add Purchasely.interceptAction convenience API
kherembourg Jun 1, 2026
a6be576
fix: align native start() with the Dart builder contract + polish
kherembourg Jun 1, 2026
c5f1904
fix(v6): align Flutter bridge with native 6.0
kherembourg Jun 1, 2026
286dd3c
feat: surface inline PLYPresentationView outcome via presentation events
kherembourg Jun 1, 2026
1184a99
fix(v6): pin Purchasely native SDKs to 6.0.0-rc1
kherembourg Jun 16, 2026
d536a77
feat(v6): resolve synchronize() via native callback + align bridges w…
kherembourg Jun 16, 2026
9e19e82
test(v6): add synchronize coverage and recreate iOS unit tests
kherembourg Jun 16, 2026
54ad8a3
chore(example): exercise v6 synchronize + iOS app config
kherembourg Jun 16, 2026
429a27d
docs(v6): update migration guide and add session report
kherembourg Jun 16, 2026
3b1772d
fix(v6): pin native SDKs to published 6.0.0-rc.1 and drop local resol…
kherembourg Jun 16, 2026
0a402ff
docs(v6): both platforms resolve 6.0.0-rc.1 from public repos
kherembourg Jun 16, 2026
af6d0ef
chore(v6): bump Flutter plugin version to 6.0.0-rc.1
kherembourg Jun 16, 2026
ca82588
feat(v6)!: remove presentSubscriptions from the Flutter SDK
kherembourg Jun 16, 2026
4e5a9f5
feat(v6)!: type presentation purchase payloads
kherembourg Jun 23, 2026
c575285
chore(android): pin Purchasely SDK beta.12
kherembourg Jun 23, 2026
1f58e35
feat(v6)!: align public API with native truth (outcome, closeReason, …
kherembourg Jun 24, 2026
8b4409d
test(v6): add Dart<->Android E2E integration test against real backend
kherembourg Jun 24, 2026
26a6069
fix(android): deliver onDismissed for builder display() path
kherembourg Jun 24, 2026
554a9e1
test(v6): E2E interceptor trigger + global dismiss handler on Android
kherembourg Jun 24, 2026
b94306d
docs(test): index E2E tests + RN/Cordova porting guide
kherembourg Jun 24, 2026
2f8b364
style(test): dart format E2E integration test files
kherembourg Jun 24, 2026
c2d5cb1
ci(e2e): add manual + nightly Android E2E workflow with emulator & dr…
kherembourg Jun 24, 2026
c53da67
ci(e2e): TEMP push trigger to verify the E2E workflow runs (revert next)
kherembourg Jun 24, 2026
5f038dd
build(android): bump native SDK pin 6.0.0-beta.12 → 6.0.0-rc.2
kherembourg Jun 24, 2026
82adc13
feat(v6): Transition.drawer/.popin ctors + Future<Presentation>.displ…
kherembourg Jun 24, 2026
37898fa
ci(e2e): resolve native SDK from Maven Central (drop mavenLocal priming)
kherembourg Jun 24, 2026
c107e6a
ci(android): pin example minSdk to 23 to match the native SDK
kherembourg Jun 24, 2026
38e5d52
refactor(dart)!: add PLY prefix to all public Dart types
kherembourg Jun 24, 2026
c59ac00
docs(migration): update guides for PLY rename + new PLYTransition ctors
kherembourg Jun 24, 2026
affce8b
ci(e2e): remove temp push trigger (verification done — manual + night…
kherembourg Jun 24, 2026
85094b3
style: dart format after PLY-prefix rename
kherembourg Jun 24, 2026
846aebd
refactor(dart): Purchasely.apiKey() as SDK init entry point
kherembourg Jun 24, 2026
9726d8b
refactor(dart): rename PLYPurchaselyBuilder → PurchaselyBuilder
kherembourg Jun 24, 2026
a90114f
docs(migration): fix PurchaselyBuilder → Purchasely.apiKey() in all e…
kherembourg Jun 24, 2026
ee8de8a
docs(migration): remove PurchaselyBuilder from rename table (new in v…
kherembourg Jun 24, 2026
1c0de67
docs(migration): replace internal v6 rename table with real v5→v6 typ…
kherembourg Jun 24, 2026
1a1924b
fix(ios/events): use NSString.fromPLYEvent for correct SCREAMING_SNAK…
kherembourg Jun 26, 2026
9162092
deps(android): bump gradle-wrapper to 8.14.5 and kotlin to 2.3.21
kherembourg Jun 26, 2026
195a20d
ci: bump actions/checkout from v6 to v7
kherembourg Jun 26, 2026
6a7204a
deps(android): bump mockk to 1.14.11 and kotlinx-coroutines-test to 1…
kherembourg Jun 26, 2026
bff3395
test(e2e): add T14–T20 integration tests for v6 new APIs
kherembourg Jun 26, 2026
a942a11
ci(e2e): add iOS E2E workflow symmetric with Android
kherembourg Jun 26, 2026
7120166
fix(ci): pin minSdkVersion to 23 + dart format
kherembourg Jun 26, 2026
5c57436
test(e2e/ios): add interceptor + dismiss handler tests with idb drivers
kherembourg Jun 26, 2026
df11e46
fix(e2e/ios): remove PLYStore.apple (n'existe pas), utiliser storekit…
kherembourg Jun 26, 2026
e2cae06
fix: update debug prints and assertions in test files for consistency
kherembourg Jun 26, 2026
c5150cd
fix(ios): call result() for setThemeMode/setDebugMode/setAttribute/us…
kherembourg Jun 26, 2026
01e3873
fix(e2e/ios): make idb drivers work against the custom-rendered paywall
kherembourg Jun 26, 2026
92e2e46
ci(e2e): run iOS+Android E2E on PRs to main; fix main.dart format for…
kherembourg Jun 26, 2026
ae54937
fix(ci/e2e-ios): install idb-companion from facebook/fb tap
kherembourg Jun 26, 2026
c0c7393
style(example): format main.dart with Dart 3.5 (CI toolchain) short s…
kherembourg Jun 26, 2026
9338c29
test(e2e/android): make uiautomator drivers robust + verbose for CI
kherembourg Jun 26, 2026
1827bbb
fix(ci): classic AppDelegate for Flutter 3.24 + diagnostics in androi…
kherembourg Jun 26, 2026
7a68222
ci(e2e): cache setup phases + diagnose iOS start() hang on CI
kherembourg Jun 26, 2026
30fd91d
ci(e2e-ios): bump Flutter to 3.41.4 (fix simulator launch crash) + cr…
kherembourg Jun 26, 2026
67d7a0f
test(e2e): retry the flaky driver-based suites (interceptor, dismiss)
kherembourg Jun 26, 2026
d6aee7d
ci(e2e): bridge = hard gate, interceptor/dismiss = best-effort (non-b…
kherembourg Jun 26, 2026
d14af4f
test(e2e/ios): harden idb drivers — repeat tap / swipe for reliability
kherembourg Jun 26, 2026
08603b4
feat(dismiss): route display() dismissal to default handler when no l…
kherembourg Jun 26, 2026
990ec0f
fix(flutter): inline paywall close via hybrid composition
kherembourg Jun 26, 2026
e6af2b6
chore(example/android): use flutter.minSdkVersion for the sample app
kherembourg Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Setup Flutter
uses: subosito/flutter-action@v2
Expand Down Expand Up @@ -79,7 +79,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Setup Flutter
uses: subosito/flutter-action@v2
Expand Down Expand Up @@ -126,7 +126,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Setup Java
uses: actions/setup-java@v5
Expand Down Expand Up @@ -180,7 +180,7 @@ jobs:
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Setup Flutter
uses: subosito/flutter-action@v2
Expand Down Expand Up @@ -235,7 +235,7 @@ jobs:
needs: [analyze]
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Setup Flutter
uses: subosito/flutter-action@v2
Expand Down Expand Up @@ -273,7 +273,7 @@ jobs:
needs: [analyze]
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Setup Java
uses: actions/setup-java@v5
Expand Down Expand Up @@ -323,7 +323,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Check version consistency
run: |
Expand Down Expand Up @@ -358,7 +358,7 @@ jobs:
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Validate podspec
working-directory: purchasely/ios
Expand Down
121 changes: 121 additions & 0 deletions .github/workflows/e2e-android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: E2E Android

# End-to-end Dart <-> Android tests against the REAL Purchasely backend, run on a
# real Android emulator. These are NOT part of the PR-gating `ci.yml` (they need an
# emulator, real network, and the uiautomator drivers) — they run on demand and
# nightly.
#
# Triggers:
# * pull_request — run on PRs targeting main while the v6 migration is in
# flight, so the E2E suite gates the merge. Scoped to
# paths that affect the bridge / native layer / tests.
# * workflow_dispatch — manual run (any branch the workflow exists on)
# * schedule — nightly at 03:00 UTC (GitHub only fires schedules from the
# repository's DEFAULT branch, so the nightly run activates
# once this file is merged to main).
on:
pull_request:
branches: [main]
paths:
- "purchasely/lib/**"
- "purchasely/android/**"
- "purchasely/example/integration_test/**"
- ".github/workflows/e2e-android.yml"
workflow_dispatch:
schedule:
- cron: "0 3 * * *"

concurrency:
group: e2e-android-${{ github.ref }}
cancel-in-progress: true

jobs:
e2e-android:
name: E2E Android (real backend)
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout repository
uses: actions/checkout@v7

- name: Enable KVM (hardware acceleration for the emulator)
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "17"
cache: gradle

- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.24.x"
channel: stable
cache: true

# The native Purchasely Android SDK (io.purchasely:core / google-play / player)
# 6.0.0-rc.2 is published to Maven Central, so Gradle resolves it directly —
# no mavenLocal priming needed.

- name: Cache pub packages
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: ${{ runner.os }}-pub-${{ hashFiles('purchasely/pubspec.lock', 'purchasely/example/pubspec.lock') }}
restore-keys: ${{ runner.os }}-pub-

- name: Install Flutter deps (purchasely)
working-directory: purchasely
run: flutter pub get

- name: Install Flutter deps (example)
working-directory: purchasely/example
run: flutter pub get

- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-34-google_apis-x86_64-pixel_6

- name: Create AVD + snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
target: google_apis
arch: x86_64
profile: pixel_6
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: echo "Generated AVD snapshot for caching."

- name: Run E2E suite on emulator
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
target: google_apis
arch: x86_64
profile: pixel_6
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: bash purchasely/example/integration_test/tools/ci_run_e2e.sh emulator-5554

- name: Upload E2E logs
if: always()
uses: actions/upload-artifact@v7
with:
name: e2e-android-logs
path: purchasely/example/integration_test/ci-logs/
retention-days: 7
130 changes: 130 additions & 0 deletions .github/workflows/e2e-ios.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
name: E2E iOS

# End-to-end Dart <-> iOS tests against the REAL Purchasely backend, run on an
# iOS Simulator. These are NOT part of the PR-gating `ci.yml` (they need a
# simulator and real network) — they run on demand and nightly.
#
# Suites:
# 1/3 — dart_ios_bridge_test.dart (T1–T20, no native interaction)
# 2/3 — interceptor_trigger_ios_test (purchase interceptor; driver taps
# ply_action_purchase_* via idb)
# 3/3 — default_dismiss_handler_ios (deeplink + default dismiss; driver
# taps ply_action_close via idb)
#
# Triggers:
# * pull_request — run on PRs targeting main while the v6 migration is in
# flight, so the E2E suite gates the merge. Scoped to
# paths that affect the bridge / native layer / tests.
# * workflow_dispatch — manual run (any branch the workflow exists on)
# * schedule — nightly at 04:00 UTC (GitHub only fires schedules from
# the repository's DEFAULT branch, so the nightly run
# activates once this file is merged to main).
on:
pull_request:
branches: [main]
paths:
- "purchasely/lib/**"
- "purchasely/ios/**"
- "purchasely/example/integration_test/**"
- ".github/workflows/e2e-ios.yml"
workflow_dispatch:
schedule:
- cron: "0 4 * * *"

concurrency:
group: e2e-ios-${{ github.ref }}
cancel-in-progress: true

jobs:
e2e-ios:
name: E2E iOS (real backend)
runs-on: macos-latest
timeout-minutes: 60
steps:
- name: Checkout repository
uses: actions/checkout@v7

- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
# Match the dev toolchain (3.41.x). Flutter 3.24.5 + the macos-latest
# Xcode/iOS runtime makes the example app crash on launch on the
# simulator (the integration-test harness then times out after 12 min
# with setUpAll never running). 3.41.x runs the full suite locally.
flutter-version: "3.41.4"
channel: stable
cache: true

- name: Cache pub packages
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: ${{ runner.os }}-pub-${{ hashFiles('purchasely/pubspec.lock', 'purchasely/example/pubspec.lock') }}
restore-keys: ${{ runner.os }}-pub-

- name: Install Flutter deps (purchasely)
working-directory: purchasely
run: flutter pub get

- name: Install Flutter deps (example)
working-directory: purchasely/example
run: flutter pub get

- name: Cache CocoaPods
uses: actions/cache@v4
with:
path: |
purchasely/example/ios/Pods
~/Library/Caches/CocoaPods
key: ${{ runner.os }}-pods-${{ hashFiles('purchasely/example/ios/Podfile.lock') }}
restore-keys: ${{ runner.os }}-pods-

- name: Install CocoaPods deps
working-directory: purchasely/example/ios
# No --repo-update: the CDN resolves specs without cloning the full repo.
run: pod install

- name: Install idb-companion + idb Python client
run: |
# idb-companion lives in the facebook/fb tap, not homebrew-core.
brew install facebook/fb/idb-companion
# macOS runners' Python may be externally-managed (PEP 668).
pip3 install fb-idb || pip3 install --break-system-packages fb-idb

- name: Boot iOS Simulator
id: boot-sim
run: |
# Find an available iPhone simulator (prefer iPhone 16, fall back to 15/14)
UDID=$(xcrun simctl list devices available | \
grep -E "iPhone (16|15|14)" | head -1 | \
grep -oE '[0-9A-F-]{36}')
if [ -z "$UDID" ]; then
echo "No iPhone simulator found" >&2
xcrun simctl list devices available >&2
exit 1
fi
echo "udid=$UDID" >> "$GITHUB_OUTPUT"
echo "Booting simulator $UDID"
xcrun simctl boot "$UDID" || true
xcrun simctl bootstatus "$UDID" -b

- name: Run E2E suite on iOS Simulator
run: bash purchasely/example/integration_test/tools/ci_run_e2e_ios.sh ${{ steps.boot-sim.outputs.udid }}

- name: Collect simulator crash logs (on failure)
if: failure()
run: |
mkdir -p purchasely/example/integration_test/ci-logs
cp -R ~/Library/Logs/DiagnosticReports \
purchasely/example/integration_test/ci-logs/DiagnosticReports 2>/dev/null || true
xcrun simctl spawn ${{ steps.boot-sim.outputs.udid }} log show --last 5m \
--predicate 'processImagePath CONTAINS "Runner" OR senderImagePath CONTAINS "Purchasely"' \
> purchasely/example/integration_test/ci-logs/sim_log.txt 2>&1 || true

- name: Upload E2E logs
if: always()
uses: actions/upload-artifact@v7
with:
name: e2e-ios-logs
path: purchasely/example/integration_test/ci-logs/
retention-days: 7
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Setup Flutter
uses: subosito/flutter-action@v2
Expand Down Expand Up @@ -143,7 +143,7 @@ jobs:
needs: [publish-google, publish-player]
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Summary
run: |
Expand Down
Loading
Loading