Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
8f12a10
feat: resolve the Android store at build time
hyochan Sep 21, 2026
16cc73d
fix: give the Expo local build one working store resolution
hyochan Sep 21, 2026
b8f338a
fix: make the store rule fail closed, and pin it with a regression suite
hyochan Sep 21, 2026
ebafb9b
fix: close the gaps the second review found
hyochan Sep 21, 2026
0719d23
fix: resolve the store from abbreviated Gradle task names
hyochan Sep 21, 2026
fc05a2b
fix: close the holes the abbreviation support opened
hyochan Sep 21, 2026
6239534
fix: judge the legacy opt-out exactly as Gradle judges it
hyochan Sep 21, 2026
212f857
fix: report an opt-out that auto masks on a wrapper that cannot build it
hyochan Sep 21, 2026
02cd358
docs: name only the wrappers that apply the resolver
hyochan Sep 21, 2026
2a17ecf
fix: check the resolved store against the finished task graph
hyochan Sep 21, 2026
cd1afc0
fix: finish the final review's remaining items
hyochan Sep 22, 2026
ec40ac2
docs: add a skill for delegating the full device matrix
hyochan Sep 22, 2026
c8c4583
fix: address the PR review findings
hyochan Sep 22, 2026
99006da
fix: check the store against the tasks the request selected
hyochan Sep 22, 2026
bf6a032
fix: read the store from every task the request names
hyochan Sep 22, 2026
9515a7d
fix: drop an option's value, not the tasks after it
hyochan Sep 22, 2026
ea66ed9
fix: treat an unknown task option as a flag, not a value
hyochan Sep 22, 2026
d875f04
fix: take the value-option list from Gradle, not from memory
hyochan Sep 22, 2026
40b9300
fix: check the value-option list against Gradle instead of trusting it
hyochan Sep 22, 2026
4053ae6
fix: make the drift check able to catch what it was added for
hyochan Sep 22, 2026
a18836a
fix: make the drift check enforce what its comments warn about
hyochan Sep 22, 2026
1642531
fix: let an app opt out while keeping a store flavor
hyochan Sep 22, 2026
549c651
docs: say which pins conflict with a task flavor
hyochan Sep 22, 2026
35a0b33
docs: an anchor task does not give each flavor its own store
hyochan Sep 22, 2026
797654a
docs: say what the opt-out does and does not conflict with
hyochan Sep 22, 2026
b6aa91a
fix: name the opt-out key a later caller was refused for
hyochan Sep 22, 2026
cf51f5b
fix: keep Horizon purchases the store returned from its cache
hyochan Sep 22, 2026
7379db4
fix: stop a Horizon build blaming the Play Store
hyochan Sep 22, 2026
b00599b
fix: let the MAUI example launch on iOS 27
hyochan Sep 22, 2026
a68f88f
docs: say Mac Catalyst 27 shares the scene requirement
hyochan Sep 22, 2026
f3c105d
fix: stop the example apps losing or double-processing purchases
hyochan Sep 23, 2026
9ca993d
feat: let a Godot debug export follow the connected device
hyochan Sep 23, 2026
d72258b
fix: keep the device store probe on under the configuration cache
hyochan Sep 23, 2026
72aac99
feat: pick the Android store for native and KMP apps with a Gradle pl…
hyochan Sep 23, 2026
f21b597
docs: leave the store selection release note until after the release
hyochan Sep 23, 2026
1f78611
feat: deprecate the Expo store switches now that builds follow the de…
hyochan Sep 23, 2026
87fa841
feat: let a MAUI debug build follow the connected device
hyochan Sep 23, 2026
0ad54d1
fix: stop the Flutter library logging Android purchase tokens
hyochan Sep 23, 2026
391f7bb
docs: say Godot ships Quest support and that its export restarts adb
hyochan Sep 23, 2026
c17dad4
feat: let a Godot export carry the Horizon app id
hyochan Sep 23, 2026
03450cb
style: undo the unrelated reformatting in the parity audit
hyochan Sep 23, 2026
68112fa
fix: let the opt-out build several store flavors, and stop a guessed …
hyochan Sep 23, 2026
00666af
fix: stop the Gradle plugin replacing an app's platform, and select o…
hyochan Sep 23, 2026
b98ae5e
fix: fail the Expo prebuild on two store modules
hyochan Sep 23, 2026
ac501ef
fix: keep Horizon errors store-neutral and report an empty purchase c…
hyochan Sep 23, 2026
5f61598
fix: make openiap doctor judge store pins the way Gradle does
hyochan Sep 23, 2026
b3986d6
fix: remove a copied Amazon key once its source is gone
hyochan Sep 23, 2026
70e2e27
fix: let an Expo prebuild leave local OpenIAP development cleanly
hyochan Sep 23, 2026
d3c2fd1
fix: link each flavor's store from one dependency, and check flavor r…
hyochan Sep 23, 2026
1680585
fix: make Godot's get_store() report a Horizon or Amazon build
hyochan Sep 23, 2026
8754eb6
fix: move MAUI to AndroidX Fragment 1.9 so current Play Services builds
hyochan Sep 23, 2026
e448f75
fix: stop a MAUI pack without its facade AAR, and run on ANDROID_SERIAL
hyochan Sep 23, 2026
bc2e2af
fix: publish the Gradle plugin again unless its marker is out too
hyochan Sep 23, 2026
74b5f85
docs: fill the store setup gaps reviews found
hyochan Sep 23, 2026
4b4988c
refactor: drop store logic the task graph and app build already cover
hyochan Sep 23, 2026
55b9a66
fix: keep the next line's indent when a prebuild removes local wiring
hyochan Sep 23, 2026
b861331
refactor: stop the local Expo plugin redoing what withIapAndroid does
hyochan Sep 23, 2026
f812949
fix: write Kotlin DSL into .gradle.kts files in local Expo builds
hyochan Sep 23, 2026
26a1f57
refactor: read the plugin publish check as one plugin/marker status
hyochan Sep 23, 2026
0c30922
refactor: work out each legacy pin once in the resolver and the doctor
hyochan Sep 23, 2026
c0bcbdc
docs: clean up a change's code smells once it works, and ban as any
hyochan Sep 23, 2026
df50217
test: guard the Groovy removal, and qualify the unlisted-option comment
hyochan Sep 23, 2026
059c09f
docs: fix a code smell met while working even outside the change
hyochan Sep 23, 2026
efd4394
docs: say how to write a comment a person can read
hyochan Sep 23, 2026
8f49703
style: shorten this PR's comments to what a reader needs
hyochan Sep 23, 2026
3ff7cad
refactor: remove as any from IAPKit and the MCP server
hyochan Sep 23, 2026
fc52efb
refactor: remove as any from react-native-iap
hyochan Sep 23, 2026
6dbbad3
refactor: remove as any from expo-iap
hyochan Sep 23, 2026
429d4c4
style: trim restating comments in openiap-google and the Flutter plugin
hyochan Sep 23, 2026
cec4568
style: shorten IAPKit comments to what a reader needs
hyochan Sep 23, 2026
c40688f
ci: retry a Gradle build whose NDK download came back corrupt
hyochan Sep 23, 2026
bf87e31
ci: declare the self-hosted Mac runner label for actionlint
hyochan Sep 23, 2026
726c588
docs: bring the Foundation pages in line with what has shipped
hyochan Sep 23, 2026
39f89e6
style: finish shortening IAPKit's Convex comments
hyochan Sep 23, 2026
2d79c76
docs: list the GitHub Sponsors tiers and describe governance as pract…
hyochan Sep 23, 2026
8a5ac04
docs: check OpenCollective saves against the form value and the publi…
hyochan Sep 23, 2026
c2c3ef5
docs: fix Commerce Protocol docs that drifted from the spec
hyochan Sep 23, 2026
0c08446
fix: run ESLint in the docs lint and clear what it found
hyochan Sep 23, 2026
bc74ea0
docs: describe hosted IAPKit as a sponsored shared pool with no fees
hyochan Sep 23, 2026
9243acf
style: shorten react-native-iap comments and fix the ones that were w…
hyochan Sep 23, 2026
4a9789b
style: shorten expo-iap comments and fix the ones that were wrong
hyochan Sep 23, 2026
c21d4b2
style: use T[] in kit-api and trim its comments
hyochan Sep 23, 2026
b64bd39
feat: settle the Commerce Protocol cases the spec, runner and IAPKit …
hyochan Sep 24, 2026
cc0948d
docs: state the iOS versions external purchase actually needs
hyochan Sep 24, 2026
991d5dc
refactor(android): move Maven group to io.github.hyodotdev.openiap
hyochan Sep 24, 2026
3a25302
fix(android): resolve consumer coordinates from the published group
hyochan Sep 24, 2026
06ef839
revert: restore Maven group io.github.hyochan.openiap
hyochan Sep 24, 2026
aaed38b
refactor(android): keep one store resolver at the repository root
claude Sep 24, 2026
84f2235
fix(flutter): copy the linked store resolver into the consumer smoke …
claude Sep 24, 2026
e89e5a8
ci: list root resolver commits in release notes
claude Sep 24, 2026
d421cdd
fix: address review-round findings across expo, kit, docs, cli, and c…
hyochan Sep 24, 2026
9f41705
ci: use -PopeniapStore in CodeQL MAUI wrapper build
hyochan Sep 24, 2026
d23b2f2
fix: resolve review findings in godot plugin, rn ios gate, cli doctor…
hyochan Sep 24, 2026
521be1c
refactor(android): move store resolver back under packages/google
hyochan Sep 24, 2026
a8cb8cd
test: run apple example against local iapkit and pin no-mirror iphone…
hyochan Sep 24, 2026
0b3d444
test(skills): split e2e matrix into android and apple halves
hyochan Sep 25, 2026
b4a211d
docs(skills): drive Quest display-0 panel via tap+dump in e2e matrix
hyochan Sep 25, 2026
ca314a6
test(skills): rename e2e android half to google
hyochan Sep 25, 2026
1e9fb2c
chore: ignore local e2e reports directory
hyochan Sep 25, 2026
1e75d76
fix(flutter): forward Horizon IAPKit payload on Android
hyochan Sep 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
53 changes: 53 additions & 0 deletions .claude/commands/e2e-tests-apple.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
name: e2e-tests-apple
description: Run Apple-side device-backed OpenIAP regression on iOS using packages/apple and framework examples. Use when the user asks for iOS e2e tests or the Apple half of a parallel e2e run.
---

