Skip to content

Commit 0a4ad00

Browse files
committed
Fix React Native Swift lint CI parity
1 parent 31ddca1 commit 0a4ad00

7 files changed

Lines changed: 72 additions & 21 deletions

File tree

.github/workflows/rn-lint.yml

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,44 @@ jobs:
2020
steps:
2121
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2222
- uses: norio-nomura/action-swiftlint@9f4dcd7fd46b4e75d7935cf2f4df406d5cae3684 # 3.2.1
23+
env:
24+
WORKING_DIRECTORY: platforms/react-native
2325
with:
24-
args: --strict
26+
args: --strict modules/@shopify/checkout-kit-react-native --config .swiftlint.yml
27+
28+
swiftformat:
29+
name: SwiftFormat & SwiftLint
30+
runs-on: ${{ vars.MACOS_RUNNER }}
31+
timeout-minutes: 10
32+
env:
33+
MINT_PATH: ${{ github.workspace }}/.mint/lib
34+
MINT_LINK_PATH: ${{ github.workspace }}/.mint/bin
35+
steps:
36+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
37+
38+
- name: Cache Mint packages
39+
id: mint-cache
40+
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
41+
with:
42+
path: .mint
43+
key: ${{ runner.os }}-mint-${{ hashFiles('platforms/swift/Mintfile') }}
44+
restore-keys: |
45+
${{ runner.os }}-mint-
46+
47+
- name: Install Mint
48+
run: brew install mint
49+
50+
- name: Bootstrap Mint packages
51+
if: steps.mint-cache.outputs.cache-hit != 'true'
52+
working-directory: platforms/swift
53+
run: mint bootstrap --link
54+
55+
- name: Add Mint to PATH
56+
run: echo "${{ github.workspace }}/.mint/bin" >> "$GITHUB_PATH"
57+
58+
- name: Check Swift bridge lint and formatting
59+
working-directory: platforms/react-native
60+
run: ./scripts/lint_swift check
2561

2662
lint:
2763
name: Lint module + sample

platforms/react-native/.swiftformat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
--disable redundantReturn,hoistAwait,preferKeyPath,redundantInternal,redundantPublic
1010
--swiftversion 5.7.1
1111
--extensionacl on-declarations
12+
--exclude modules/@shopify/checkout-kit-react-native/ios/.build

platforms/react-native/.swiftlint.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,7 @@ nesting:
3636
type_level:
3737
warning: 2
3838

39+
excluded:
40+
- modules/@shopify/checkout-kit-react-native/ios/.build
41+
3942
reporter: "xcode"

platforms/react-native/modules/@shopify/checkout-kit-react-native/ios/ProtocolRelay.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ struct DispatchEnvelope<Payload: Encodable>: Encodable {
1212
let payload: Payload
1313
}
1414

