fix(perps): use live price subscription for header display in trade/c… #8131
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Apps and Run Performance E2E Tests | |
| # This workflow runs performance E2E tests every 3 hours during weekdays (Monday-Friday) | |
| # Schedule: Every 3 hours at the top of the hour (00:00, 03:00, 06:00, 09:00, 12:00, 15:00, 18:00, 21:00) | |
| # Days: Monday (1) through Friday (6) | |
| on: | |
| schedule: | |
| - cron: '0 */3 * * 1-6' | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| description: | |
| description: 'Optional description for this test run' | |
| required: false | |
| type: string | |
| sentry_target: | |
| description: 'Sentry target for performance events (test or real)' | |
| required: false | |
| type: choice | |
| options: | |
| - test | |
| - real | |
| default: test | |
| browserstack_app_url_android_onboarding: | |
| description: 'BrowserStack Android Onboarding App URL (bs://...)' | |
| required: false | |
| type: string | |
| browserstack_app_url_ios_onboarding: | |
| description: 'BrowserStack iOS Onboarding App URL (bs://...)' | |
| required: false | |
| type: string | |
| browserstack_app_url_android_imported_wallet: | |
| description: 'BrowserStack Android Imported Wallet App URL (bs://...)' | |
| required: false | |
| type: string | |
| browserstack_app_url_ios_imported_wallet: | |
| description: 'BrowserStack iOS Imported Wallet App URL (bs://...)' | |
| required: false | |
| type: string | |
| performance_tags: | |
| description: 'JSON array of performance tags (e.g. ["@PerformanceLogin","@PerformanceSwaps"]). Omit/blank = run all. "[]" = skip all (PR with no relevant changes).' | |
| required: false | |
| type: string | |
| default: '' | |
| workflow_call: | |
| inputs: | |
| description: | |
| description: 'Optional description for this test run' | |
| required: false | |
| type: string | |
| sentry_target: | |
| description: 'Sentry target for performance events (test or real)' | |
| required: false | |
| type: string | |
| default: test | |
| browserstack_app_url_android_onboarding: | |
| description: 'BrowserStack Android Onboarding App URL (bs://...)' | |
| required: false | |
| type: string | |
| browserstack_app_url_ios_onboarding: | |
| description: 'BrowserStack iOS Onboarding App URL (bs://...)' | |
| required: false | |
| type: string | |
| browserstack_app_url_android_imported_wallet: | |
| description: 'BrowserStack Android Imported Wallet App URL (bs://...)' | |
| required: false | |
| type: string | |
| browserstack_app_url_ios_imported_wallet: | |
| description: 'BrowserStack iOS Imported Wallet App URL (bs://...)' | |
| required: false | |
| type: string | |
| branch_name: | |
| description: 'Branch name to use for build names (defaults to auto-detection)' | |
| required: false | |
| type: string | |
| build_variant: | |
| description: 'BrowserStack build profile (e2e = build-e2e, works on feature branches; rc = build-rc, release branches only; exp = experimental)' | |
| required: false | |
| type: string | |
| default: 'e2e' | |
| performance_tags: | |
| description: 'JSON array of performance tags (e.g. ["@PerformanceLogin","@PerformanceSwaps"]). Omit/blank = run all. "[]" = skip all (PR with no relevant changes).' | |
| required: false | |
| type: string | |
| default: '' | |
| performance_tags_reasoning: | |
| description: 'Human-readable explanation of why performance tags were selected' | |
| required: false | |
| type: string | |
| default: '' | |
| pr_number: | |
| description: 'Pull request number for posting results as a PR comment (workflow_call only)' | |
| required: false | |
| type: string | |
| default: '' | |
| reuse_main_builds: | |
| description: >- | |
| When true, skip fresh Android BrowserStack builds and reuse the latest | |
| uploaded apps from main-branch CI instead. | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write | |
| id-token: write | |
| actions: write | |
| pull-requests: write | |
| concurrency: | |
| # Include build_variant so e2e, experimental (exp), and release/direct (rc) don't share the same | |
| # queue — avoids "Build Apps" (direct/release) and e2e/experimental runs canceling each other. | |
| # Note: GitHub allows at most 1 running + 1 pending per group; a 3rd run cancels the pending one. | |
| group: performance-e2e-${{ github.ref }}-${{ github.event_name }}-${{ inputs.build_variant || 'e2e' }} | |
| # Do not cancel in-progress runs; pending runs can still be replaced by a newer trigger. | |
| cancel-in-progress: false | |
| env: | |
| BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} | |
| BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} | |
| MM_TEST_ACCOUNT_SRP: ${{ secrets.MM_TEST_ACCOUNT_SRP }} | |
| TEST_SRP_1: ${{ secrets.TEST_SRP_1 }} | |
| TEST_SRP_2: ${{ secrets.TEST_SRP_2 }} | |
| TEST_SRP_3: ${{ secrets.TEST_SRP_3 }} | |
| TEST_SRP_4: ${{ secrets.TEST_SRP_4 }} | |
| E2E_PASSWORD: ${{ secrets.E2E_PASSWORD }} | |
| DISABLE_VIDEO_DOWNLOAD: true | |
| jobs: | |
| determine-branch-name: | |
| name: Determine Branch Name | |
| runs-on: ubuntu-latest | |
| outputs: | |
| branch_name: ${{ steps.get-branch.outputs.branch_name }} | |
| steps: | |
| - name: Get correct branch name | |
| id: get-branch | |
| env: | |
| INPUT_BRANCH: ${{ inputs.branch_name }} | |
| HEAD_REF: ${{ github.head_ref }} | |
| REF_NAME: ${{ github.ref_name }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| run: | | |
| # Determine the correct branch name for all trigger scenarios: | |
| # - workflow_call (from ci.yml): uses INPUT_BRANCH (github.head_ref for PRs, github.ref_name for push) | |
| # - pull_request: uses HEAD_REF (source branch, e.g., "feature-branch") | |
| # - schedule: uses REF_NAME (typically "main") | |
| # - workflow_dispatch: uses INPUT_BRANCH if provided, otherwise REF_NAME | |
| # Priority: explicit input > PR head_ref > ref_name | |
| if [ -n "$INPUT_BRANCH" ]; then | |
| BRANCH_NAME="$INPUT_BRANCH" | |
| echo "Using explicit input: $BRANCH_NAME" | |
| elif [ "$EVENT_NAME" = "pull_request" ] && [ -n "$HEAD_REF" ]; then | |
| BRANCH_NAME="$HEAD_REF" | |
| echo "Using PR source branch: $BRANCH_NAME" | |
| else | |
| BRANCH_NAME="$REF_NAME" | |
| echo "Using ref_name: $BRANCH_NAME" | |
| fi | |
| echo "branch_name=$BRANCH_NAME" >> "$GITHUB_OUTPUT" | |
| echo "Branch: $BRANCH_NAME" | |
| read-device-matrix: | |
| name: Read Device Matrix | |
| runs-on: ubuntu-latest | |
| needs: [determine-branch-name] | |
| outputs: | |
| android_matrix: ${{ steps.read-matrix.outputs.android_matrix }} | |
| android_mm_connect_matrix: ${{ steps.read-matrix.outputs.android_mm_connect_matrix }} | |
| ios_matrix: ${{ steps.read-matrix.outputs.ios_matrix }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Select Devices | |
| id: read-matrix | |
| env: | |
| BRANCH_NAME: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| PR_NUMBER: ${{ inputs.pr_number }} | |
| run: | | |
| FILE="tests/performance/device-matrix.json" | |
| # PRs: run the AI-selected performance tests on Android low profile only. | |
| # Pushes keep the previous low-device behavior to control cost and flakes. | |
| # Schedule and workflow_dispatch use the full device matrix. | |
| if [ -n "$PR_NUMBER" ]; then | |
| ANDROID_MATRIX=$(jq '[.android_devices[] | select(.category == "low")]' "$FILE") | |
| ANDROID_MM_CONNECT_MATRIX="$ANDROID_MATRIX" | |
| IOS_MATRIX='[]' | |
| echo "PR mode: Android low category devices only (PR: $PR_NUMBER, branch: $BRANCH_NAME)" | |
| elif [ "${{ github.event_name }}" = "push" ]; then | |
| ANDROID_MATRIX=$(jq '[.android_devices[] | select(.category == "low")]' "$FILE") | |
| ANDROID_MM_CONNECT_MATRIX=$(jq '[.android_devices[] | select(.name | contains("Samsung"))]' "$FILE") | |
| IOS_MATRIX=$(jq '[.ios_devices[] | select(.category == "low")]' "$FILE") | |
| echo "Push mode: low category devices only (event: ${{ github.event_name }}, branch: $BRANCH_NAME)" | |
| else | |
| ANDROID_MATRIX=$(jq ".android_devices" "$FILE") | |
| ANDROID_MM_CONNECT_MATRIX=$(jq '[.android_devices[] | select(.name | contains("Samsung"))]' "$FILE") | |
| IOS_MATRIX=$(jq ".ios_devices" "$FILE") | |
| echo "Full mode: All devices (event: ${{ github.event_name }}, branch: $BRANCH_NAME)" | |
| fi | |
| { | |
| echo "android_matrix<<EOF" | |
| echo "$ANDROID_MATRIX" | |
| echo "EOF" | |
| echo "android_mm_connect_matrix<<EOF" | |
| echo "$ANDROID_MM_CONNECT_MATRIX" | |
| echo "EOF" | |
| echo "ios_matrix<<EOF" | |
| echo "$IOS_MATRIX" | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| echo "Selected: $(echo "$ANDROID_MATRIX" | jq length) Android, $(echo "$IOS_MATRIX" | jq length) iOS" | |
| echo "Selected for Android MM-Connect: $(echo "$ANDROID_MM_CONNECT_MATRIX" | jq length)" | |
| set-build-names: | |
| name: Set Unified BrowserStack Build Names | |
| runs-on: ubuntu-latest | |
| needs: [determine-branch-name] | |
| outputs: | |
| android_build_name: ${{ steps.set-builds.outputs.android_build_name }} | |
| ios_build_name: ${{ steps.set-builds.outputs.ios_build_name }} | |
| steps: | |
| - name: Set unified build names | |
| id: set-builds | |
| run: | | |
| BRANCH_NAME="${{ needs.determine-branch-name.outputs.branch_name }}" | |
| echo "android_build_name=Android-Performance-$BRANCH_NAME-Branch" >> "$GITHUB_OUTPUT" | |
| echo "ios_build_name=iOS-Performance-$BRANCH_NAME-Branch" >> "$GITHUB_OUTPUT" | |
| echo "Set unified build names:" | |
| echo " Android: Android-Performance-$BRANCH_NAME-Branch" | |
| echo " iOS: iOS-Performance-$BRANCH_NAME-Branch" | |
| compute-test-selection: | |
| name: Compute Performance Test Selection | |
| runs-on: ubuntu-latest | |
| outputs: | |
| run_tests: ${{ steps.map.outputs.run_tests }} | |
| grep_pattern: ${{ steps.map.outputs.grep_pattern }} | |
| steps: | |
| - name: Map performance tags to grep pattern | |
| id: map | |
| env: | |
| PERF_REASONING: ${{ inputs.performance_tags_reasoning }} | |
| run: | | |
| TAGS='${{ inputs.performance_tags }}' | |
| REASONING="$PERF_REASONING" | |
| # No input (blank) → schedule/dispatch: run all tests with no grep filter | |
| if [[ -z "$TAGS" ]]; then | |
| echo "run_tests=true" >> "$GITHUB_OUTPUT" | |
| echo "grep_pattern=" >> "$GITHUB_OUTPUT" | |
| echo "▶️ Running all performance tests (schedule/dispatch mode — no tag filter)" | |
| exit 0 | |
| fi | |
| # '[]' → PR with no performance-relevant changes: skip all tests | |
| if [[ "$TAGS" == "[]" ]]; then | |
| echo "run_tests=false" >> "$GITHUB_OUTPUT" | |
| echo "grep_pattern=" >> "$GITHUB_OUTPUT" | |
| echo "⏭️ Skipping performance tests — no performance-relevant changes detected in this PR" | |
| if [[ -n "$REASONING" ]]; then | |
| echo " Reasoning: $REASONING" | |
| fi | |
| exit 0 | |
| fi | |
| # Build OR-pattern for playwright --grep (e.g. "@PerformanceSwaps|@PerformanceLogin") | |
| # Playwright matches against the full test name (describe + test title), so each tag | |
| # selects only the individual tests that use it in their describe block. | |
| GREP=$(echo "$TAGS" | jq -r 'join("|")') | |
| echo "run_tests=true" >> "$GITHUB_OUTPUT" | |
| echo "grep_pattern=$GREP" >> "$GITHUB_OUTPUT" | |
| echo "⚡ Performance test selection:" | |
| echo " Tags: $TAGS" | |
| echo " Grep pattern: $GREP" | |
| if [[ -n "$REASONING" ]]; then | |
| echo " Reasoning: $REASONING" | |
| fi | |
| resolve-main-browserstack-urls: | |
| name: Resolve main-branch BrowserStack Android apps | |
| runs-on: ubuntu-latest | |
| if: >- | |
| inputs.reuse_main_builds && | |
| !inputs.browserstack_app_url_android_onboarding && | |
| !inputs.browserstack_app_url_android_imported_wallet | |
| outputs: | |
| found: ${{ steps.resolve.outputs.found }} | |
| with-srp-browserstack-url: ${{ steps.resolve.outputs.with-srp-browserstack-url }} | |
| without-srp-browserstack-url: ${{ steps.resolve.outputs.without-srp-browserstack-url }} | |
| with-srp-version: ${{ steps.resolve.outputs.with-srp-version }} | |
| without-srp-version: ${{ steps.resolve.outputs.without-srp-version }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| .github/scripts/resolve-main-browserstack-apps.cjs | |
| .github/scripts/browserstack-app-validation.cjs | |
| sparse-checkout-cone-mode: false | |
| - name: Resolve latest main BrowserStack apps | |
| id: resolve | |
| run: node .github/scripts/resolve-main-browserstack-apps.cjs | |
| env: | |
| BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} | |
| BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} | |
| trigger-android-dual-versions: | |
| name: Trigger Android Dual Versions and Extract BrowserStack URLs | |
| uses: ./.github/workflows/build-android-upload-to-browserstack.yml | |
| needs: [determine-branch-name, resolve-main-browserstack-urls] | |
| # Build/upload when not reusing main, or when main reuse lookup found nothing. | |
| if: >- | |
| always() && | |
| !cancelled() && | |
| (needs.resolve-main-browserstack-urls.result == 'skipped' || needs.resolve-main-browserstack-urls.result == 'success') && | |
| (!inputs.browserstack_app_url_android_onboarding && !inputs.browserstack_app_url_android_imported_wallet) && | |
| ( | |
| !inputs.reuse_main_builds || | |
| needs.resolve-main-browserstack-urls.outputs.found != 'true' | |
| ) | |
| with: | |
| branch_name: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| build_variant: ${{ inputs.build_variant || 'e2e' }} | |
| secrets: inherit | |
| trigger-ios-dual-versions: | |
| name: Trigger iOS Dual Versions and Extract BrowserStack URLs | |
| uses: ./.github/workflows/build-ios-upload-to-browserstack.yml | |
| needs: [determine-branch-name] | |
| if: false # temporarily disabled — iOS tests not yet active | |
| # if: (!inputs.browserstack_app_url_ios_onboarding && !inputs.browserstack_app_url_ios_imported_wallet) | |
| with: | |
| branch_name: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| build_variant: ${{ inputs.build_variant || 'e2e' }} | |
| secrets: inherit | |
| # ============================================================================= | |
| # PHASE 1: ONBOARDING TESTS (Run First) | |
| # ============================================================================= | |
| run-android-onboarding-tests: | |
| name: Run Android Onboarding Tests | |
| uses: ./.github/workflows/performance-test-runner.yml | |
| needs: | |
| [ | |
| read-device-matrix, | |
| trigger-android-dual-versions, | |
| resolve-main-browserstack-urls, | |
| set-build-names, | |
| determine-branch-name, | |
| compute-test-selection, | |
| ] | |
| if: >- | |
| always() && !failure() && !cancelled() && | |
| needs.compute-test-selection.outputs.run_tests == 'true' && | |
| ( | |
| needs.trigger-android-dual-versions.result == 'skipped' || | |
| needs.trigger-android-dual-versions.result == 'success' | |
| ) && | |
| ( | |
| needs.resolve-main-browserstack-urls.result == 'skipped' || | |
| needs.resolve-main-browserstack-urls.result == 'success' | |
| ) && | |
| ( | |
| inputs.browserstack_app_url_android_onboarding != '' || | |
| needs.trigger-android-dual-versions.outputs.without-srp-browserstack-url != '' || | |
| needs.resolve-main-browserstack-urls.outputs.without-srp-browserstack-url != '' | |
| ) | |
| with: | |
| platform: android | |
| build_type: onboarding | |
| sentry_target: ${{ inputs.sentry_target || 'test' }} | |
| build_variant: ${{ inputs.build_variant || 'e2e' }} | |
| device_matrix: ${{ needs.read-device-matrix.outputs.android_matrix }} | |
| browserstack_app_url: ${{ needs.resolve-main-browserstack-urls.outputs.without-srp-browserstack-url || needs.trigger-android-dual-versions.outputs.without-srp-browserstack-url || inputs.browserstack_app_url_android_onboarding }} | |
| app_version: ${{ needs.resolve-main-browserstack-urls.outputs.without-srp-version || needs.trigger-android-dual-versions.outputs.without-srp-version || 'Manual-Input' }} | |
| branch_name: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| browserstack_build_name: ${{ needs.set-build-names.outputs.android_build_name }} | |
| grep_tags: ${{ needs.compute-test-selection.outputs.grep_pattern }} | |
| secrets: inherit | |
| run-ios-onboarding-tests: | |
| name: Run iOS Onboarding Tests | |
| uses: ./.github/workflows/performance-test-runner.yml | |
| needs: | |
| [ | |
| read-device-matrix, | |
| trigger-ios-dual-versions, | |
| set-build-names, | |
| determine-branch-name, | |
| compute-test-selection, | |
| ] | |
| if: always() && !failure() && !cancelled() && needs.compute-test-selection.outputs.run_tests == 'true' && (needs.trigger-ios-dual-versions.result == 'skipped' || needs.trigger-ios-dual-versions.result == 'success') && (inputs.browserstack_app_url_ios_onboarding != '' || needs.trigger-ios-dual-versions.outputs.without-srp-browserstack-url != '') | |
| with: | |
| platform: ios | |
| build_type: onboarding | |
| sentry_target: ${{ inputs.sentry_target || 'test' }} | |
| build_variant: ${{ inputs.build_variant || 'e2e' }} | |
| device_matrix: ${{ needs.read-device-matrix.outputs.ios_matrix }} | |
| browserstack_app_url: ${{ needs.trigger-ios-dual-versions.outputs.without-srp-browserstack-url || inputs.browserstack_app_url_ios_onboarding }} | |
| app_version: ${{ needs.trigger-ios-dual-versions.outputs.without-srp-version || 'Manual-Input' }} | |
| branch_name: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| browserstack_build_name: ${{ needs.set-build-names.outputs.ios_build_name }} | |
| grep_tags: ${{ needs.compute-test-selection.outputs.grep_pattern }} | |
| secrets: inherit | |
| # ============================================================================= | |
| # PHASE 2: IMPORTED WALLET TESTS (Run After Onboarding Complete) | |
| # ============================================================================= | |
| wait-for-onboarding-completion: | |
| name: Wait for Onboarding Completion | |
| runs-on: ubuntu-latest | |
| needs: [run-android-onboarding-tests, run-ios-onboarding-tests] | |
| if: always() | |
| steps: | |
| - name: Wait for onboarding tests to complete | |
| run: | | |
| echo "Onboarding tests have completed (success or failure)" | |
| echo "Proceeding with imported wallet tests..." | |
| run-android-imported-wallet-tests: | |
| name: Run Android Imported Wallet Tests | |
| uses: ./.github/workflows/performance-test-runner.yml | |
| needs: | |
| [ | |
| read-device-matrix, | |
| trigger-android-dual-versions, | |
| resolve-main-browserstack-urls, | |
| wait-for-onboarding-completion, | |
| set-build-names, | |
| determine-branch-name, | |
| compute-test-selection, | |
| ] | |
| if: >- | |
| always() && !cancelled() && | |
| needs.compute-test-selection.outputs.run_tests == 'true' && | |
| ( | |
| needs.trigger-android-dual-versions.result == 'skipped' || | |
| needs.trigger-android-dual-versions.result == 'success' | |
| ) && | |
| ( | |
| needs.resolve-main-browserstack-urls.result == 'skipped' || | |
| needs.resolve-main-browserstack-urls.result == 'success' | |
| ) && | |
| ( | |
| inputs.browserstack_app_url_android_imported_wallet != '' || | |
| needs.trigger-android-dual-versions.outputs.with-srp-browserstack-url != '' || | |
| needs.resolve-main-browserstack-urls.outputs.with-srp-browserstack-url != '' | |
| ) | |
| with: | |
| platform: android | |
| build_type: imported-wallet | |
| sentry_target: ${{ inputs.sentry_target || 'test' }} | |
| build_variant: ${{ inputs.build_variant || 'e2e' }} | |
| device_matrix: ${{ needs.read-device-matrix.outputs.android_matrix }} | |
| browserstack_app_url: ${{ needs.resolve-main-browserstack-urls.outputs.with-srp-browserstack-url || needs.trigger-android-dual-versions.outputs.with-srp-browserstack-url || inputs.browserstack_app_url_android_imported_wallet }} | |
| app_version: ${{ needs.resolve-main-browserstack-urls.outputs.with-srp-version || needs.trigger-android-dual-versions.outputs.with-srp-version || 'Manual-Input' }} | |
| branch_name: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| browserstack_build_name: ${{ needs.set-build-names.outputs.android_build_name }} | |
| grep_tags: ${{ needs.compute-test-selection.outputs.grep_pattern }} | |
| secrets: inherit | |
| run-ios-imported-wallet-tests: | |
| name: Run iOS Imported Wallet Tests | |
| uses: ./.github/workflows/performance-test-runner.yml | |
| needs: | |
| [ | |
| read-device-matrix, | |
| trigger-ios-dual-versions, | |
| wait-for-onboarding-completion, | |
| set-build-names, | |
| determine-branch-name, | |
| compute-test-selection, | |
| ] | |
| if: always() && !cancelled() && needs.compute-test-selection.outputs.run_tests == 'true' && (needs.trigger-ios-dual-versions.result == 'skipped' || needs.trigger-ios-dual-versions.result == 'success') && (inputs.browserstack_app_url_ios_imported_wallet != '' || needs.trigger-ios-dual-versions.outputs.with-srp-browserstack-url != '') | |
| with: | |
| platform: ios | |
| build_type: imported-wallet | |
| sentry_target: ${{ inputs.sentry_target || 'test' }} | |
| build_variant: ${{ inputs.build_variant || 'e2e' }} | |
| device_matrix: ${{ needs.read-device-matrix.outputs.ios_matrix }} | |
| browserstack_app_url: ${{ needs.trigger-ios-dual-versions.outputs.with-srp-browserstack-url || inputs.browserstack_app_url_ios_imported_wallet }} | |
| app_version: ${{ needs.trigger-ios-dual-versions.outputs.with-srp-version || 'Manual-Input' }} | |
| branch_name: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| browserstack_build_name: ${{ needs.set-build-names.outputs.ios_build_name }} | |
| grep_tags: ${{ needs.compute-test-selection.outputs.grep_pattern }} | |
| secrets: inherit | |
| fetch-rn-playground-apk-upload-to-browserstack: | |
| name: Fetch RN Playground APK and Upload to BrowserStack | |
| runs-on: ubuntu-latest | |
| needs: [wait-for-onboarding-completion] | |
| if: always() && !cancelled() | |
| outputs: | |
| browserstack-playground-url: ${{ steps.upload-playground.outputs.browserstack-url }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Fetch playground APK from GitHub Releases | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| RN_PLAYGROUND_APK_VERSION: ${{ vars.RN_PLAYGROUND_APK_VERSION || '' }} | |
| run: ./tests/scripts/fetch-rn-playground-apk.sh --output ./tmp/rn-playground.apk | |
| - name: Upload playground APK to BrowserStack | |
| id: upload-playground | |
| run: | | |
| echo "Uploading RN Playground APK to BrowserStack..." | |
| RESPONSE=$(curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \ | |
| -X POST "https://api-cloud.browserstack.com/app-automate/upload" \ | |
| -F "file=@./tmp/rn-playground.apk" \ | |
| -F "custom_id=RN-Playground-${{ github.run_id }}") | |
| APP_URL=$(echo "$RESPONSE" | jq -r '.app_url') | |
| if [ -z "$APP_URL" ] || [ "$APP_URL" = "null" ]; then | |
| echo "Error: Failed to upload playground APK to BrowserStack" | |
| echo "Response: $RESPONSE" | |
| exit 1 | |
| fi | |
| echo "browserstack-url=$APP_URL" >> "$GITHUB_OUTPUT" | |
| echo "Playground APK uploaded: $APP_URL" | |
| run-android-mm-connect-tests: | |
| name: Run Android MM-Connect Tests | |
| uses: ./.github/workflows/performance-test-runner.yml | |
| needs: | |
| [ | |
| read-device-matrix, | |
| trigger-android-dual-versions, | |
| resolve-main-browserstack-urls, | |
| fetch-rn-playground-apk-upload-to-browserstack, | |
| set-build-names, | |
| determine-branch-name, | |
| compute-test-selection, | |
| ] | |
| if: >- | |
| always() && !cancelled() && | |
| needs.compute-test-selection.outputs.run_tests == 'true' && | |
| ( | |
| needs.trigger-android-dual-versions.result == 'skipped' || | |
| needs.trigger-android-dual-versions.result == 'success' | |
| ) && | |
| ( | |
| needs.resolve-main-browserstack-urls.result == 'skipped' || | |
| needs.resolve-main-browserstack-urls.result == 'success' | |
| ) && | |
| ( | |
| inputs.browserstack_app_url_android_imported_wallet != '' || | |
| needs.trigger-android-dual-versions.outputs.with-srp-browserstack-url != '' || | |
| needs.resolve-main-browserstack-urls.outputs.with-srp-browserstack-url != '' | |
| ) | |
| with: | |
| platform: android | |
| build_type: mm-connect | |
| sentry_target: ${{ inputs.sentry_target || 'test' }} | |
| build_variant: ${{ inputs.build_variant || 'e2e' }} | |
| device_matrix: ${{ needs.read-device-matrix.outputs.android_mm_connect_matrix }} | |
| browserstack_app_url: ${{ needs.resolve-main-browserstack-urls.outputs.with-srp-browserstack-url || needs.trigger-android-dual-versions.outputs.with-srp-browserstack-url || inputs.browserstack_app_url_android_imported_wallet }} | |
| app_version: ${{ needs.resolve-main-browserstack-urls.outputs.with-srp-version || needs.trigger-android-dual-versions.outputs.with-srp-version || 'Manual-Input' }} | |
| branch_name: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| browserstack_build_name: ${{ needs.set-build-names.outputs.android_build_name }} | |
| browserstack_playground_url: ${{ needs.fetch-rn-playground-apk-upload-to-browserstack.outputs.browserstack-playground-url }} | |
| grep_tags: ${{ needs.compute-test-selection.outputs.grep_pattern }} | |
| secrets: inherit | |
| aggregate-results: | |
| name: Aggregate All Test Results | |
| runs-on: ubuntu-latest | |
| needs: | |
| [ | |
| run-android-imported-wallet-tests, | |
| run-android-onboarding-tests, | |
| run-android-mm-connect-tests, | |
| run-ios-imported-wallet-tests, | |
| run-ios-onboarding-tests, | |
| wait-for-onboarding-completion, | |
| determine-branch-name, | |
| ] | |
| if: always() | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download All Test Results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: '*-test-results-*' | |
| path: ./test-results | |
| merge-multiple: true | |
| - name: Run aggregation script | |
| env: | |
| BRANCH_NAME: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| BUILD_VARIANT: ${{ inputs.build_variant || 'e2e' }} | |
| run: | | |
| echo "Processing all test results..." | |
| echo "Running aggregation script..." | |
| node tests/scripts/aggregate-performance-reports.mjs | |
| echo "Aggregation completed" | |
| - name: Upload Final Combined Results | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: aggregated-reports | |
| path: | | |
| tests/aggregated-reports/ | |
| if-no-files-found: ignore | |
| retention-days: 30 | |
| post-pr-comment: | |
| name: Post Performance Results to PR | |
| runs-on: ubuntu-latest | |
| needs: [aggregate-results, determine-branch-name] | |
| # Only runs when triggered from a PR via workflow_call with a pr_number | |
| if: always() && !cancelled() && inputs.pr_number != '' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download Aggregated Results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: aggregated-reports | |
| path: ./aggregated-reports | |
| continue-on-error: true | |
| - name: Generate PR comment markdown | |
| env: | |
| GITHUB_RUN_ID: ${{ github.run_id }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| run: | | |
| node tests/scripts/generate-performance-pr-comment.mjs \ | |
| aggregated-reports/summary.json \ | |
| performance-pr-comment.md | |
| - name: Delete previous performance results comments | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| ALL_COMMENT_IDS=$(gh api "repos/${{ github.repository }}/issues/${{ inputs.pr_number }}/comments" \ | |
| --jq '.[] | select(.body | contains("<!-- perf-test-results -->")) | .id') | |
| if [ -n "$ALL_COMMENT_IDS" ]; then | |
| echo "$ALL_COMMENT_IDS" | while read -r COMMENT_ID; do | |
| if [ -n "$COMMENT_ID" ]; then | |
| gh api "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" \ | |
| --method DELETE > /dev/null 2>&1 || true | |
| fi | |
| done | |
| echo "Deleted previous performance results comments" | |
| fi | |
| - name: Post PR comment | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| MARKER="<!-- perf-test-results -->" | |
| COMMENT=$(cat performance-pr-comment.md 2>/dev/null || echo "⚠️ Performance test results are not available.") | |
| FULL_COMMENT="${COMMENT}"$'\n'"${MARKER}" | |
| gh pr comment "${{ inputs.pr_number }}" --repo "${{ github.repository }}" --body "$FULL_COMMENT" | |
| echo "Performance results posted to PR #${{ inputs.pr_number }}" | |
| slack-notification: | |
| name: Send Slack Notification | |
| runs-on: ubuntu-latest | |
| needs: | |
| [ | |
| run-android-imported-wallet-tests, | |
| run-android-onboarding-tests, | |
| run-android-mm-connect-tests, | |
| run-ios-imported-wallet-tests, | |
| run-ios-onboarding-tests, | |
| aggregate-results, | |
| determine-branch-name, | |
| ] | |
| if: always() | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download Aggregated Results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: aggregated-reports | |
| path: ./aggregated-reports | |
| - name: Generate Test Summary | |
| id: summary | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| BRANCH_NAME: ${{ needs.determine-branch-name.outputs.branch_name }} | |
| run: | | |
| { | |
| echo "summary<<EOF" | |
| ./tests/scripts/generate-slack-summary.sh aggregated-reports/summary.json | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Send Slack Notification | |
| uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a | |
| with: | |
| webhook: ${{ secrets.PERFORMANCE_E2E_SLACK_WEBHOOK_URL }} | |
| webhook-type: incoming-webhook | |
| payload: | | |
| { | |
| "text": "${{ steps.summary.outputs.summary }}" | |
| } |