# E2E Tests Apple — iOS

Run this for the Apple half of OpenIAP device regression, alone or in
parallel with `/e2e-tests-google`. For the full matrix in one run, use
`/e2e-tests` instead. For a delegated hardware run, use
`$e2e-matrix-runner-apple`.

`e2e-tests.md` is the authority on what a row means and how to verify one.
Read it first and follow the sections named below; this file only narrows the
scope.

## Scope

- `packages/apple` native: `swift build` and `swift test`, plus the
xcframework build when iOS native packaging or bindings changed
(`## Package-Level Checks`, Apple package).
- iOS rows: all six frameworks (`react-native-iap`, `expo-iap`,
`flutter_inapp_purchase`, `kmp-iap`, `maui-iap`, `godot-iap`).
- Expo Onside: iOS build-only (`EXPO_IAP_ONSIDE=1` path under
`## Expo Checks`).
- Local (IAPKit) receipt vertical on iOS
(`## Local (IAPKit) Receipt Vertical`).

That is the 7 iOS cells plus the Expo Onside build-only cell of the full
matrix. Report every unavailable row as `BLOCKED` with its exact missing
prerequisite.

For each row, run the matching iOS sections under `## Expo Checks`,
`## React Native Checks`, `## Flutter Checks`, `## KMP Checks`,
`## MAUI Checks`, and `## Godot Checks`, then the iPhone bullet under
`## Manual Store Flows`.

