diff --git a/.github/workflows/api-validation.yml b/.github/workflows/api-validation.yml index 7f023d44..1e56e81c 100644 --- a/.github/workflows/api-validation.yml +++ b/.github/workflows/api-validation.yml @@ -1,6 +1,13 @@ name: Public API change Validation -on: [pull_request] +on: + pull_request: + paths-ignore: + - '**/*.md' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: validate-api: @@ -18,4 +25,4 @@ jobs: run: npm run prepare - name: Validate API - run: npx api-extractor run \ No newline at end of file + run: npx api-extractor run diff --git a/.github/workflows/build-sample-app.yml b/.github/workflows/build-sample-app.yml index b175274b..cc9ae0c4 100644 --- a/.github/workflows/build-sample-app.yml +++ b/.github/workflows/build-sample-app.yml @@ -32,6 +32,11 @@ on: description: "Name of the platform in all upper case (IOS or ANDROID)" required: true type: string + should_distribute: + description: "Whether to sign and publish the sample app" + required: false + default: true + type: boolean outputs: sdk_version_name: @@ -222,10 +227,13 @@ jobs: if: ${{ inputs.platform == 'ios' }} uses: actions/cache@v4 with: - path: example/Pods - key: ${{ runner.os }}-${{ inputs.app_name }}-Pods-${{ github.ref }} + path: | + ~/Library/Caches/CocoaPods + ~/.cocoapods + example/ios/Pods + key: ${{ runner.os }}-${{ inputs.app_name }}-Pods-${{ hashFiles('package.json', 'package-lock.json', 'example/package.json', 'example/package-lock.json', 'example/ios/Podfile', 'example/Gemfile.lock', 'customerio-reactnative.podspec', 'customerio-reactnative-richpush.podspec') }} restore-keys: | - ${{ runner.os }}-${{ inputs.app_name }}-Pods + ${{ runner.os }}-${{ inputs.app_name }}-Pods- - name: Install dependencies to build SDK run: npm ci @@ -302,6 +310,7 @@ jobs: uses: customerio/mobile-ci-tools/github-actions/ios/setup-ios/v1@main - name: Build and upload ${{ inputs.platform_name }} ${{ inputs.app_name }} sample app via Fastlane + if: ${{ inputs.should_distribute }} id: build_app uses: maierj/fastlane-action@5a3b971aaa26776459bb26894d6c1a1a84a311a7 # v3.1.0 with: @@ -314,8 +323,27 @@ jobs: FIREBASE_APP_DISTRIBUTION_SERVICE_ACCOUNT_CREDS_B64: ${{ secrets.FIREBASE_APP_DISTRIBUTION_SERVICE_ACCOUNT_CREDS_B64 }} continue-on-error: true + - name: Compile ${{ inputs.platform_name }} ${{ inputs.app_name }} sample app (verification only) + if: ${{ !inputs.should_distribute }} + id: verify_build + shell: bash + run: | + set -euo pipefail + if [[ "${{ inputs.platform }}" == 'android' ]]; then + ./android/gradlew -p android :app:assembleRelease + else + xcodebuild \ + -workspace ios/SampleApp.xcworkspace \ + -scheme SampleApp \ + -configuration Release \ + -sdk iphonesimulator \ + -destination 'generic/platform=iOS Simulator' \ + CODE_SIGNING_ALLOWED=NO \ + build + fi + - name: Send slack notification for ${{ inputs.platform_name }} ${{ inputs.app_name }} sample app builds - if: ${{ always() && env.IS_PRIMARY_APP == 'true' }} + if: ${{ always() && inputs.should_distribute && env.IS_PRIMARY_APP == 'true' }} uses: customerio/mobile-ci-tools/github-actions/slack-notify-sample-app/v1@main with: build_status: ${{ steps.build_app.outcome }} @@ -332,11 +360,18 @@ jobs: slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }} - name: Check build statuses and mark failure + if: ${{ always() }} + env: + SHOULD_DISTRIBUTE: ${{ inputs.should_distribute }} + DISTRIBUTION_OUTCOME: ${{ steps.build_app.outcome }} + VERIFICATION_OUTCOME: ${{ steps.verify_build.outcome }} run: | - FAILED_BUILDS=() - [ "${{ steps.build_app.outcome }}" != "success" ] && FAILED_BUILDS+=("(${{ inputs.platform_name }})") - - if [ ${#FAILED_BUILDS[@]} -ne 0 ]; then - echo "Build failed for: ${FAILED_BUILDS[*]}" + if [[ "$SHOULD_DISTRIBUTE" == 'true' ]]; then + outcome="$DISTRIBUTION_OUTCOME" + else + outcome="$VERIFICATION_OUTCOME" + fi + if [[ "$outcome" != 'success' ]]; then + echo "${{ inputs.platform_name }} build failed with outcome: $outcome" exit 1 fi diff --git a/.github/workflows/build-test-sample-apps.yml b/.github/workflows/build-test-sample-apps.yml index 77a4ae22..4bd2100a 100644 --- a/.github/workflows/build-test-sample-apps.yml +++ b/.github/workflows/build-test-sample-apps.yml @@ -1,18 +1,44 @@ name: Publish Test Sample Apps on: - pull_request: # build sample apps for every commit pushed to an open pull request (including drafts) + pull_request: + types: [opened, synchronize, reopened, labeled] + paths-ignore: + - '**/*.md' workflow_dispatch: push: - branches: [main, feature/*] + branches: [main] concurrency: # cancel previous workflow run if one exists. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }}-${{ (github.event.action == 'labeled' && github.event.label.name != 'ci:full') && github.run_id || 'validation' }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + prepare: + name: Select sample app lane + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.select.outputs.matrix }} + steps: + - name: Select verification or distribution matrix + id: select + shell: bash + env: + EVENT_NAME: ${{ github.event_name }} + FULL_PR: ${{ contains(github.event.pull_request.labels.*.name, 'ci:full') && github.event.pull_request.head.repo.full_name == github.repository }} + run: | + if [[ "$EVENT_NAME" == 'pull_request' && "$FULL_PR" != 'true' ]]; then + echo 'matrix=[{"name":"APN","cio-workspace-name":"Mobile: React Native","platform":"ios","platform_name":"iOS","platform_name_upper":"IOS","should_distribute":false},{"name":"APN","cio-workspace-name":"Mobile: React Native","platform":"android","platform_name":"Android","platform_name_upper":"ANDROID","should_distribute":false}]' >> "$GITHUB_OUTPUT" + else + echo 'matrix=[{"name":"APN","cio-workspace-name":"Mobile: React Native","platform":"ios","platform_name":"iOS","platform_name_upper":"IOS","should_distribute":true},{"name":"FCM","cio-workspace-name":"Mobile: xReact Native FCM workspace","platform":"ios","platform_name":"iOS","platform_name_upper":"IOS","should_distribute":true},{"name":"APN","cio-workspace-name":"Mobile: React Native","platform":"android","platform_name":"Android","platform_name_upper":"ANDROID","should_distribute":true}]' >> "$GITHUB_OUTPUT" + fi + update-pr-comment: - if: ${{ github.event_name == 'pull_request' }} + if: >- + (github.event.action != 'labeled' || github.event.label.name == 'ci:full') && + github.event_name == 'pull_request' && + contains(github.event.pull_request.labels.*.name, 'ci:full') && + github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest permissions: pull-requests: write # to be able to comment on PR @@ -40,33 +66,19 @@ jobs: Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request. --- - ${{ steps.build.outputs.build-log }} + Builds are in progress. This comment will be updated when they finish. edit-mode: replace # replace the existing comment with new content since we are creating new builds build-sample-apps: - if: ${{ always() }} # do not skip running this step if update-pr-comment does not run - needs: [update-pr-comment] # wait for PR comment to be created saying new builds are being made. + if: >- + always() && + needs.prepare.result == 'success' && + (github.event.action != 'labeled' || github.event.label.name == 'ci:full') + needs: [prepare, update-pr-comment] strategy: fail-fast: false # if one sample app fails to build, let the other sample apps continue to build and not cancel them. matrix: # Use a matrix allowing us to build multiple apps in parallel. Just add an entry to the matrix and it will build! - sample-app: - # List all sample apps you want to have compiled. - # List item is name of directory inside of "Apps" directory for the corresponding app to compile. - - name: 'APN' - cio-workspace-name: 'Mobile: React Native' - platform: 'ios' - platform_name: 'iOS' - platform_name_upper: 'IOS' - - name: 'FCM' - cio-workspace-name: 'Mobile: xReact Native FCM workspace' - platform: 'ios' - platform_name: 'iOS' - platform_name_upper: 'IOS' - - name: 'APN' - cio-workspace-name: 'Mobile: React Native' - platform: 'android' - platform_name: 'Android' - platform_name_upper: 'ANDROID' + sample-app: ${{ fromJSON(needs.prepare.outputs.matrix) }} name: Building the ${{ matrix.sample-app.platform_name }} ${{ matrix.sample-app.name }} sample app uses: ./.github/workflows/build-sample-app.yml @@ -76,12 +88,17 @@ jobs: platform: ${{ matrix.sample-app.platform }} platform_name: ${{ matrix.sample-app.platform_name }} platform_name_upper: ${{ matrix.sample-app.platform_name_upper }} + should_distribute: ${{ matrix.sample-app.should_distribute }} secrets: inherit # Update PR comment with build information update-pr-comment-with-status: - if: ${{ github.event_name == 'pull_request' }} + if: >- + (github.event.action != 'labeled' || github.event.label.name == 'ci:full') && + github.event_name == 'pull_request' && + contains(github.event.pull_request.labels.*.name, 'ci:full') && + github.event.pull_request.head.repo.full_name == github.repository needs: [build-sample-apps, update-pr-comment] runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/pr-helper.yml b/.github/workflows/pr-helper.yml index 114ecdc7..ed43e73a 100644 --- a/.github/workflows/pr-helper.yml +++ b/.github/workflows/pr-helper.yml @@ -2,7 +2,7 @@ name: Semantic PR helper on: pull_request: - types: [opened, reopened, edited, synchronize, labeled] + types: [opened, reopened, edited, synchronize] jobs: lint-pr-title: diff --git a/.github/workflows/react-native-scene-e2e.yml b/.github/workflows/react-native-scene-e2e.yml index 6bf4db17..62400dec 100644 --- a/.github/workflows/react-native-scene-e2e.yml +++ b/.github/workflows/react-native-scene-e2e.yml @@ -2,44 +2,7 @@ name: React Native scene routing E2E on: pull_request: - paths: - - '.github/workflows/react-native-scene-e2e.yml' - - '.maestro/fixtures/customerio_scene_cold.apns' - - '.maestro/fixtures/customerio_scene_declined.apns' - - '.maestro/fixtures/customerio_scene_warm.apns' - - '.maestro/fixtures/react-native-scene/**' - - '.maestro/run_scene_push.sh' - - '.maestro/scene_push_open.yaml' - - '.maestro/scene_push_declined.yaml' - - '.maestro/scene_push_prepare.yaml' - - '.maestro/scene_push_warm.yaml' - - '.maestro/scene_url_open.yaml' - - 'src/customerio-cdp.ts' - - 'src/customerio-push.ts' - - 'src/index.ts' - - 'src/native-logger-listener.ts' - - 'src/specs/modules/NativeCustomerIO.ts' - - 'src/specs/modules/NativeCustomerIOMessagingPush.ts' - - 'src/types/data-pipelines.ts' - - 'src/types/index.ts' - - 'src/types/internal.ts' - - 'src/types/push.ts' - - 'src/utils/native-bridge.ts' - - 'src/utils/param-validation.ts' - - 'ios/wrappers/CustomerIOReactNativeDeepLinkRouter.swift' - - 'ios/wrappers/CustomerIOReactNativeDeepLinkRequestStore.swift' - - 'ios/wrappers/NativeCustomerIO.swift' - - 'ios/wrappers/NativeCustomerIO.mm' - - 'ios/wrappers/liveactivities/NativeLiveActivities.swift' - - 'ios/wrappers/push/**' - - 'ios/wrappers/utils/CioConfigUtils.swift' - - 'ios/wrappers/utils/CioConstants.swift' - - 'ios/wrappers/CustomerioReactnative-Bridging-Header.h' - - 'ios/cocoapods_deployment_target.rb' - - 'customerio-reactnative.podspec' - - 'scripts/test_ios_deep_link_request_store.swift' - - 'package.json' - - 'package-lock.json' + types: [opened, synchronize, reopened, labeled] schedule: - cron: '47 7 * * *' workflow_dispatch: @@ -48,13 +11,17 @@ permissions: contents: read concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}-${{ (github.event.action == 'labeled' && github.event.label.name != 'ci:full') && github.run_id || 'validation' }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: route-notifications: name: RN scene notification routing on Xcode 27 - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + if: >- + (github.event.action != 'labeled' || github.event.label.name == 'ci:full') && + (github.event_name != 'pull_request' || + (contains(github.event.pull_request.labels.*.name, 'ci:full') && + github.event.pull_request.head.repo.full_name == github.repository)) runs-on: xcode-27 timeout-minutes: 60 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5a1df8c0..c4b77cb3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,15 @@ name: Test -on: [push, pull_request] +on: + push: + branches: [main] + pull_request: + paths-ignore: + - '**/*.md' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: test-deploy: @@ -11,6 +20,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: '24' + cache: 'npm' - run: npm ci - name: Compile