Skip to content

Commit a1f5149

Browse files
committed
ci: add Capacitor 8 + Xcode 26 to iOS build matrix
Capacitor 8 requires Xcode 26 for SPM — the xcframework uses $NonescapableTypes which gates extension methods behind a compiler feature flag. With the correct Xcode, all APIs (reject, getString, etc.) work natively. Matrix: - Cap 6: macOS-14, Xcode 15.4, CocoaPods - Cap 7: macOS-14, Xcode 15.4, CocoaPods - Cap 8: macOS-15, Xcode 26.0, SPM Also revert SPM workarounds — use idiomatic Capacitor APIs everywhere.
1 parent 8abc9cf commit a1f5149

2 files changed

Lines changed: 25 additions & 24 deletions

File tree

.github/workflows/build-capacitor-ios.yml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,20 @@ on:
88

99
jobs:
1010
build:
11-
runs-on: macos-14
11+
runs-on: ${{ matrix.runner }}
1212
strategy:
1313
fail-fast: false
1414
matrix:
1515
include:
1616
- capacitor-version: '6'
1717
xcode-version: '15.4'
18+
runner: macos-14
1819
- capacitor-version: '7'
1920
xcode-version: '15.4'
21+
runner: macos-14
22+
- capacitor-version: '8'
23+
xcode-version: '26.0'
24+
runner: macos-15
2025
steps:
2126
- uses: actions/checkout@v4
2227

@@ -40,7 +45,6 @@ jobs:
4045
mkdir test-cap-app && cd test-cap-app
4146
npm init -y
4247
npm install @capacitor/core@${{ matrix.capacitor-version }} @capacitor/ios@${{ matrix.capacitor-version }} @capacitor/cli@${{ matrix.capacitor-version }}
43-
# Minimal capacitor config
4448
echo '{"appId":"com.test.app","appName":"TestApp","webDir":"dist"}' > capacitor.config.json
4549
mkdir -p dist
4650
echo '<html><body></body></html>' > dist/index.html
@@ -55,9 +59,10 @@ jobs:
5559
- name: Install plugin
5660
run: |
5761
cd test-cap-app
58-
# Plugin requires iOS 15.0 (StoreKit 2) — bump Podfile target
59-
sed -i '' "s/platform :ios, '13.0'/platform :ios, '15.0'/" ios/App/Podfile || true
60-
sed -i '' "s/platform :ios, '14.0'/platform :ios, '15.0'/" ios/App/Podfile || true
62+
# Plugin requires iOS 15.0 (StoreKit 2) — bump Podfile target if CocoaPods
63+
if [ -f ios/App/Podfile ]; then
64+
sed -i '' "s/platform :ios, '1[34].0'/platform :ios, '15.0'/" ios/App/Podfile
65+
fi
6166
cp "$GITHUB_WORKSPACE/www/store.js" "$GITHUB_WORKSPACE/capacitor/www/store.js"
6267
cp "$GITHUB_WORKSPACE/www/store.d.ts" "$GITHUB_WORKSPACE/capacitor/www/store.d.ts"
6368
npm install "$GITHUB_WORKSPACE/capacitor"

capacitor/ios/Sources/PurchasePlugin/PurchasePlugin.swift

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
7777
}
7878

7979
@objc func load(_ call: CAPPluginCall) {
80-
guard let productIds = call.options["productIds"] as? [String] else {
81-
rejectCall(call, "productIds is required")
80+
guard let productIds = call.getArray("productIds") as? [String] else {
81+
call.reject("productIds is required")
8282
return
8383
}
8484
debugLog("load: \(productIds)")
@@ -102,27 +102,27 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
102102
"invalidProductIds": invalidIds
103103
])
104104
} catch {
105-
rejectCall(call, "Failed to load products: \(error.localizedDescription)")
105+
call.reject("Failed to load products: \(error.localizedDescription)")
106106
}
107107
}
108108
}
109109

110110
@objc func purchase(_ call: CAPPluginCall) {
111-
guard let productId = call.options["productId"] as? String else {
112-
rejectCall(call, "productId is required")
111+
guard let productId = call.getString("productId") else {
112+
call.reject("productId is required")
113113
return
114114
}
115115
debugLog("purchase: \(productId)")
116116

117117
guard let product = products[productId] else {
118-
rejectCall(call, "Product not loaded: \(productId)")
118+
call.reject("Product not loaded: \(productId)")
119119
return
120120
}
121121

122122
Task {
123123
do {
124124
var options: Set<Product.PurchaseOption> = []
125-
if let username = call.options["applicationUsername"] as? String {
125+
if let username = call.getString("applicationUsername") {
126126
options.insert(.appAccountToken(
127127
UUID(uuidString: username) ?? UUID()))
128128
}
@@ -160,17 +160,17 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
160160
])
161161
call.resolve()
162162
@unknown default:
163-
rejectCall(call, "Unknown purchase result")
163+
call.reject("Unknown purchase result")
164164
}
165165
} catch {
166-
rejectCall(call, "Purchase failed: \(error.localizedDescription)")
166+
call.reject("Purchase failed: \(error.localizedDescription)")
167167
}
168168
}
169169
}
170170

171171
@objc func finish(_ call: CAPPluginCall) {
172-
guard let transactionId = call.options["transactionId"] as? String else {
173-
rejectCall(call, "transactionId is required")
172+
guard let transactionId = call.getString("transactionId") else {
173+
call.reject("transactionId is required")
174174
return
175175
}
176176
debugLog("finish: \(transactionId)")
@@ -209,7 +209,7 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
209209
call.resolve()
210210
} catch {
211211
notifyListeners("restoreFailed", data: ["errorCode": 0])
212-
rejectCall(call, "Restore failed: \(error.localizedDescription)")
212+
call.reject("Restore failed: \(error.localizedDescription)")
213213
}
214214
}
215215
}
@@ -251,13 +251,13 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
251251
"appVersion": transaction.appVersion,
252252
]])
253253
case .unverified(_, _):
254-
rejectCall(call, "App transaction verification failed")
254+
call.reject("App transaction verification failed")
255255
}
256256
} catch {
257-
rejectCall(call, "Failed to refresh receipts: \(error.localizedDescription)")
257+
call.reject("Failed to refresh receipts: \(error.localizedDescription)")
258258
}
259259
} else {
260-
rejectCall(call, "refreshReceipts requires iOS 16.0 or newer")
260+
call.reject("refreshReceipts requires iOS 16.0 or newer")
261261
}
262262
}
263263
}
@@ -376,10 +376,6 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
376376
}
377377
}
378378

379-
private func rejectCall(_ call: CAPPluginCall, _ message: String) {
380-
call.reject(message)
381-
}
382-
383379
private func debugLog(_ msg: String) {
384380
if debugEnabled {
385381
print("PurchasePlugin[debug]: \(msg)")

0 commit comments

Comments
 (0)