## Preflight

Run the `## Preflight` block from `e2e-tests.md`, skipping only the
Android-only probes (`adb`, `vega`/`kepler`).

## Parallel-run rules

- Start the local IAPKit server once and share it with the Android half:
the iPhone verifies over the Mac's LAN address, Android over
`adb reverse tcp:3100`.
- Run only one Metro packager at a time across both halves (the RN/Expo
debug rows share port 8081); the devices otherwise proceed in parallel.

## Final Report

Use the `## Final Report` matrix in `e2e-tests.md`, iOS rows only.
56 changes: 56 additions & 0 deletions .claude/commands/e2e-tests-google.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
name: e2e-tests-google
description: Run Android-side device-backed OpenIAP regression across Google Play, Amazon Appstore, Meta Horizon, and VegaOS using packages/google and framework examples. Use when the user asks for Android e2e tests or the Android half of a parallel e2e run.
---

# E2E Tests Google — Play / Amazon / Horizon / VegaOS

Run this for the Android half of OpenIAP device regression, alone or in
parallel with `/e2e-tests-apple`. For the full matrix in one run, use
`/e2e-tests` instead. For a delegated hardware run, use
`$e2e-matrix-runner-google`.

`e2e-tests.md` is the authority on what a row means and how to verify one.
Read it first and follow the sections named below; this file only narrows the
scope.

