Skip to content

Commit d6ea146

Browse files
committed
Fix React Native Swift lint CI parity
1 parent 6e965dd commit d6ea146

7 files changed

Lines changed: 71 additions & 21 deletions

File tree

.github/workflows/rn-lint.yml

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

2055
lint:
2156
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)