15-
// Bridges native CheckoutProtocol notifications to the React Native onDispatch
16-
// event stream. Payloads are emitted in protocol wire casing; JS performs the
17-
// schema-aware conversion to the public camelCase shape with QuickType.
15+
/// Bridges native CheckoutProtocol notifications to the React Native onDispatch
16+
/// event stream. Payloads are emitted in protocol wire casing; JS performs the
17+
/// schema-aware conversion to the public camelCase shape with QuickType.
1818
let supportedProtocolRelayMethods = [
1919
CheckoutProtocol.complete.method,
2020
CheckoutProtocol.error.method,
@@ -65,9 +65,9 @@ func makeRelayClient(
6565
}
6666

6767
@MainActor
68-
private func forwardEnvelope<P: Encodable>(
68+
private func forwardEnvelope(
6969
type: String,
70-
payload: P,
70+
payload: some Encodable,
7171
dispatch: @MainActor @Sendable (String) -> Void
7272
) {
7373
let encoder = JSONEncoder()

platforms/react-native/modules/@shopify/checkout-kit-react-native/ios/ShopifyCheckoutKit.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ class RCTShopifyCheckoutKit: NSObject {
247247
return NSNumber(value: available)
248248
}
249249

250-
@objc func respondToGeolocationRequest(_ allow: Bool) {
250+
@objc func respondToGeolocationRequest(_: Bool) {
251251
// No-op on iOS — geolocation permission is handled natively
252252
}
253253

@@ -321,14 +321,14 @@ extension RCTShopifyCheckoutKit: CheckoutDelegate {
321321

322322
// MARK: - Dispatch envelope helpers
323323

324-
private extension RCTShopifyCheckoutKit {
325-
func emitDispatchEvent(_ json: String) {
324+
extension RCTShopifyCheckoutKit {
325+
private func emitDispatchEvent(_ json: String) {
326326
perform(NSSelectorFromString("emitOnDispatchFromSwift:"), with: json)
327327
}
328328

329329
/// Builds a `{ "type": ..., "payload": ... }` envelope and forwards
330330
/// it to the JS dispatch event stream.
331-
func emitDispatchEnvelope(type: DispatchEventType, payload: [String: Any]?) {
331+
private func emitDispatchEnvelope(type: DispatchEventType, payload: [String: Any]?) {
332332
var envelope: [String: Any] = ["type": type.rawValue]
333333
if let payload {
334334
envelope["payload"] = payload
@@ -350,7 +350,7 @@ private extension RCTShopifyCheckoutKit {
350350
/// shape the JS dispatcher expects. Field names match Android's
351351
/// `CustomCheckoutListener.populateErrorDetails` so the JS-side
352352
/// `parseCheckoutError` works identically on both platforms.
353-
static func errorPayload(from error: CheckoutError) -> [String: Any] {
353+
fileprivate static func errorPayload(from error: CheckoutError) -> [String: Any] {
354354
switch error {
355355
case let .sdkError(underlying):
356356
return [

platforms/react-native/modules/@shopify/checkout-kit-react-native/ios/Tests/ProtocolRelayTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct ProtocolRelayTests {
1818

1919
let payloadDict = try #require(parsed["payload"] as? [String: Any])
2020
#expect(payloadDict["continue_url"] as? String == "https://example.com")
21-
#expect(payloadDict["line_items"] as? [Any] != nil)
21+
#expect(payloadDict["line_items"] is [Any])
2222
#expect(payloadDict["continueUrl"] == nil)
2323
#expect(payloadDict["lineItems"] == nil)
2424
}
@@ -96,7 +96,7 @@ struct ProtocolRelayTests {
9696
}
9797

9898
@MainActor
99-
@Test func relayIgnoresMethodsNotInSubscribedList() async throws {
99+
@Test func relayIgnoresMethodsNotInSubscribedList() async {
100100
var captured: String?
101101
let client = makeRelayClient(
102102
subscribedMethods: [],

platforms/react-native/scripts/lint_swift

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,38 @@ print_install_instructions() {
2424

2525
resolve_tool() {
2626
local command_name=$1
27+
local display_name=$2
2728

28-
if which "$command_name" >/dev/null; then
29-
which "$command_name"
30-
return 0
29+
if command -v mint >/dev/null; then
30+
local mint_tool
31+
if mint_tool="$(cd "$SWIFT_TOOLS_DIR" && mint which "$command_name" 2>/dev/null)"; then
32+
echo "$mint_tool"
33+
return 0
34+
fi
3135
fi
3236

33-
if command -v mint >/dev/null; then
34-
(cd "$SWIFT_TOOLS_DIR" && mint which "$command_name")
35-
return $?
37+
if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
38+
echo "$display_name must resolve through Mint in CI" >&2
39+
print_install_instructions >&2
40+
return 1
41+
fi
42+
43+
if command -v "$command_name" >/dev/null; then
44+
echo "⚠️ WARN: using $display_name from PATH. Run 'dev up' or bootstrap Mint for the pinned version." >&2
45+
command -v "$command_name"
46+
return 0
3647
fi
3748

3849
return 1
3950
}
4051

41-
if ! SWIFTLINT="$(resolve_tool swiftlint)"; then
52+
if ! SWIFTLINT="$(resolve_tool swiftlint SwiftLint)"; then
4253
echo "⚠️ WARN: SwiftLint not installed"
4354
print_install_instructions
4455
exit 1
4556
fi
4657

47-
if ! SWIFTFORMAT="$(resolve_tool swiftformat)"; then
58+
if ! SWIFTFORMAT="$(resolve_tool swiftformat SwiftFormat)"; then
4859
echo "⚠️ WARN: SwiftFormat not installed"
4960
print_install_instructions
5061
exit 1

0 commit comments

Comments
 (0)