## Scope

- `packages/google` native: Play, Amazon, and Horizon compile plus tests
(`## Package-Level Checks`, Google Android package).
- Play rows: all six frameworks (`react-native-iap`, `expo-iap`,
`flutter_inapp_purchase`, `kmp-iap`, `maui-iap`, `godot-iap`).
- FireOS/Amazon rows: all six except `godot-iap`, which has no Amazon flavor.
- Horizon rows: all six except `godot-iap`, which has no Horizon flavor.
Horizon is build-only unless the request authorizes a visibly test/sandbox
checkout.
- VegaOS rows: `react-native-iap` and `expo-iap` only.
- Local (IAPKit) receipt vertical on Android
(`## Local (IAPKit) Receipt Vertical`).

That is the 21 Android/Horizon cells plus the 2 VegaOS cells of the full
matrix. Report the two Godot gaps as `UNSUPPORTED` with the reason, never
omitted; every other unavailable row is `BLOCKED` with its exact missing
prerequisite.

For each row, run the matching Android sections under `## Expo Checks`,
`## React Native Checks`, `## Flutter Checks`, `## KMP Checks`,
`## MAUI Checks`, and `## Godot Checks`, then the Android platform bullets
under `## Manual Store Flows` (Play, FireOS, VegaOS, Horizon).

## Preflight

Run the `## Preflight` block from `e2e-tests.md`, skipping only the iOS-only
probes (`xcrun`, `xcodebuild`).

## Parallel-run rules

- Start the local IAPKit server once and share it with the Apple half:
Android verifies over `adb reverse tcp:3100`, the iPhone over the Mac's LAN
address.
- Run only one Metro packager at a time across both halves (the RN/Expo
debug rows share port 8081); the devices otherwise proceed in parallel.

## Final Report

Use the `## Final Report` matrix in `e2e-tests.md`, Android rows only.
123 changes: 32 additions & 91 deletions .claude/commands/e2e-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ description: Run device-backed OpenIAP regression across native packages and fra
Run this when a PR or release candidate needs real-device regression across
OpenIAP native packages and framework examples.

For a parallel run, split the matrix instead: `/e2e-tests-google` takes
Play, Amazon, Horizon, and VegaOS; `/e2e-tests-apple` takes iOS. Both read
this file as the row authority.

## Scope

Use the narrowest scope that satisfies the request, but broaden when native
Expand Down Expand Up @@ -482,14 +486,16 @@ FireOS/Amazon Android path:

