diff --git a/.github/codeql/ReactCodeQLShim.swift b/.github/codeql/ReactCodeQLShim.swift new file mode 100644 index 000000000..381cbc1e2 --- /dev/null +++ b/.github/codeql/ReactCodeQLShim.swift @@ -0,0 +1,22 @@ +// Provides the minimal React types needed to compile the Swift wrapper without its dependency graph. +// This module is built before CodeQL starts, so the shim itself is not analyzed. + +import Foundation +import UIKit + +public typealias RCTDirectEventBlock = ([AnyHashable: Any]?) -> Void +public typealias RCTBubblingEventBlock = ([AnyHashable: Any]?) -> Void + +open class RCTViewManager: NSObject { + open func view() -> UIView! { + nil + } + + open class func requiresMainQueueSetup() -> Bool { + false + } + + open func constantsToExport() -> [AnyHashable: Any]! { + nil + } +} diff --git a/.github/codeql/build_react_native_ios b/.github/codeql/build_react_native_ios new file mode 100755 index 000000000..0650b2e34 --- /dev/null +++ b/.github/codeql/build_react_native_ios @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_directory="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repository_root="$(cd "$script_directory/../.." && pwd)" +module_directory="${RUNNER_TEMP:-${TMPDIR:-/tmp}}/codeql-react-native-ios-modules" +module_cache_directory="$module_directory/clang-module-cache" +sdk_path="$(xcrun --sdk iphonesimulator --show-sdk-path)" +target="arm64-apple-ios16.6-simulator" + +mkdir -p "$module_cache_directory" + +if [[ ! -f "$module_directory/React.swiftmodule" ]]; then + xcrun swiftc \ + -emit-module \ + -parse-as-library \ + -module-name React \ + -target "$target" \ + -sdk "$sdk_path" \ + -module-cache-path "$module_cache_directory" \ + "$script_directory/ReactCodeQLShim.swift" \ + -emit-module-path "$module_directory/React.swiftmodule" +fi + +shopify_checkout_kit_products="$repository_root/platforms/react-native/test/rct-integration-app/build/Debug-iphonesimulator/ShopifyCheckoutKit" +shopify_checkout_kit_module_map="$shopify_checkout_kit_products/ShopifyCheckoutKit.modulemap" + +if [[ ! -f "$shopify_checkout_kit_module_map" ]]; then + echo "ShopifyCheckoutKit module map was not built at $shopify_checkout_kit_module_map" >&2 + exit 1 +fi + +wrapper_sources=( + "$repository_root"/platforms/react-native/modules/@shopify/checkout-kit-react-native/ios/*.swift +) + +if [[ "${#wrapper_sources[@]}" -eq 0 ]]; then + echo "No React Native iOS Swift sources were found" >&2 + exit 1 +fi + +xcrun swiftc \ + -emit-module \ + -parse-as-library \ + -module-name RNShopifyCheckoutKit \ + -target "$target" \ + -sdk "$sdk_path" \ + -module-cache-path "$module_cache_directory" \ + -I "$module_directory" \ + -I "$shopify_checkout_kit_products" \ + -Xcc -fmodule-map-file="$shopify_checkout_kit_module_map" \ + -Xcc -I \ + -Xcc "$shopify_checkout_kit_products" \ + -D COCOAPODS \ + "${wrapper_sources[@]}" \ + -emit-module-path "$module_directory/RNShopifyCheckoutKit.swiftmodule" diff --git a/.github/codeql/build_swift b/.github/codeql/build_swift new file mode 100755 index 000000000..8c457105d --- /dev/null +++ b/.github/codeql/build_swift @@ -0,0 +1,149 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_directory="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repository_root="$(cd "$script_directory/../.." && pwd)" +mode="${1:---typecheck}" + +: "${DERIVED_DATA_PATH:?DERIVED_DATA_PATH must be set}" + +products_directory="$DERIVED_DATA_PATH/Build/Products/Debug-iphonesimulator" +intermediates_directory="$DERIVED_DATA_PATH/Build/Intermediates.noindex/ShopifyCheckoutKit.build/Debug-iphonesimulator" +prepared_module_directory="${RUNNER_TEMP:-${TMPDIR:-/tmp}}/codeql-swift-prepared-modules" +sdk_path="$(xcrun --sdk iphonesimulator --show-sdk-path)" +target="arm64-apple-ios15.0-simulator" + +case "$mode" in + --prepare-dependencies) + module_cache_directory="${RUNNER_TEMP:-${TMPDIR:-/tmp}}/codeql-swift-prepare-clang-module-cache" + rm -rf "$prepared_module_directory" + mkdir -p "$prepared_module_directory" + ;; + --typecheck) + module_cache_directory="${RUNNER_TEMP:-${TMPDIR:-/tmp}}/codeql-swift-clang-module-cache" + ;; + *) + echo "Usage: $0 [--prepare-dependencies|--typecheck]" >&2 + exit 1 + ;; +esac + +if [[ ! -d "$products_directory" ]]; then + echo "Prepared Swift products were not found at $products_directory" >&2 + exit 1 +fi + +rm -rf "$module_cache_directory" +mkdir -p "$module_cache_directory" + +common_arguments=( + -parse-as-library + -swift-version 6 + -target "$target" + -sdk "$sdk_path" + -module-cache-path "$module_cache_directory" + -I "$prepared_module_directory" + -I "$products_directory" + -D SWIFT_PACKAGE + -D DEBUG + -D SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE + -D Xcode + -enable-testing + -package-name checkout_kit + -warnings-as-errors +) + +emit_module() { + local module_name="$1" + shift + + echo "::group::Prepare $module_name for focused CodeQL type checking ($# sources)" + xcrun swiftc \ + -emit-module \ + "${common_arguments[@]}" \ + -module-name "$module_name" \ + "$@" \ + -emit-module-path "$prepared_module_directory/$module_name.swiftmodule" + echo "::endgroup::" +} + +typecheck_module() { + local module_name="$1" + shift + + echo "::group::Type-check $module_name for CodeQL ($# sources)" + xcrun swiftc \ + -typecheck \ + "${common_arguments[@]}" \ + -module-name "$module_name" \ + "$@" + echo "::endgroup::" +} + +require_sources() { + local module_name="$1" + local source_count="$2" + + if [[ "$source_count" -eq 0 ]]; then + echo "No Swift sources were found for $module_name" >&2 + exit 1 + fi +} + +protocol_sources=() +while IFS= read -r source; do + protocol_sources+=("$source") +done < <(find "$repository_root/protocol/languages/swift/Sources/UniversalCommerceProtocol/EmbeddedCheckoutProtocol" -type f -name '*.swift' | sort) +require_sources EmbeddedCheckoutProtocol "${#protocol_sources[@]}" + +telemetry_sources=() +while IFS= read -r source; do + telemetry_sources+=("$source") +done < <(find "$repository_root/telemetry/languages/swift/Sources/CheckoutKitTelemetry" -type f -name '*.swift' | sort) +require_sources CheckoutKitTelemetry "${#telemetry_sources[@]}" + +checkout_sources=() +while IFS= read -r source; do + checkout_sources+=("$source") +done < <(find "$repository_root/platforms/swift/Sources/ShopifyCheckoutKit" -type f -name '*.swift' | sort) +require_sources ShopifyCheckoutKit "${#checkout_sources[@]}" +checkout_sources+=( + "$intermediates_directory/ShopifyCheckoutKit.build/DerivedSources/resource_bundle_accessor.swift" + "$intermediates_directory/ShopifyCheckoutKit.build/DerivedSources/GeneratedAssetSymbols.swift" +) + +accelerated_sources=() +while IFS= read -r source; do + accelerated_sources+=("$source") +done < <(find "$repository_root/platforms/swift/Sources/ShopifyAcceleratedCheckouts" -type f -name '*.swift' | sort) +require_sources ShopifyAcceleratedCheckouts "${#accelerated_sources[@]}" +accelerated_sources+=( + "$intermediates_directory/ShopifyAcceleratedCheckouts.build/DerivedSources/resource_bundle_accessor.swift" + "$intermediates_directory/ShopifyAcceleratedCheckouts.build/DerivedSources/GeneratedAssetSymbols.swift" +) + +for source in "${checkout_sources[@]}" "${accelerated_sources[@]}"; do + if [[ ! -f "$source" ]]; then + echo "Required Swift source was not found at $source" >&2 + exit 1 + fi +done + +if [[ "$mode" == "--prepare-dependencies" ]]; then + emit_module EmbeddedCheckoutProtocol "${protocol_sources[@]}" + emit_module CheckoutKitTelemetry "${telemetry_sources[@]}" + emit_module ShopifyCheckoutKit "${checkout_sources[@]}" +else + for module_name in EmbeddedCheckoutProtocol CheckoutKitTelemetry ShopifyCheckoutKit; do + if [[ ! -f "$prepared_module_directory/$module_name.swiftmodule" ]]; then + echo "Prepared Swift module was not found at $prepared_module_directory/$module_name.swiftmodule" >&2 + exit 1 + fi + done + + typecheck_module EmbeddedCheckoutProtocol "${protocol_sources[@]}" + typecheck_module CheckoutKitTelemetry "${telemetry_sources[@]}" + typecheck_module ShopifyCheckoutKit "${checkout_sources[@]}" + typecheck_module ShopifyAcceleratedCheckouts "${accelerated_sources[@]}" +fi diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 000000000..af4d7723d --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,18 @@ +name: Checkout Kit CodeQL + +queries: + - uses: security-extended + +paths-ignore: + - '**/Tests/**' + - '**/tests/**' + - '**/test/**' + - '**/Samples/**' + - '**/samples/**' + - '**/sample/**' + - '**/*.test.*' + - '**/*.spec.*' + - '**/Fixtures/**' + - '**/fixtures/**' + - 'scripts/test/**' + - 'scripts/test_ruby' diff --git a/.github/codeql/prepare_swift_modules b/.github/codeql/prepare_swift_modules new file mode 100755 index 000000000..86ab9a2d8 --- /dev/null +++ b/.github/codeql/prepare_swift_modules @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_directory="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repository_root="$(cd "$script_directory/../.." && pwd)" + +: "${CURRENT_SIMULATOR_UUID:?CURRENT_SIMULATOR_UUID must be set}" +: "${DERIVED_DATA_PATH:?DERIVED_DATA_PATH must be set}" + +xcodebuild_arguments=( + build + -scheme ShopifyCheckoutKit-Package + -sdk iphonesimulator + -destination "id=$CURRENT_SIMULATOR_UUID" + -derivedDataPath "$DERIVED_DATA_PATH" + -skipPackagePluginValidation + -disableAutomaticPackageResolution + SWIFT_TREAT_WARNINGS_AS_ERRORS=YES + CODE_SIGNING_REQUIRED=NO + CODE_SIGNING_ALLOWED=NO + COMPILER_INDEX_STORE_ENABLE=NO +) + +rm -rf "$DERIVED_DATA_PATH" +cd "$repository_root" + +if command -v xcbeautify >/dev/null 2>&1; then + if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then + xcodebuild "${xcodebuild_arguments[@]}" | xcbeautify --renderer github-actions + else + xcodebuild "${xcodebuild_arguments[@]}" | xcbeautify + fi +else + xcodebuild "${xcodebuild_arguments[@]}" +fi + +"$script_directory/build_swift" --prepare-dependencies diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..aee525278 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,410 @@ +name: CodeQL + +on: + push: + branches: + - main + paths-ignore: + - '**/Tests/**' + - '**/tests/**' + - '**/test/**' + - '**/Samples/**' + - '**/samples/**' + - '**/sample/**' + - '**/*.test.*' + - '**/*.spec.*' + - '**/Fixtures/**' + - '**/fixtures/**' + - 'scripts/test/**' + - 'scripts/test_ruby' + pull_request: + types: [opened, synchronize, reopened, ready_for_review, converted_to_draft] + schedule: + - cron: '17 8 * * 1' + workflow_dispatch: + +permissions: + actions: read + contents: read + packages: read + pull-requests: read + security-events: write + +concurrency: + group: codeql-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + analyze-without-build: + name: Analyze (${{ matrix.language }}) + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + language: + - actions + - javascript-typescript + - ruby + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Initialize CodeQL + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + languages: ${{ matrix.language }} + build-mode: none + config-file: ./.github/codeql/codeql-config.yml + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + category: /language:${{ matrix.language }} + + native-changes: + name: Detect native changes + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + android: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || steps.platform.outputs.android == 'true' || steps.platform.outputs.codeql == 'true' }} + reactNativeAndroid: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || steps.platform.outputs.reactNativeAndroid == 'true' || steps.platform.outputs.codeql == 'true' }} + reactNativeIos: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || steps.platform.outputs.reactNativeIos == 'true' || steps.platform.outputs.codeql == 'true' }} + swift: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || steps.platform.outputs.swift == 'true' || steps.platform.outputs.codeql == 'true' }} + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Detect changed native platforms + id: platform + uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3 + with: + filters: | + android: + - 'platforms/android/lib/src/main/**' + - 'platforms/android/**/*.gradle*' + - 'platforms/android/gradle/**' + - 'platforms/android/gradle.properties' + - 'protocol/languages/kotlin/**' + reactNativeAndroid: + - 'platforms/react-native/modules/@shopify/checkout-kit-react-native/android/**' + reactNativeIos: + - 'platforms/react-native/modules/@shopify/checkout-kit-react-native/ios/**' + - 'platforms/react-native/modules/@shopify/checkout-kit-react-native/RNShopifyCheckoutKit.podspec' + swift: + - 'Package.swift' + - 'Package.resolved' + - 'platforms/swift/Package.swift' + - 'platforms/swift/Sources/**' + - 'protocol/languages/swift/Sources/**' + - 'telemetry/languages/swift/Sources/**' + codeql: + - '.github/codeql/**' + - '.github/workflows/codeql.yml' + + analyze-android: + name: Analyze (android) + needs: native-changes + if: needs.native-changes.outputs.android == 'true' + runs-on: ubuntu-latest + timeout-minutes: 20 + env: + GRADLE_OPTS: -Xmx4g -XX:MaxMetaspaceSize=768m + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Install JDK 17 + uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6.0.0 + with: + distribution: zulu + java-version: 17 + cache: gradle + cache-dependency-path: | + platforms/android/**/*.gradle* + platforms/android/**/gradle-wrapper.properties + platforms/android/gradle.properties + protocol/languages/kotlin/**/*.gradle* + protocol/languages/kotlin/**/*.toml + + - name: Initialize CodeQL + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + languages: java-kotlin + build-mode: manual + config-file: ./.github/codeql/codeql-config.yml + + - name: Build Android SDK and protocol + run: | + platforms/android/gradlew \ + -p platforms/android \ + :lib:assembleRelease \ + --console=plain \ + --no-daemon + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + category: /language:java-kotlin/platform:android + output: sarif-results + upload: failure-only + + - name: Filter Android results to shipped sources + uses: advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0 # v1.1 + with: + patterns: | + -** + +platforms/android/lib/src/main/**/* + +protocol/languages/kotlin/embedded-checkout-protocol/src/main/**/* + input: sarif-results/java.sarif + output: sarif-results/java.sarif + + - name: Upload Android results + uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + sarif_file: sarif-results/java.sarif + + analyze-react-native-android: + name: Analyze (react-native-android) + needs: native-changes + if: needs.native-changes.outputs.reactNativeAndroid == 'true' + runs-on: ubuntu-latest + timeout-minutes: 30 + env: + GRADLE_OPTS: -Xmx4g -XX:MaxMetaspaceSize=768m + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Setup Node.js, pnpm, and React Native dependencies + uses: ./.github/actions/setup + with: + node-version-file: platforms/react-native/package.json + cache-dependency-path: platforms/react-native/pnpm-lock.yaml + package-json-file: platforms/react-native/package.json + working-directory: platforms/react-native + + - name: Install JDK 17 + uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6.0.0 + with: + distribution: zulu + java-version: 17 + cache: gradle + cache-dependency-path: | + platforms/react-native/package.json + platforms/react-native/pnpm-lock.yaml + platforms/react-native/sample/package.json + platforms/react-native/sample/android/**/*.gradle* + platforms/react-native/sample/android/**/gradle-wrapper.properties + platforms/react-native/sample/android/gradle.properties + platforms/react-native/modules/@shopify/checkout-kit-react-native/android/**/*.gradle* + platforms/react-native/modules/@shopify/checkout-kit-react-native/android/gradle.properties + + - name: Prepare React Native Android build + run: | + printf 'STOREFRONT_DOMAIN=example.myshopify.com\n' > platforms/react-native/sample/.env + platforms/react-native/sample/android/gradlew \ + -p platforms/react-native/sample/android \ + projects \ + --console=plain \ + --no-daemon + + - name: Initialize CodeQL + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + languages: java-kotlin + build-mode: manual + config-file: ./.github/codeql/codeql-config.yml + + - name: Build React Native Android wrapper + run: | + platforms/react-native/sample/android/gradlew \ + -p platforms/react-native/sample/android \ + :shopify_checkout-kit-react-native:assembleRelease \ + -PreactNativeArchitectures=arm64-v8a \ + --console=plain \ + --no-daemon + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + category: /language:java-kotlin/platform:react-native-android + output: sarif-results + upload: failure-only + + - name: Filter React Native Android results to shipped sources + uses: advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0 # v1.1 + with: + patterns: | + -** + +platforms/react-native/modules/@shopify/checkout-kit-react-native/android/src/main/**/* + input: sarif-results/java.sarif + output: sarif-results/java.sarif + + - name: Upload React Native Android results + uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + sarif_file: sarif-results/java.sarif + + analyze-swift: + name: Analyze (swift) + needs: native-changes + if: needs.native-changes.outputs.swift == 'true' + runs-on: ${{ vars.MACOS_RUNNER }} + timeout-minutes: 45 + env: + DERIVED_DATA_PATH: ${{ github.workspace }}/../codeql-swift-derived-data + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Switch to Xcode 26.2 + run: sudo xcode-select --switch /Applications/Xcode_26.2.app + + - name: Setup iOS simulator + run: | + xcrun simctl delete all + CURRENT_SIMULATOR_UUID=$(xcrun simctl create CodeQL 'iPhone 17 Pro') + echo "CURRENT_SIMULATOR_UUID=$CURRENT_SIMULATOR_UUID" >> "$GITHUB_ENV" + + - name: Prepare Swift modules + run: .github/codeql/prepare_swift_modules + + - name: Initialize CodeQL + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + languages: swift + build-mode: manual + config-file: ./.github/codeql/codeql-config.yml + + - name: Type-check Swift modules for CodeQL + run: .github/codeql/build_swift --typecheck + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + category: /language:swift/platform:swift + output: sarif-results + upload: failure-only + + - name: Filter Swift results to shipped sources + uses: advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0 # v1.1 + with: + patterns: | + -** + +platforms/swift/Sources/**/* + +protocol/languages/swift/Sources/**/* + +telemetry/languages/swift/Sources/**/* + input: sarif-results/swift.sarif + output: sarif-results/swift.sarif + + - name: Upload Swift results + uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + sarif_file: sarif-results/swift.sarif + + analyze-react-native-ios: + name: Analyze (react-native-ios) + needs: native-changes + if: needs.native-changes.outputs.reactNativeIos == 'true' + runs-on: ${{ vars.MACOS_RUNNER }} + timeout-minutes: 25 + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/platforms/react-native/sample/Gemfile + DERIVED_DATA_PATH: ${{ github.workspace }}/../codeql-react-native-ios-derived-data + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Switch to Xcode 26.2 + run: sudo xcode-select --switch /Applications/Xcode_26.2.app + + - name: Setup iOS simulator + run: | + xcrun simctl delete all + CURRENT_SIMULATOR_UUID=$(xcrun simctl create CodeQL 'iPhone 17 Pro') + echo "CURRENT_SIMULATOR_UUID=$CURRENT_SIMULATOR_UUID" >> "$GITHUB_ENV" + + - name: Setup Node.js, pnpm, and React Native dependencies + uses: ./.github/actions/setup + with: + node-version-file: platforms/react-native/package.json + cache-dependency-path: platforms/react-native/pnpm-lock.yaml + package-json-file: platforms/react-native/package.json + working-directory: platforms/react-native + + - name: Setup Ruby + uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0 + with: + ruby-version: .ruby-version + bundler-cache: true + working-directory: platforms/react-native/sample + + - uses: ./.github/actions/setup-mint + + - name: Generate React Native integration project + run: platforms/swift/Scripts/generate_xcode_projects --spec ../react-native/test/rct-integration-app/project.yml + + - name: Verify iOS lockfile uses published native SDK + run: platforms/react-native/scripts/check_published_podfile_lock platforms/react-native/test/rct-integration-app/Podfile.lock + + - name: Cache CocoaPods + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: platforms/react-native/test/rct-integration-app/Pods + key: ${{ runner.os }}-codeql-react-native-ios-pods-${{ hashFiles('platforms/react-native/test/rct-integration-app/Podfile.lock', 'platforms/react-native/sample/Gemfile', 'platforms/react-native/sample/Gemfile.lock', 'platforms/react-native/sample/package.json', 'platforms/react-native/modules/@shopify/checkout-kit-react-native/package.json', 'platforms/react-native/modules/@shopify/checkout-kit-react-native/RNShopifyCheckoutKit.podspec', 'platforms/react-native/package.json', 'platforms/react-native/pnpm-lock.yaml') }} + + - name: Install React Native CocoaPods + working-directory: platforms/react-native/test/rct-integration-app + run: bundle exec pod install --deployment + + - name: Build published Swift SDK dependency + working-directory: platforms/react-native/test/rct-integration-app + run: | + set -o pipefail + xcodebuild build \ + -project Pods/Pods.xcodeproj \ + -scheme ShopifyCheckoutKit \ + -sdk iphonesimulator \ + -destination "id=$CURRENT_SIMULATOR_UUID" \ + -derivedDataPath "$DERIVED_DATA_PATH" \ + -skipPackagePluginValidation \ + -disableAutomaticPackageResolution \ + CODE_SIGNING_ALLOWED=NO \ + COMPILER_INDEX_STORE_ENABLE=NO | xcbeautify --renderer github-actions + + - name: Validate React Native Swift wrapper module + run: .github/codeql/build_react_native_ios + + - name: Initialize CodeQL + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + languages: swift + build-mode: manual + config-file: ./.github/codeql/codeql-config.yml + + - name: Build React Native Swift wrapper for CodeQL + run: .github/codeql/build_react_native_ios + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + category: /language:swift/platform:react-native-ios + output: sarif-results + upload: failure-only + + - name: Filter React Native iOS results to shipped sources + uses: advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0 # v1.1 + with: + patterns: | + -** + +platforms/react-native/modules/@shopify/checkout-kit-react-native/ios/**/* + input: sarif-results/swift.sarif + output: sarif-results/swift.sarif + + - name: Upload React Native iOS results + uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + sarif_file: sarif-results/swift.sarif