diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f8619d5a..43cf6efd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -63,3 +63,54 @@ updates: apollo: patterns: - "com.apollographql.apollo*" + + # React Native — root pnpm workspace + - package-ecosystem: npm + directory: "/platforms/react-native" + schedule: + interval: daily + cooldown: + default-days: 7 + ignore: + - dependency-name: "*" + update-types: + - "version-update:semver-major" + - "version-update:semver-minor" + + # React Native — Checkout Sheet Kit module + - package-ecosystem: npm + directory: "/platforms/react-native/modules/@shopify/checkout-sheet-kit" + schedule: + interval: daily + cooldown: + default-days: 7 + ignore: + - dependency-name: "*" + update-types: + - "version-update:semver-major" + - "version-update:semver-minor" + + # React Native — sample app + - package-ecosystem: npm + directory: "/platforms/react-native/sample" + schedule: + interval: daily + cooldown: + default-days: 7 + ignore: + - dependency-name: "*" + update-types: + - "version-update:semver-major" + + # React Native — sample iOS CocoaPods (via Bundler/Gemfile) + - package-ecosystem: bundler + directory: "/platforms/react-native/sample" + schedule: + interval: daily + cooldown: + default-days: 7 + ignore: + - dependency-name: "*" + update-types: + - "version-update:semver-major" + - "version-update:semver-minor" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d5ff97c..ca958b61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,6 +50,12 @@ jobs: - '.github/workflows/ci.yml' reactNative: - 'platforms/react-native/**' + - '.github/workflows/rn-test.yml' + - '.github/workflows/rn-test-android.yml' + - '.github/workflows/rn-test-ios.yml' + - '.github/workflows/rn-license-headers.yml' + - '.github/workflows/rn-check-packed-files.yml' + - '.github/workflows/rn-lint.yml' - '.github/workflows/ci.yml' android-test: @@ -82,6 +88,45 @@ jobs: if: needs.changes.outputs.swift == 'true' uses: ./.github/workflows/swift-lint.yml + rn-test: + name: React Native + needs: changes + if: needs.changes.outputs.reactNative == 'true' + permissions: + contents: read + pull-requests: write + uses: ./.github/workflows/rn-test.yml + + rn-test-android: + name: React Native + needs: changes + if: needs.changes.outputs.reactNative == 'true' + uses: ./.github/workflows/rn-test-android.yml + + rn-test-ios: + name: React Native + needs: changes + if: needs.changes.outputs.reactNative == 'true' + uses: ./.github/workflows/rn-test-ios.yml + + rn-license-headers: + name: React Native + needs: changes + if: needs.changes.outputs.reactNative == 'true' + uses: ./.github/workflows/rn-license-headers.yml + + rn-check-packed-files: + name: React Native + needs: changes + if: needs.changes.outputs.reactNative == 'true' + uses: ./.github/workflows/rn-check-packed-files.yml + + rn-lint: + name: React Native + needs: changes + if: needs.changes.outputs.reactNative == 'true' + uses: ./.github/workflows/rn-lint.yml + # Single required status check for branch protection. # Passes when every relevant platform job either succeeded or was skipped # because no files in that platform's tree changed. @@ -95,6 +140,12 @@ jobs: - swift-test-package - swift-build-samples - swift-lint + - rn-test + - rn-test-android + - rn-test-ios + - rn-license-headers + - rn-check-packed-files + - rn-lint runs-on: ubuntu-latest steps: - name: Verify all upstream jobs succeeded or were skipped diff --git a/.github/workflows/rn-check-packed-files.yml b/.github/workflows/rn-check-packed-files.yml new file mode 100644 index 00000000..1d2ff27c --- /dev/null +++ b/.github/workflows/rn-check-packed-files.yml @@ -0,0 +1,41 @@ +name: React Native — Check Packed Files + +on: + workflow_call: + workflow_dispatch: + +jobs: + check-packed-files: + name: Check package files + runs-on: ubuntu-latest + timeout-minutes: 5 + env: + TERM: xterm + defaults: + run: + working-directory: platforms/react-native + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js and pnpm + uses: shop/setup-javascript-action@main + with: + node-version-file: platforms/react-native/package.json + cache-dependency-path: platforms/react-native/pnpm-lock.yaml + + - name: Cache turbo build setup + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: platforms/react-native/.turbo + key: ${{ runner.os }}-turbo-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-turbo- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build module and compare snapshot + run: | + pnpm module clean + pnpm module build + pnpm compare-snapshot diff --git a/.github/workflows/rn-license-headers.yml b/.github/workflows/rn-license-headers.yml new file mode 100644 index 00000000..037eb8e8 --- /dev/null +++ b/.github/workflows/rn-license-headers.yml @@ -0,0 +1,19 @@ +name: React Native — Check License Headers + +on: + workflow_call: + workflow_dispatch: + +jobs: + license: + name: Verify license headers + runs-on: ubuntu-latest + timeout-minutes: 5 + defaults: + run: + working-directory: platforms/react-native + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Check license headers + run: ./scripts/copy_license --check diff --git a/.github/workflows/rn-lint.yml b/.github/workflows/rn-lint.yml new file mode 100644 index 00000000..53ef820f --- /dev/null +++ b/.github/workflows/rn-lint.yml @@ -0,0 +1,51 @@ +name: React Native — Lint + +on: + workflow_call: + workflow_dispatch: + +jobs: + swiftlint: + name: SwiftLint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: norio-nomura/action-swiftlint@9f4dcd7fd46b4e75d7935cf2f4df406d5cae3684 # 3.2.1 + with: + args: --strict + + lint: + name: Lint module + sample + runs-on: ubuntu-latest + timeout-minutes: 10 + defaults: + run: + working-directory: platforms/react-native + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js and pnpm + uses: shop/setup-javascript-action@main + with: + node-version-file: platforms/react-native/package.json + cache-dependency-path: platforms/react-native/pnpm-lock.yaml + + - name: Cache turbo build setup + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: platforms/react-native/.turbo + key: ${{ runner.os }}-turbo-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-turbo- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build module + run: pnpm module build + + - name: Lint module + run: pnpm module lint + + - name: Lint sample + run: pnpm sample lint diff --git a/.github/workflows/rn-test-android.yml b/.github/workflows/rn-test-android.yml new file mode 100644 index 00000000..7b228045 --- /dev/null +++ b/.github/workflows/rn-test-android.yml @@ -0,0 +1,56 @@ +name: React Native — Run Android Tests + +on: + workflow_call: + workflow_dispatch: + +env: + JAVA_VERSION: '22' + +jobs: + test-android: + name: Run Android Tests + runs-on: ubuntu-latest + timeout-minutes: 20 + defaults: + run: + working-directory: platforms/react-native + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js and pnpm + uses: shop/setup-javascript-action@main + with: + node-version-file: platforms/react-native/package.json + cache-dependency-path: platforms/react-native/pnpm-lock.yaml + + - name: Install JDK + id: setup-java + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: zulu + java-version: ${{ env.JAVA_VERSION }} + + - name: Cache turbo build setup + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: platforms/react-native/.turbo + key: ${{ runner.os }}-turbo-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-turbo- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run Android tests + timeout-minutes: 20 + env: + GRADLE_OPTS: -Xmx4g -XX:MaxMetaspaceSize=768m + JAVA_HOME: ${{ steps.setup-java.outputs.path }} + run: | + echo "JAVA_HOME: $JAVA_HOME" + java -version + javac -version + echo "STOREFRONT_DOMAIN=myshopify.com" > sample/.env + pnpm module build + pnpm sample test:android --no-daemon diff --git a/.github/workflows/rn-test-ios.yml b/.github/workflows/rn-test-ios.yml new file mode 100644 index 00000000..2c0c6da0 --- /dev/null +++ b/.github/workflows/rn-test-ios.yml @@ -0,0 +1,73 @@ +name: React Native — Run iOS Tests + +on: + workflow_call: + workflow_dispatch: + +jobs: + test-ios: + name: Run iOS Tests + runs-on: ${{ vars.MACOS_RUNNER }} + timeout-minutes: 30 + defaults: + run: + working-directory: platforms/react-native + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Display Xcode info + run: | + echo "Xcode Path: $(xcode-select -p)" + echo "Xcode Version: $(xcrun xcodebuild -version)" + + - name: Setup iOS Simulator + run: | + xcrun simctl list runtimes + xcrun simctl list devicetypes | grep iPhone + xcrun simctl delete all + CURRENT_SIMULATOR_UUID=$(xcrun simctl create TestDevice "iPhone 16 Pro") + echo "CURRENT_SIMULATOR_UUID=$CURRENT_SIMULATOR_UUID" >> "$GITHUB_ENV" + + - name: Setup Node.js and pnpm + uses: shop/setup-javascript-action@main + with: + node-version-file: platforms/react-native/package.json + cache-dependency-path: platforms/react-native/pnpm-lock.yaml + + - name: Cache turbo build setup + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: platforms/react-native/.turbo + key: ${{ runner.os }}-turbo-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-turbo- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Setup Ruby + uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0 + with: + ruby-version: 3.3.6 + bundler-cache: true + working-directory: platforms/react-native/sample + + - name: Cache cocoapods + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: platforms/react-native/sample/ios/Pods + key: ${{ runner.os }}-cocoapods-${{ hashFiles('platforms/react-native/sample/ios/Podfile.lock', 'platforms/react-native/sample/Gemfile.lock', 'platforms/react-native/sample/Gemfile', 'platforms/react-native/package.json', 'platforms/react-native/sample/package.json', 'platforms/react-native/modules/@shopify/checkout-sheet-kit/package.json', 'platforms/react-native/pnpm-lock.yaml') }} + + - name: Install cocoapods + working-directory: platforms/react-native/sample + run: | + set -euo pipefail + bundle install + cd ios + bundle exec pod install --deployment --repo-update + + - name: Build module + run: pnpm module build + + - name: Run iOS tests + run: pnpm sample test:ios diff --git a/.github/workflows/rn-test.yml b/.github/workflows/rn-test.yml new file mode 100644 index 00000000..1660fcca --- /dev/null +++ b/.github/workflows/rn-test.yml @@ -0,0 +1,39 @@ +name: React Native — Run Jest Tests + +on: + workflow_call: + workflow_dispatch: + +jobs: + test: + name: Run jest tests + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + pull-requests: write + defaults: + run: + working-directory: platforms/react-native + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js and pnpm + uses: shop/setup-javascript-action@main + with: + node-version-file: platforms/react-native/package.json + cache-dependency-path: platforms/react-native/pnpm-lock.yaml + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run tests with coverage + run: pnpm test --coverage --testPathPatterns="modules/@shopify/checkout-sheet-kit/tests" --coverageReporters=json-summary + + - name: Coverage comment + if: github.event_name == 'pull_request' + uses: MishaKav/jest-coverage-comment@fb83bcbaeb5ca467936175796f862a2992938833 # main + with: + coverage-summary-path: platforms/react-native/coverage/coverage-summary.json + title: 'React Native — Coverage Report' + create-new-comment: false diff --git a/.gitignore b/.gitignore index 00c74dfe..f94dac8a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,10 @@ xcuserdata/ # Sample app secrets (Swift) **/Storefront.xcconfig **/*.entitlements +# Exception: the React Native sample's entitlements are source code (associated +# domains + in-app payments merchant ID), not secrets — Xcode requires this file +# at build time and CI fails without it. +!platforms/react-native/sample/ios/ReactNative/ReactNative.entitlements # Apollo / GraphQL *.graphqls diff --git a/platforms/react-native/modules/@shopify/checkout-sheet-kit/package.snapshot.json b/platforms/react-native/modules/@shopify/checkout-sheet-kit/package.snapshot.json index 8cddcc9f..6e731350 100644 --- a/platforms/react-native/modules/@shopify/checkout-sheet-kit/package.snapshot.json +++ b/platforms/react-native/modules/@shopify/checkout-sheet-kit/package.snapshot.json @@ -1,6 +1,4 @@ [ - "LICENSE", - "RNShopifyCheckoutSheetKit.podspec", "android/build.gradle", "android/gradle.properties", "android/proguard-rules.pro", @@ -62,7 +60,9 @@ "lib/typescript/src/specs/NativeShopifyCheckoutSheetKit.d.ts.map", "lib/typescript/src/specs/RCTAcceleratedCheckoutButtonsNativeComponent.d.ts", "lib/typescript/src/specs/RCTAcceleratedCheckoutButtonsNativeComponent.d.ts.map", + "LICENSE", "package.json", + "RNShopifyCheckoutSheetKit.podspec", "src/components/AcceleratedCheckoutButtons.tsx", "src/context.tsx", "src/errors.d.ts", diff --git a/platforms/react-native/sample/ios/ReactNative/ReactNative.entitlements b/platforms/react-native/sample/ios/ReactNative/ReactNative.entitlements new file mode 100644 index 00000000..dda6002c --- /dev/null +++ b/platforms/react-native/sample/ios/ReactNative/ReactNative.entitlements @@ -0,0 +1,15 @@ + + + + + com.apple.developer.associated-domains + + webcredentials:myshopify.com + applinks:myshopify.com + + com.apple.developer.in-app-payments + + merchant.com.shopify.example.CheckoutKitReactNative + + + diff --git a/platforms/react-native/scripts/create_snapshot b/platforms/react-native/scripts/create_snapshot index 878ff422..165f4c19 100755 --- a/platforms/react-native/scripts/create_snapshot +++ b/platforms/react-native/scripts/create_snapshot @@ -2,4 +2,4 @@ OUTPUT_FILE=${1:-modules/@shopify/checkout-sheet-kit/package.snapshot.json} -(cd modules/@shopify/checkout-sheet-kit && npm pack --dry-run --json) | jq ".[0].files | map(.path)" > $OUTPUT_FILE +(cd modules/@shopify/checkout-sheet-kit && pnpm pack --dry-run --json) | jq ".files | map(.path)" > $OUTPUT_FILE