```bash
cd libraries/expo-iap/example
EXPO_IAP_FIREOS=1 bunx expo prebuild --platform android --clean
bunx expo prebuild --platform android --clean
cd android
variant_report="$(./gradlew :app:dependencyInsight \
# The build follows the connected device; the inline pin keeps a build-only run
# exact without leaking into the next row.
variant_report="$(ORG_GRADLE_PROJECT_openiapStore=amazon ./gradlew :app:dependencyInsight \
--configuration debugRuntimeClasspath --dependency openiap-google)"
printf '%s\n' "$variant_report" | grep -F 'Variant amazonDebugRuntimeElements'
printf '%s\n' "$variant_report" | \
grep -E 'ProductFlavor:platform[[:space:]]+\| amazon'
./gradlew :app:assembleDebug
ORG_GRADLE_PROJECT_openiapStore=amazon ./gradlew :app:assembleDebug
# Build-only regression can stop here.
: "${FIREOS_SERIAL:?Set FIREOS_SERIAL to the target FireOS device serial}"
adb -s "$FIREOS_SERIAL" install -r app/build/outputs/apk/debug/app-debug.apk
Expand All @@ -500,14 +506,16 @@ Horizon Android build and optional device path:

```bash
cd libraries/expo-iap/example
EXPO_IAP_HORIZON=1 bunx expo prebuild --platform android --clean
bunx expo prebuild --platform android --clean
cd android
variant_report="$(./gradlew :app:dependencyInsight \
# The build follows the connected device; the inline pin keeps a build-only run
# exact without leaking into the next row.
variant_report="$(ORG_GRADLE_PROJECT_openiapStore=horizon ./gradlew :app:dependencyInsight \
--configuration debugRuntimeClasspath --dependency openiap-google)"
printf '%s\n' "$variant_report" | grep -F 'Variant horizonDebugRuntimeElements'
printf '%s\n' "$variant_report" | \
grep -E 'ProductFlavor:platform[[:space:]]+\| horizon'
./gradlew :app:assembleDebug
ORG_GRADLE_PROJECT_openiapStore=horizon ./gradlew :app:assembleDebug
# Build-only regression can stop here.
: "${HORIZON_SERIAL:?Set HORIZON_SERIAL to the target Horizon device serial}"
adb -s "$HORIZON_SERIAL" install -r app/build/outputs/apk/debug/app-debug.apk
Expand Down Expand Up @@ -579,7 +587,7 @@ FireOS/Amazon Android build and launch smoke:

```bash
cd libraries/react-native-iap/example/android
./gradlew :app:assembleDebug -PfireOsEnabled=true
./gradlew :app:assembleDebug -PopeniapStore=amazon
# Build-only regression can stop here.
: "${FIREOS_SERIAL:?Set FIREOS_SERIAL to the target FireOS device serial}"
adb -s "$FIREOS_SERIAL" install -r app/build/outputs/apk/debug/app-debug.apk
Expand All @@ -590,7 +598,7 @@ Horizon Android build-only path:

```bash
cd libraries/react-native-iap/example/android
./gradlew :app:assembleDebug -PhorizonEnabled=true
./gradlew :app:assembleDebug -PopeniapStore=horizon
```

Normal iOS physical-device build and launch smoke:
Expand Down Expand Up @@ -666,7 +674,7 @@ FireOS/Amazon Android build and launch smoke:

```bash
cd libraries/flutter_inapp_purchase/example/android
./gradlew :app:assembleDebug -PfireOsEnabled=true
./gradlew :app:assembleDebug -PopeniapStore=amazon
# Build-only regression can stop here.
# Flutter redirects its gradle output to `example/build/app/outputs/flutter-apk/`,
# so this path is not the `android/app/build/...` layout the other examples use.
Expand All @@ -679,7 +687,7 @@ Horizon Android build-only path:

```bash
cd libraries/flutter_inapp_purchase/example/android
./gradlew :app:assembleDebug -PhorizonEnabled=true
./gradlew :app:assembleDebug -PopeniapStore=horizon
```

iOS physical-device build and launch smoke:
Expand Down Expand Up @@ -770,101 +778,29 @@ dotnet build src/OpenIap.Maui/OpenIap.Maui.csproj -p:TargetFrameworks=net10.0 --
dotnet build src/OpenIap.Maui/OpenIap.Maui.csproj -p:TargetFrameworks=net10.0-ios --nologo
```

Normal Android / Play build and launch smoke:
Android build and launch smoke. The library is the same for every store; the
example build links one, from `OpenIapStore` or, on a Debug build, the device
`ANDROID_SERIAL` names. Its `openiap: store=... (source=...)` line says which.

```bash
# The MAUI-owned Android facade AAR output path is shared, so build it for the
# requested store immediately before the matching dotnet build. The library
# build disables ProjectReference rebuilds because the Android binding is built
# explicitly first.
cd libraries/maui-iap/android
../../../packages/google/gradlew :openiap:assembleRelease -PopenIapAndroidStore=play
../../../packages/google/gradlew :openiap:assembleRelease
cd ..
dotnet build-server shutdown || true
rm -rf \
src/OpenIap.Maui.Bindings.Android/bin src/OpenIap.Maui.Bindings.Android/obj \
src/OpenIap.Maui/bin src/OpenIap.Maui/obj \
example/OpenIap.Maui.Example/bin example/OpenIap.Maui.Example/obj
dotnet build src/OpenIap.Maui.Bindings.Android/OpenIap.Maui.Bindings.Android.csproj \
-p:TargetFrameworks=net10.0-android \
-p:OpenIapAndroidStore=play \
--nologo
dotnet build src/OpenIap.Maui/OpenIap.Maui.csproj \
-p:TargetFrameworks=net10.0-android \
-p:OpenIapAndroidStore=play \
-p:BuildProjectReferences=false \
--nologo
: "${ANDROID_SERIAL:?Set ANDROID_SERIAL to the Play, FireOS, or Horizon device}"
dotnet build example/OpenIap.Maui.Example/OpenIap.Maui.Example.csproj \
-f net10.0-android \
-p:OpenIapAndroidStore=play \
-p:TargetFrameworks=net10.0-android \
-p:EmbedAssembliesIntoApk=true \
--nologo
# Build-only regression can stop here.
: "${ANDROID_SERIAL:?Set ANDROID_SERIAL to the target Android device serial}"
adb -s "$ANDROID_SERIAL" uninstall dev.hyo.martie || true
adb -s "$ANDROID_SERIAL" install --no-incremental -r \
example/OpenIap.Maui.Example/bin/Debug/net10.0-android/dev.hyo.martie-Signed.apk
adb -s "$ANDROID_SERIAL" shell monkey -p dev.hyo.martie 1
```

FireOS/Amazon Android build and launch smoke:

```bash
cd libraries/maui-iap/android
../../../packages/google/gradlew :openiap:assembleRelease -PopenIapAndroidStore=amazon
cd ..
dotnet build-server shutdown || true
rm -rf \
src/OpenIap.Maui.Bindings.Android/bin src/OpenIap.Maui.Bindings.Android/obj \
src/OpenIap.Maui/bin src/OpenIap.Maui/obj \
example/OpenIap.Maui.Example/bin example/OpenIap.Maui.Example/obj
dotnet build src/OpenIap.Maui.Bindings.Android/OpenIap.Maui.Bindings.Android.csproj \
-p:TargetFrameworks=net10.0-android \
-p:OpenIapAndroidStore=amazon \
--nologo
dotnet build src/OpenIap.Maui/OpenIap.Maui.csproj \
-p:TargetFrameworks=net10.0-android \
-p:OpenIapAndroidStore=amazon \
-p:BuildProjectReferences=false \
--nologo
dotnet build example/OpenIap.Maui.Example/OpenIap.Maui.Example.csproj \
-f net10.0-android \
-p:OpenIapAndroidStore=amazon \
-p:EmbedAssembliesIntoApk=true \
--nologo
# Build-only regression can stop here.
: "${FIREOS_SERIAL:?Set FIREOS_SERIAL to the target FireOS device serial}"
adb -s "$FIREOS_SERIAL" uninstall dev.hyo.martie || true
adb -s "$FIREOS_SERIAL" install --no-incremental -r \
example/OpenIap.Maui.Example/bin/stores/amazon/Debug/net10.0-android/dev.hyo.martie-Signed.apk
adb -s "$FIREOS_SERIAL" shell monkey -p dev.hyo.martie 1
```

Horizon Android build-only path:

```bash
cd libraries/maui-iap/android
../../../packages/google/gradlew :openiap:assembleRelease -PopenIapAndroidStore=horizon
cd ..
dotnet build-server shutdown || true
rm -rf \
src/OpenIap.Maui.Bindings.Android/bin src/OpenIap.Maui.Bindings.Android/obj \
src/OpenIap.Maui/bin src/OpenIap.Maui/obj \
example/OpenIap.Maui.Example/bin example/OpenIap.Maui.Example/obj
dotnet build src/OpenIap.Maui.Bindings.Android/OpenIap.Maui.Bindings.Android.csproj \
-p:TargetFrameworks=net10.0-android \
-p:OpenIapAndroidStore=horizon \
--nologo
dotnet build src/OpenIap.Maui/OpenIap.Maui.csproj \
-p:TargetFrameworks=net10.0-android \
-p:OpenIapAndroidStore=horizon \
-p:BuildProjectReferences=false \
--nologo
dotnet build example/OpenIap.Maui.Example/OpenIap.Maui.Example.csproj \
-f net10.0-android \
-p:OpenIapAndroidStore=horizon \
--nologo
```
Run it once per store device. Without a device, pin the store instead:
`-p:OpenIapStore=horizon`. `bash scripts/verify-store-selection.sh` covers the
selection rule itself without hardware.

iOS physical-device build and launch smoke:

Expand Down Expand Up @@ -901,6 +837,11 @@ adb -s "$ANDROID_SERIAL" install -r Example/android/Martie.apk
adb -s "$ANDROID_SERIAL" shell monkey -p dev.hyo.martie 1
```

A headless Godot export runs `adb kill-server` on exit (editor setting
`export/android/shutdown_adb_on_exit`, on by default). That drops every
`adb reverse` rule and scrcpy session on every device, so re-create the
`tcp:3100` rule before verifying, and export before the other Android rows.

iOS build and launch smoke:

```bash
Expand Down
31 changes: 12 additions & 19 deletions .claude/commands/verify-all.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,25 +151,18 @@ bun run audit:commerce-evidence || echo "commerce evidence differs from current
(
cd libraries/maui-iap
DOTNET_BUILD_ARGS=(/m:1 /nr:false -p:UseSharedCompilation=false --nologo)
for store in play amazon horizon; do
dotnet build-server shutdown || true
rm -rf \
src/OpenIap.Maui.Bindings.Android/bin \
src/OpenIap.Maui.Bindings.Android/obj
(cd android && ../../../packages/google/gradlew \
:openiap:assembleRelease -PopenIapAndroidStore="$store")
dotnet build \
src/OpenIap.Maui.Bindings.Android/OpenIap.Maui.Bindings.Android.csproj \
-p:TargetFrameworks=net10.0-android \
-p:OpenIapAndroidStore="$store" \
"${DOTNET_BUILD_ARGS[@]}"
dotnet build \
src/OpenIap.Maui/OpenIap.Maui.csproj \
-p:TargetFrameworks=net10.0-android \
-p:OpenIapAndroidStore="$store" \
-p:BuildProjectReferences=false \
"${DOTNET_BUILD_ARGS[@]}"
done
(cd android && ../../../packages/google/gradlew :openiap:assembleRelease)
dotnet build \
src/OpenIap.Maui.Bindings.Android/OpenIap.Maui.Bindings.Android.csproj \
-p:TargetFrameworks=net10.0-android \
"${DOTNET_BUILD_ARGS[@]}"
dotnet build \
src/OpenIap.Maui/OpenIap.Maui.csproj \
-p:TargetFrameworks=net10.0-android \
-p:BuildProjectReferences=false \
"${DOTNET_BUILD_ARGS[@]}"
# The app build picks the store; this checks every rule against a fake adb.
bash scripts/verify-store-selection.sh
)

# MAUI iOS/macCatalyst binding and platform library (requires xcodegen + MAUI workload)
Expand Down
20 changes: 20 additions & 0 deletions .claude/skills/e2e-matrix-runner-apple/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: e2e-matrix-runner-apple
description: Run the Apple half of the OpenIAP device matrix — six frameworks plus the native package on iOS — on a physical iPhone and report one row per cell with evidence. Use when asked for iOS e2e or delegated hardware testing.
---

# E2E Matrix Runner Apple (Claude Code)

The canonical procedure lives in
`.codex/skills/e2e-matrix-runner-apple/SKILL.md`. Read that file first and
follow it fully — the narrowed matrix, the parallel-run rules, and its
references to the full skill's driving techniques and reporting contract are
all defined there.

## Claude Code notes

- `.claude/commands/e2e-tests-apple.md` scopes this run;
`.claude/commands/e2e-tests.md` is the authority on what an individual row
means.
- Prefer the repo's own scripts over ad-hoc commands, and run long builds in the
background so the session stays responsive.
Loading
Loading