@Mobile E2E • Manual • iOS Only • support/tahoe-testing • lewisd5 #3891
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: "[Mobile] E2E Only - Scheduled/Manual" | |
| run-name: > | |
| @Mobile E2E • ${{ github.event_name == 'workflow_dispatch' && 'Manual' || github.event_name == 'schedule' && 'Scheduled' || github.event_name }} • ${{ inputs.tests_type || 'All' }} • ${{ inputs.ref || github.ref_name }} • ${{ github.actor }} | |
| on: | |
| schedule: | |
| - cron: "0 3 * * 1-5" | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: "The branch which triggered this workflow" | |
| required: false | |
| test_filter: | |
| description: Filter to execute only test suite spec files according to pattern(s) (e.g. to execute nftGallery.spec.ts and deeplinks.spec.ts files "addAccount deeplinks")" | |
| required: false | |
| type: string | |
| tests_type: | |
| description: "Which tests to run" | |
| required: true | |
| type: choice | |
| default: "iOS & Android" | |
| options: | |
| - "Android Only" | |
| - "iOS Only" | |
| - "iOS & Android" | |
| speculos_device: | |
| description: Speculos device to use | |
| required: true | |
| type: choice | |
| options: | |
| - nanoS | |
| - nanoSP | |
| - nanoX | |
| - stax | |
| - flex | |
| - nanoGen5 | |
| default: nanoX | |
| production_firebase: | |
| description: "Target Firebase Production env" | |
| required: false | |
| type: boolean | |
| default: false | |
| enable_broadcast: | |
| description: "Enable transaction broadcast" | |
| required: false | |
| type: boolean | |
| default: false | |
| export_to_xray: | |
| description: "Send results to Xray" | |
| required: false | |
| type: boolean | |
| default: false | |
| test_execution_android: | |
| description: "Xray execution key for Android (optional)" | |
| required: false | |
| type: string | |
| test_execution_ios: | |
| description: "Xray execution key for iOS (optional)" | |
| required: false | |
| type: string | |
| workflow_call: | |
| inputs: | |
| ref: | |
| description: "The branch which triggered this workflow" | |
| required: false | |
| type: string | |
| test_filter: | |
| description: "Filter to execute only test suite spec files according to pattern(s)" | |
| required: false | |
| type: string | |
| tests_type: | |
| description: "Which tests to run" | |
| required: true | |
| type: string | |
| default: "iOS & Android" | |
| speculos_device: | |
| description: "Speculos device to use" | |
| required: true | |
| type: string | |
| production_firebase: | |
| description: "Target Firebase Production env" | |
| required: false | |
| type: boolean | |
| default: false | |
| enable_broadcast: | |
| description: "Enable transaction broadcast" | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| id-token: write | |
| contents: read | |
| env: | |
| cache-bucket: ll-gha-s3-cache | |
| ANDROID_APK_PATH: apps/ledger-live-mobile/android/app/build/outputs/apk/detox${{ inputs.production_firebase == true && 'PreRelease' || '' }}/app-x86_64-detox${{ inputs.production_firebase == true && 'PreRelease' || '' }}.apk | |
| ANDROID_JSBUNDLE_PATH: apps/ledger-live-mobile/main.jsbundle | |
| ANDROID_TESTBINARY_PATH: apps/ledger-live-mobile/android/app/build/outputs/apk/androidTest/detox${{ inputs.production_firebase == true && 'PreRelease' || '' }}/app-detox${{ inputs.production_firebase == true && 'PreRelease' || '' }}-androidTest.apk | |
| IOS_JSBUNDLE_PATH: apps/ledger-live-mobile/ios/build/Build/Products/Release-iphonesimulator/ledgerlivemobile.app/main.jsbundle | |
| IOS_NATIVE_PATH: apps/ledger-live-mobile/ios/build/Build/Products/Release-iphonesimulator | |
| SPECULOS_IMAGE_TAG: ghcr.io/ledgerhq/speculos:${{ inputs.speculos_device == 'nanoS' && '1be65b91a8e0691866f880fd437ac05fce78af9d' || 'master' }} | |
| COINAPPS: ${{ github.workspace }}/coin-apps | |
| SPECULOS_DEVICE: ${{ inputs.speculos_device || 'nanoX' }} | |
| # Android AVD configuration | |
| AVD_API: 35 | |
| AVD_ARCH: x86_64 | |
| AVD_PROFILE: pixel_7_pro | |
| AVD_TARGET: google_apis | |
| AVD_NAME: "Android_Emulator" | |
| AVD_CORES: 4 | |
| AVD_RAM_SIZE: 5120M | |
| AVD_HEAP_SIZE: 1023M | |
| AVD_OPTIONS: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none | |
| jobs: | |
| determine-builds: | |
| name: "Determine Builds & Generate Shards" | |
| runs-on: ledger-live-medium | |
| outputs: | |
| matrix_ios: ${{ steps.generate-shards.outputs.matrix_ios }} | |
| matrix_android: ${{ steps.generate-shards.outputs.matrix_android }} | |
| test_files_for_sharding: ${{ steps.generate-shards.outputs.test_files_for_sharding }} | |
| ios_timeout: ${{ steps.generate-shards.outputs.ios_timeout }} | |
| android_timeout: ${{ steps.generate-shards.outputs.android_timeout }} | |
| ios_native_exists: ${{ steps.check-ios-native.outputs.cache-hit }} | |
| ios_js_exists: ${{ steps.check-ios-js.outputs.cache-hit }} | |
| android_native_exists: ${{ steps.check-android-native.outputs.cache-hit }} | |
| android_js_exists: ${{ steps.check-android-js.outputs.cache-hit }} | |
| ios_native_key: ${{ steps.cache-keys.outputs.ios_native_key }} | |
| ios_js_key: ${{ steps.cache-keys.outputs.ios_js_key }} | |
| android_native_key: ${{ steps.cache-keys.outputs.android_native_key }} | |
| android_js_key: ${{ steps.cache-keys.outputs.android_js_key }} | |
| android_timing_cache_key: ${{ steps.cache-keys.outputs.android_timing_cache_key }} | |
| ios_timing_cache_key: ${{ steps.cache-keys.outputs.ios_timing_cache_key }} | |
| avd_cache_key: ${{ steps.cache-keys.outputs.avd_cache_key }} | |
| avd_exists: ${{ steps.check-avd.outputs.cache-hit }} | |
| steps: | |
| - name: generate token | |
| id: generate-token | |
| uses: tibdex/github-app-token@v1 | |
| with: | |
| app_id: ${{ secrets.GH_BOT_APP_ID }} | |
| private_key: ${{ secrets.GH_BOT_PRIVATE_KEY }} | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ inputs.ref || github.sha }} | |
| repository: LedgerHQ/ledger-live | |
| persist-credentials: false | |
| sparse-checkout: | | |
| apps/ledger-live-mobile | |
| e2e/mobile | |
| token: ${{ steps.generate-token.outputs.token }} | |
| - name: Write summary | |
| run: | | |
| FILTER_PATTERN="${{ inputs.test_filter || '' }}" | |
| DEVICE="${{ inputs.speculos_device || 'nanoX' }}" | |
| BUILD_TYPE="${{ inputs.production_firebase && 'production' || 'testing' }}" | |
| BROADCAST_ENABLED="${{ inputs.enable_broadcast }}" | |
| TEST_EXECUTION_ANDROID="${{ inputs.test_execution_android || '(not provided)' }}" | |
| TEST_EXECUTION_IOS="${{ inputs.test_execution_ios || '(not provided)' }}" | |
| if [ -z "$FILTER_PATTERN" ]; then | |
| FILTER_PATTERN="(none)" | |
| fi | |
| { | |
| echo "## Workflow Context" | |
| echo "" | |
| echo "- **Workflow source branch:** ${{ github.ref_name }}" | |
| echo "- **Triggered branch:** ${{ inputs.ref || github.ref_name }}" | |
| echo "- **Commit SHA:** ${{ github.sha }}" | |
| echo "- **Device selected:** $DEVICE" | |
| echo "- **Filtered pattern:** $FILTER_PATTERN" | |
| echo "- **Test Execution ticket ID (Android):** $TEST_EXECUTION_ANDROID" | |
| echo "- **Test Execution ticket ID (iOS):** $TEST_EXECUTION_IOS" | |
| echo "- **Firebase env to target:** $BUILD_TYPE" | |
| echo "- **Broadcast enabled:** $BROADCAST_ENABLED" | |
| } >> $GITHUB_STEP_SUMMARY | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| id: aws | |
| with: | |
| role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID_PROD }}:role/${{ secrets.AWS_CACHE_ROLE_NAME }} | |
| aws-region: ${{ secrets.AWS_CACHE_REGION }} | |
| - name: Determine cache keys | |
| id: cache-keys | |
| run: | | |
| echo "ios_native_key=longterm-${{ hashFiles('apps/ledger-live-mobile/ios') }}-detox-native-ios-${{ inputs.production_firebase == true && 'prod-2' || '3' }}" >> $GITHUB_OUTPUT | |
| echo "android_native_key=longterm-${{ hashFiles('apps/ledger-live-mobile/android') }}-detox-native-android-${{ inputs.production_firebase == true && 'prod-2' || '3' }}" >> $GITHUB_OUTPUT | |
| echo "ios_js_key=${{ inputs.ref || github.sha }}-detox-js-ios" >> $GITHUB_OUTPUT | |
| echo "android_js_key=${{ inputs.ref || github.sha }}-detox-js-android" >> $GITHUB_OUTPUT | |
| echo "android_timing_cache_key=android-e2e-timing-${{ hashFiles('e2e/mobile/specs') }}-2" >> $GITHUB_OUTPUT | |
| echo "ios_timing_cache_key=ios-e2e-timing-${{ hashFiles('e2e/mobile/specs') }}-2" >> $GITHUB_OUTPUT | |
| echo "avd_cache_key=${{ runner.os }}-detox-avd-${{ env.AVD_NAME }}_4-${{ env.AVD_PROFILE }}-${{ env.AVD_TARGET }}-${{ env.AVD_API }}-${{ env.AVD_ARCH }}-${{ env.AVD_CORES }}-${{ env.AVD_RAM_SIZE }}-${{ env.AVD_HEAP_SIZE }}-r2-v8" >> $GITHUB_OUTPUT | |
| - name: Generate shards matrix and test files | |
| id: generate-shards | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/generate-shards-matrix@develop | |
| with: | |
| test_directory: e2e/mobile | |
| test_filter: ${{ inputs.test_filter || '' }} | |
| event_name: ${{ github.event_name }} | |
| ref: ${{ inputs.ref || github.ref_name }} | |
| ios_timing_cache_key: ${{ steps.cache-keys.outputs.ios_timing_cache_key }} | |
| android_timing_cache_key: ${{ steps.cache-keys.outputs.android_timing_cache_key }} | |
| aws_access_key_id: ${{ env.AWS_ACCESS_KEY_ID }} | |
| aws_secret_access_key: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| aws_session_token: ${{ env.AWS_SESSION_TOKEN }} | |
| cache_bucket: ${{ env.cache-bucket }} | |
| aws_region: ${{ secrets.AWS_CACHE_REGION }} | |
| - name: Check if iOS Native Build exists already | |
| id: check-ios-native | |
| uses: tespkg/actions-cache/restore@v1.9.0 | |
| with: | |
| path: apps/ledger-live-mobile/ios/build/Build/Products/Release-iphonesimulator | |
| key: ${{ steps.cache-keys.outputs.ios_native_key }} | |
| accessKey: ${{ env.AWS_ACCESS_KEY_ID }} | |
| secretKey: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| sessionToken: ${{ env.AWS_SESSION_TOKEN}} | |
| bucket: ${{ env.cache-bucket }} | |
| region: ${{ secrets.AWS_CACHE_REGION }} | |
| use-fallback: false | |
| lookup-only: true | |
| - name: Check if Android Native Build exists already | |
| id: check-android-native | |
| uses: tespkg/actions-cache/restore@v1.9.0 | |
| with: | |
| path: apps/ledger-live-mobile/android/app/build/outputs/apk/detox/app-x86_64-detox.apk | |
| key: ${{ steps.cache-keys.outputs.android_native_key }} | |
| accessKey: ${{ env.AWS_ACCESS_KEY_ID }} | |
| secretKey: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| sessionToken: ${{ env.AWS_SESSION_TOKEN}} | |
| bucket: ${{ env.cache-bucket }} | |
| region: ${{ secrets.AWS_CACHE_REGION }} | |
| use-fallback: false | |
| lookup-only: true | |
| - name: Check if iOS JS Build exists already | |
| id: check-ios-js | |
| uses: tespkg/actions-cache/restore@v1.9.0 | |
| with: | |
| path: apps/ledger-live-mobile/main.jsbundle | |
| key: ${{ steps.cache-keys.outputs.ios_js_key }} | |
| accessKey: ${{ env.AWS_ACCESS_KEY_ID }} | |
| secretKey: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| sessionToken: ${{ env.AWS_SESSION_TOKEN}} | |
| bucket: ${{ env.cache-bucket }} | |
| region: ${{ secrets.AWS_CACHE_REGION }} | |
| use-fallback: false | |
| lookup-only: true | |
| - name: Check if Android JS Build exists already | |
| id: check-android-js | |
| uses: tespkg/actions-cache/restore@v1.9.0 | |
| with: | |
| path: apps/ledger-live-mobile/main.jsbundle | |
| key: ${{ steps.cache-keys.outputs.android_js_key }} | |
| accessKey: ${{ env.AWS_ACCESS_KEY_ID }} | |
| secretKey: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| sessionToken: ${{ env.AWS_SESSION_TOKEN}} | |
| bucket: ${{ env.cache-bucket }} | |
| region: ${{ secrets.AWS_CACHE_REGION }} | |
| use-fallback: false | |
| lookup-only: true | |
| - name: Check if Android AVD cache exists | |
| id: check-avd | |
| if: ${{ inputs.tests_type != 'iOS Only' }} | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/cache/exists@develop | |
| with: | |
| key: ${{ steps.cache-keys.outputs.avd_cache_key }} | |
| accessKey: ${{ secrets.R2_ACCESS_KEY_ID }} | |
| secretKey: ${{ secrets.R2_SECRET_ACCESS_KEY }} | |
| bucket: ledger-live-cache | |
| endpoint: ${{ secrets.R2_ENDPOINT }} | |
| region: auto | |
| build-ios: | |
| name: "iOS Build" | |
| needs: [determine-builds] | |
| if: ${{ inputs.tests_type != 'Android Only' && needs.determine-builds.outputs.test_files_for_sharding != '' }} | |
| uses: LedgerHQ/ledger-live/.github/workflows/test-mobile-build-ios-reusable.yml@develop | |
| with: | |
| ref: ${{ inputs.ref || github.sha }} | |
| macos-specificity-runner-label: "general-pool" | |
| disable-turbo-cache: false | |
| build-ios-js: ${{ needs.determine-builds.outputs.ios_js_exists == 'false' }} | |
| build-ios-native: ${{ needs.determine-builds.outputs.ios_native_exists == 'false' }} | |
| ios-native-cache-key: ${{ needs.determine-builds.outputs.ios_native_key }} | |
| ios-js-cache-key: ${{ needs.determine-builds.outputs.ios_js_key }} | |
| production_firebase: ${{ inputs.production_firebase || false }} | |
| secrets: inherit | |
| # build-android: | |
| # name: "Android Build" | |
| # needs: [determine-builds] | |
| # if: ${{ inputs.tests_type != 'iOS Only' && needs.determine-builds.outputs.test_files_for_sharding != '' }} | |
| # uses: LedgerHQ/ledger-live/.github/workflows/test-mobile-build-android-reusable.yml@develop | |
| # with: | |
| # ref: ${{ inputs.ref || github.sha }} | |
| # disable-turbo-cache: false | |
| # build-android-js: ${{ needs.determine-builds.outputs.android_js_exists == 'false' }} | |
| # build-android-native: ${{ needs.determine-builds.outputs.android_native_exists == 'false' }} | |
| # android-native-cache-key: ${{ needs.determine-builds.outputs.android_native_key }} | |
| # android-js-cache-key: ${{ needs.determine-builds.outputs.android_js_key }} | |
| # production_firebase: ${{ inputs.production_firebase || false }} | |
| # secrets: inherit | |
| # setup-android-avd: | |
| # name: "Setup Android AVD" | |
| # needs: [determine-builds] | |
| # if: ${{ inputs.tests_type != 'iOS Only' && needs.determine-builds.outputs.test_files_for_sharding != '' && needs.determine-builds.outputs.avd_exists != 'true' }} | |
| # runs-on: [ledger-live-linux-e2e-8CPU-32RAM] | |
| # steps: | |
| # - name: Setup Android AVDs | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/setup-android-avd@develop | |
| # with: | |
| # ref: ${{ inputs.ref || github.sha }} | |
| # avd_api: ${{ env.AVD_API }} | |
| # avd_arch: ${{ env.AVD_ARCH }} | |
| # avd_profile: ${{ env.AVD_PROFILE }} | |
| # avd_target: ${{ env.AVD_TARGET }} | |
| # avd_name: ${{ env.AVD_NAME }} | |
| # avd_cores: ${{ env.AVD_CORES }} | |
| # avd_ram_size: ${{ env.AVD_RAM_SIZE }} | |
| # avd_heap_size: ${{ env.AVD_HEAP_SIZE }} | |
| # avd_options: ${{ env.AVD_OPTIONS }} | |
| # cache_key: ${{ needs.determine-builds.outputs.avd_cache_key }} | |
| # r2_access_key: ${{ secrets.R2_ACCESS_KEY_ID }} | |
| # r2_secret_key: ${{ secrets.R2_SECRET_ACCESS_KEY }} | |
| # r2_endpoint: ${{ secrets.R2_ENDPOINT }} | |
| detox-tests-ios: | |
| name: iOS E2E Tests (${{ matrix.shard }}, ${{ matrix.total }}) | |
| needs: [build-ios, determine-builds] | |
| if: ${{ inputs.tests_type != 'Android Only' && needs.determine-builds.outputs.test_files_for_sharding != '' }} | |
| runs-on: [project-portugal] | |
| env: | |
| NODE_OPTIONS: "--max-old-space-size=8192" | |
| LANG: en_US.UTF-8 | |
| LANGUAGE: en_US.UTF-8 | |
| LC_ALL: en_US.UTF-8 | |
| outputs: | |
| status: ${{ steps.run-ios.outcome }} | |
| artifact: ${{ steps.test-artifacts.outputs.artifact-id }} | |
| status_1: ${{ steps.set-output.outputs.status_1 }} | |
| status_2: ${{ steps.set-output.outputs.status_2 }} | |
| status_3: ${{ steps.set-output.outputs.status_3 }} | |
| status_4: ${{ steps.set-output.outputs.status_4 }} | |
| status_5: ${{ steps.set-output.outputs.status_5 }} | |
| status_6: ${{ steps.set-output.outputs.status_6 }} | |
| status_7: ${{ steps.set-output.outputs.status_7 }} | |
| status_8: ${{ steps.set-output.outputs.status_8 }} | |
| status_9: ${{ steps.set-output.outputs.status_9 }} | |
| status_10: ${{ steps.set-output.outputs.status_10 }} | |
| status_11: ${{ steps.set-output.outputs.status_11 }} | |
| status_12: ${{ steps.set-output.outputs.status_12 }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: ${{ fromJSON(needs.determine-builds.outputs.matrix_ios) }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ inputs.ref || github.sha }} | |
| repository: LedgerHQ/ledger-live | |
| persist-credentials: false | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| id: aws | |
| with: | |
| role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID_PROD }}:role/${{ secrets.AWS_CACHE_ROLE_NAME }} | |
| aws-region: ${{ secrets.AWS_CACHE_REGION }} | |
| - name: Set shard test files from pre-computed matrix | |
| run: | | |
| echo "SHARD_TEST_FILES<<EOF" >> $GITHUB_ENV | |
| echo "${{ matrix.files }}" >> $GITHUB_ENV | |
| echo "EOF" >> $GITHUB_ENV | |
| echo "Using pre-computed shard ${{ matrix.shard }}/${{ matrix.total }} with $(echo '${{ matrix.files }}' | wc -w) test files" | |
| - name: Boot iOS Simulator in Background | |
| run: | | |
| LOG_FILE="e2e/mobile/artifacts/simulator-boot.log" | |
| mkdir -p e2e/mobile/artifacts | |
| nohup bash -c ' | |
| echo "🛫 Booting simulator..." | |
| xcrun simctl boot "iOS Simulator" || true | |
| xcrun simctl bootstatus "iOS Simulator" | |
| ' > "$LOG_FILE" 2>&1 & | |
| echo "ℹ️ Simulator boot started in background." | |
| shell: bash | |
| - name: setup caches | |
| id: setup-caches | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop | |
| with: | |
| skip-pod-cache: "false" | |
| skip-turbo-cache: "false" | |
| skip-pnpm-cache: "true" | |
| accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} | |
| roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} | |
| region: ${{ secrets.AWS_CACHE_REGION }} | |
| turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} | |
| - uses: nick-fields/retry@v3 | |
| name: install dependencies | |
| id: install-dependencies | |
| with: | |
| max_attempts: 2 | |
| timeout_minutes: 15 | |
| command: pnpm i --filter="live-mobile..." --filter="ledger-live" --filter="ledger-live-mobile-e2e-tests" --filter="@ledgerhq/dummy-*-app..." --filter="live-cli*..." --no-frozen-lockfile --unsafe-perm --ignore-scripts | |
| new_command_on_retry: rm -rf ~/.cocoapods/ && pnpm clean && pnpm i --filter="live-mobile..." --filter="ledger-live" --filter="ledger-live-mobile-e2e-tests" --filter="@ledgerhq/dummy-*-app..." --filter="live-cli*..." --no-frozen-lockfile --unsafe-perm | |
| - name: Detox Post Install | |
| run: node apps/ledger-live-mobile/node_modules/detox/scripts/postinstall.js | |
| - name: Download Native Build | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/cache/download@develop | |
| with: | |
| endpoint: ${{ secrets.S3_DIRECTCONNECT_ENDPOINT }} | |
| key: ${{ needs.determine-builds.outputs.ios_native_key }} | |
| accessKey: ${{ env.AWS_ACCESS_KEY_ID }} | |
| secretKey: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| sessionToken: ${{ env.AWS_SESSION_TOKEN}} | |
| bucket: ${{ env.cache-bucket }} | |
| region: ${{ secrets.AWS_CACHE_REGION }} | |
| - name: Download JS Build | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/cache/download@develop | |
| with: | |
| endpoint: ${{ secrets.S3_DIRECTCONNECT_ENDPOINT }} | |
| key: ${{ needs.determine-builds.outputs.ios_js_key }} | |
| accessKey: ${{ env.AWS_ACCESS_KEY_ID }} | |
| secretKey: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| sessionToken: ${{ env.AWS_SESSION_TOKEN}} | |
| bucket: ${{ env.cache-bucket }} | |
| region: ${{ secrets.AWS_CACHE_REGION }} | |
| - name: Copy JS build | |
| run: | | |
| cp apps/ledger-live-mobile/main.jsbundle ${{ env.IOS_JSBUNDLE_PATH }} | |
| cp apps/ledger-live-mobile/main.jsbundle ${{ env.IOS_NATIVE_PATH }}/main.jsbundle | |
| - name: Build dependencies | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/turbo-step@develop | |
| with: | |
| command: pnpm build:llm:deps | |
| turbo_server_token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} | |
| turbo_port: ${{ steps.setup-caches.outputs.port }} | |
| disable_cache: false | |
| - name: Build CLI | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/turbo-step@develop | |
| with: | |
| command: pnpm build:cli | |
| turbo_server_token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} | |
| turbo_port: ${{ steps.setup-caches.outputs.port }} | |
| disable_cache: false | |
| - name: Setup Speculos image and Coin Apps | |
| id: setup-speculos | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/setup-speculos_image@develop | |
| with: | |
| coinapps_path: ${{ env.COINAPPS }} | |
| bot_id: ${{ secrets.GH_BOT_APP_ID }} | |
| bot_key: ${{ secrets.GH_BOT_PRIVATE_KEY }} | |
| - name: Set DISABLE_TRANSACTION_BROADCAST | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/setup-e2e-env@develop | |
| with: | |
| enable_broadcast: ${{ inputs.enable_broadcast }} | |
| build_type: ${{ inputs.production_firebase == 'true' && 'js' || 'testing' }} | |
| - name: Run iOS Detox shard ${{ matrix.shard }}/${{ matrix.total }} | |
| id: run-ios | |
| timeout-minutes: ${{ fromJSON(needs.determine-builds.outputs.ios_timeout) }} | |
| run: | | |
| pnpm mobile e2e:ci -p ios -t \ | |
| --e2e \ | |
| $([[ "$PRODUCTION" == "true" ]] && printf %s '--production') \ | |
| $SHARD_TEST_FILES \ | |
| --outputFile=artifacts/e2e-test-results-ios-shard-${{ matrix.shard }}.json | |
| env: | |
| SEED: ${{ secrets.SEED_QAA_B2C }} | |
| GITHUB_TOKEN: ${{ secrets.LL_SPECULOS_CI }} | |
| INPUT_E2E: "true" | |
| REMOTE_SPECULOS: "true" | |
| PRODUCTION: ${{ inputs.production_firebase }} | |
| INPUTS_TEST_FILTER: ${{ inputs.test_filter }} | |
| SWAP_API_BASE: ${{ env.SWAP_API_BASE }} | |
| SHARD_INDEX: ${{ matrix.shard }} | |
| - name: Upload iOS artifacts | |
| if: (!cancelled() || steps.run-ios.outcome == 'cancelled') | |
| uses: actions/upload-artifact@v4 | |
| id: "test-artifacts" | |
| with: | |
| name: ios-test-artifacts-${{ matrix.shard }} | |
| path: e2e/mobile/artifacts | |
| - name: Setup iOS Shard timing artifacts | |
| if: (!cancelled() || steps.run-ios.outcome == 'cancelled') | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| path: e2e/mobile/artifacts/e2e-test-results-ios-shard-${{ matrix.shard }}.json | |
| name: "${{ needs.determine-builds.outputs.ios_timing_cache_key }}-${{ matrix.shard }}" | |
| - name: Set job output based on detox result | |
| id: set-output | |
| if: ${{ !cancelled() }} | |
| run: | | |
| echo "status_${{ matrix.shard }}=${{ steps.run-ios.outcome }}" >> $GITHUB_OUTPUT | |
| # detox-tests-android: | |
| # name: Android E2E Tests (${{ matrix.shard }}, ${{ matrix.total }}) | |
| # needs: [build-android, determine-builds] | |
| # if: ${{ inputs.tests_type != 'iOS Only' && needs.determine-builds.outputs.test_files_for_sharding != '' }} | |
| # runs-on: [ledger-live-linux-e2e-8CPU-32RAM] | |
| # env: | |
| # NODE_OPTIONS: "--max-old-space-size=7168" | |
| # LANG: en_US.UTF-8 | |
| # LANGUAGE: en_US.UTF-8 | |
| # LC_ALL: en_US.UTF-8 | |
| # outputs: | |
| # status: ${{ steps.run-android.outcome }} | |
| # artifact: ${{ steps.test-artifacts.outputs.artifact-id }} | |
| # status_1: ${{ steps.set-output.outputs.status_1 }} | |
| # status_2: ${{ steps.set-output.outputs.status_2 }} | |
| # status_3: ${{ steps.set-output.outputs.status_3 }} | |
| # status_4: ${{ steps.set-output.outputs.status_4 }} | |
| # status_5: ${{ steps.set-output.outputs.status_5 }} | |
| # status_6: ${{ steps.set-output.outputs.status_6 }} | |
| # status_7: ${{ steps.set-output.outputs.status_7 }} | |
| # status_8: ${{ steps.set-output.outputs.status_8 }} | |
| # status_9: ${{ steps.set-output.outputs.status_9 }} | |
| # status_10: ${{ steps.set-output.outputs.status_10 }} | |
| # status_11: ${{ steps.set-output.outputs.status_11 }} | |
| # status_12: ${{ steps.set-output.outputs.status_12 }} | |
| # strategy: | |
| # fail-fast: false | |
| # matrix: | |
| # include: ${{ fromJSON(needs.determine-builds.outputs.matrix_android) }} | |
| # steps: | |
| # - uses: actions/checkout@v4 | |
| # with: | |
| # ref: ${{ inputs.ref || github.sha }} | |
| # repository: LedgerHQ/ledger-live | |
| # persist-credentials: false | |
| # | |
| # - name: Configure AWS credentials | |
| # uses: aws-actions/configure-aws-credentials@v4 | |
| # id: aws | |
| # with: | |
| # role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID_PROD }}:role/${{ secrets.AWS_CACHE_ROLE_NAME }} | |
| # aws-region: ${{ secrets.AWS_CACHE_REGION }} | |
| # | |
| # - name: Set shard test files from pre-computed matrix | |
| # run: | | |
| # echo "SHARD_TEST_FILES<<EOF" >> $GITHUB_ENV | |
| # echo "${{ matrix.files }}" >> $GITHUB_ENV | |
| # echo "EOF" >> $GITHUB_ENV | |
| # echo "Using pre-computed shard ${{ matrix.shard }}/${{ matrix.total }} with $(echo '${{ matrix.files }}' | wc -w) test files" | |
| # | |
| # - name: Setup Android Environment | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/setup-android-env@develop | |
| # | |
| # - name: Download Native Build | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/cache/download@develop | |
| # with: | |
| # key: ${{ needs.determine-builds.outputs.android_native_key }} | |
| # accessKey: ${{ env.AWS_ACCESS_KEY_ID }} | |
| # secretKey: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| # sessionToken: ${{ env.AWS_SESSION_TOKEN}} | |
| # bucket: ${{ env.cache-bucket }} | |
| # region: ${{ secrets.AWS_CACHE_REGION }} | |
| # | |
| # - name: Download JS Bundle | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/cache/download@develop | |
| # with: | |
| # key: ${{ needs.determine-builds.outputs.android_js_key }} | |
| # accessKey: ${{ env.AWS_ACCESS_KEY_ID }} | |
| # secretKey: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| # sessionToken: ${{ env.AWS_SESSION_TOKEN}} | |
| # bucket: ${{ env.cache-bucket }} | |
| # region: ${{ secrets.AWS_CACHE_REGION }} | |
| # | |
| # - name: Prepare APK | |
| # run: | | |
| # mkdir -p /tmp/apk/assets | |
| # mkdir /home/runner/.android/ | |
| # mv ${{ env.ANDROID_JSBUNDLE_PATH }} /tmp/apk/assets/index.android.bundle | |
| # mv ${{ env.ANDROID_APK_PATH }} /tmp/apk/tmp.apk | |
| # (cd /tmp/apk/; zip -r tmp.apk assets/index.android.bundle) | |
| # /usr/local/lib/android/sdk/build-tools/34.0.0/zipalign -p 4 /tmp/apk/tmp.apk ${{ env.ANDROID_APK_PATH }} | |
| # /usr/local/lib/android/sdk/build-tools/34.0.0/apksigner sign --ks ${{ secrets.ANDROID_KEYSTORE_PATH }} --ks-pass ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} --ks-key-alias staging --key-pass ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} ${{ env.ANDROID_APK_PATH }} | |
| # | |
| # - name: Setup the caches | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop | |
| # id: setup-caches | |
| # with: | |
| # install-proto: true | |
| # skip-pnpm-cache: "true" | |
| # skip-turbo-cache: "false" | |
| # accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} | |
| # roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} | |
| # region: ${{ secrets.AWS_CACHE_REGION }} | |
| # turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} | |
| # | |
| # - name: Install dependencies | |
| # run: | | |
| # pnpm i --filter="live-mobile..." --filter="ledger-live" --filter="ledger-live-mobile-e2e-tests" --filter="live-cli*..." --filter="@ledgerhq/dummy-*-app..." --no-frozen-lockfile --unsafe-perm --ignore-scripts | |
| # | |
| # - name: Detox Post Install | |
| # run: node apps/ledger-live-mobile/node_modules/detox/scripts/postinstall.js | |
| # | |
| # - name: Build dependencies | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/turbo-step@develop | |
| # with: | |
| # command: pnpm build:llm:deps | |
| # turbo_server_token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} | |
| # turbo_port: ${{ steps.setup-caches.outputs.port }} | |
| # disable_cache: false | |
| # | |
| # - name: Download android emulator | |
| # timeout-minutes: 10 | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/cache/download@develop | |
| # id: detox-avd | |
| # with: | |
| # key: ${{ needs.determine-builds.outputs.avd_cache_key }} | |
| # accessKey: "${{ secrets.R2_ACCESS_KEY_ID }}" | |
| # secretKey: "${{ secrets.R2_SECRET_ACCESS_KEY }}" | |
| # bucket: ledger-live-cache | |
| # endpoint: ${{ secrets.R2_ENDPOINT }} | |
| # region: auto | |
| # destination: / | |
| # | |
| # - name: Duplicate AVDs for parallel testing | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/duplicate-avd@develop | |
| # with: | |
| # source_avd_name: ${{ env.AVD_NAME }} | |
| # target_suffixes: "_2,_3" | |
| # avd_api: ${{ env.AVD_API }} | |
| # | |
| # - name: Boot Android Emulators in Background | |
| # run: | | |
| # LOG_FILE="e2e/mobile/artifacts/emulator-boot.log" | |
| # mkdir -p e2e/mobile/artifacts | |
| # nohup bash -c ' | |
| # log() { echo "[$(date +%H:%M:%S)] $1"; } | |
| # ts() { while IFS= read -r line; do echo "[$(date +%H:%M:%S)] [$1] $line"; done; } | |
| # | |
| # log "🛫 Starting emulators..." | |
| # $ANDROID_HOME/emulator/emulator -avd ${{ env.AVD_NAME }} ${{ env.AVD_OPTIONS }} 2>&1 | ts "EMU1" & | |
| # $ANDROID_HOME/emulator/emulator -avd ${{ env.AVD_NAME }}_2 ${{ env.AVD_OPTIONS }} 2>&1 | ts "EMU2" & | |
| # $ANDROID_HOME/emulator/emulator -avd ${{ env.AVD_NAME }}_3 ${{ env.AVD_OPTIONS }} 2>&1 | ts "EMU3" & | |
| # | |
| # log "⏳ Waiting for 3 emulators to connect..." | |
| # while [ "$(adb devices | grep -c emulator)" -lt 3 ]; do sleep 2; done | |
| # log "✅ 3 emulators connected" | |
| # log "⏳ Waiting for all emulators to finish booting..." | |
| # adb -s emulator-5554 wait-for-device shell "while [ \"\$(getprop sys.boot_completed)\" != 1 ]; do sleep 1; done" | |
| # log "✅ emulator-5554 booted" | |
| # adb -s emulator-5556 wait-for-device shell "while [ \"\$(getprop sys.boot_completed)\" != 1 ]; do sleep 1; done" | |
| # log "✅ emulator-5556 booted" | |
| # adb -s emulator-5558 wait-for-device shell "while [ \"\$(getprop sys.boot_completed)\" != 1 ]; do sleep 1; done" | |
| # log "✅ emulator-5558 booted" | |
| # | |
| # log "✅ All 3 emulators are fully booted" | |
| # ' > "$LOG_FILE" 2>&1 & | |
| # echo "ℹ️ Android emulators boot started in background." | |
| # shell: bash | |
| # | |
| # - name: Setup Speculos image and Coin Apps | |
| # id: setup-speculos | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/setup-speculos_image@develop | |
| # with: | |
| # coinapps_path: ${{ env.COINAPPS }} | |
| # bot_id: ${{ secrets.GH_BOT_APP_ID }} | |
| # bot_key: ${{ secrets.GH_BOT_PRIVATE_KEY }} | |
| # | |
| # - name: Build CLI | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/turbo-step@develop | |
| # with: | |
| # command: pnpm build:cli | |
| # turbo_server_token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} | |
| # turbo_port: ${{ steps.setup-caches.outputs.port }} | |
| # disable_cache: false | |
| # | |
| # - name: Set DISABLE_TRANSACTION_BROADCAST | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/setup-e2e-env@develop | |
| # with: | |
| # enable_broadcast: ${{ inputs.enable_broadcast }} | |
| # build_type: ${{ inputs.production_firebase == 'true' && 'js' || 'testing' }} | |
| # | |
| # - name: Run Android Detox shard ${{ matrix.shard }}/${{ matrix.total }} | |
| # id: run-android | |
| # timeout-minutes: ${{ fromJSON(needs.determine-builds.outputs.android_timeout) }} | |
| # run: | | |
| # pnpm mobile e2e:ci -p android -t \ | |
| # --e2e \ | |
| # $([[ "$PRODUCTION" == "true" ]] && printf %s '--production') \ | |
| # $SHARD_TEST_FILES \ | |
| # --outputFile=artifacts/e2e-test-results-android-shard-${{ matrix.shard }}.json | |
| # | |
| # env: | |
| # DETOX_INSTALL_TIMEOUT: 120000 | |
| # SEED: ${{ secrets.SEED_QAA_B2C }} | |
| # INPUT_E2E: "true" | |
| # PRODUCTION: ${{ inputs.production_firebase }} | |
| # INPUTS_TEST_FILTER: ${{ inputs.test_filter }} | |
| # SWAP_API_BASE: ${{ env.SWAP_API_BASE }} | |
| # SHARD_INDEX: ${{ matrix.shard }} | |
| # | |
| # - name: Upload Android artifacts | |
| # if: (!cancelled() || steps.run-android.outcome == 'cancelled') | |
| # uses: actions/upload-artifact@v4 | |
| # id: "test-artifacts" | |
| # with: | |
| # name: android-test-artifacts-${{ matrix.shard }} | |
| # path: e2e/mobile/artifacts | |
| # | |
| # - name: Setup Android Shard timing artifacts | |
| # if: (!cancelled() || steps.run-android.outcome == 'cancelled') | |
| # uses: actions/upload-artifact@v4 | |
| # with: | |
| # path: e2e/mobile/artifacts/e2e-test-results-android-shard-${{ matrix.shard }}.json | |
| # name: "${{ needs.determine-builds.outputs.android_timing_cache_key }}-${{ matrix.shard }}" | |
| # | |
| # - name: Set job output based on detox result | |
| # id: set-output | |
| # if: ${{ !cancelled() }} | |
| # run: | | |
| # echo "status_${{ matrix.shard }}=${{ steps.run-android.outcome }}" >> $GITHUB_OUTPUT | |
| allure-report-ios: | |
| name: Allure Report iOS | |
| runs-on: [ledger-live-medium] | |
| if: ${{ !cancelled() && needs.detox-tests-ios.outputs.artifact && inputs.tests_type != 'Android Only' }} | |
| needs: [determine-builds, detox-tests-ios] | |
| outputs: | |
| report-url: ${{ steps.upload.outputs.report-url }} | |
| result: ${{ steps.summary.outputs.test_result }} | |
| finalStatus: ${{ steps.aggregate.outputs.finalStatus }} | |
| missingShards: ${{ steps.aggregate.outputs.missingShards }} | |
| steps: | |
| - name: Download Allure Report | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ios-test-artifacts | |
| pattern: ios-test-artifacts* | |
| merge-multiple: true | |
| - uses: LedgerHQ/ledger-live/tools/actions/composites/upload-allure-report@develop | |
| if: ${{ !cancelled() }} | |
| id: upload | |
| with: | |
| platform: ios-e2e | |
| login: ${{ vars.ALLURE_USERNAME }} | |
| password: ${{ secrets.ALLURE_LEDGER_LIVE_PASSWORD }} | |
| path: ios-test-artifacts | |
| report_path_suffix: ${{ github.event_name != 'schedule' && 'manual' || '' }} | |
| - name: Get summary | |
| id: summary | |
| if: ${{ !cancelled() }} | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/get-allure-summary@develop | |
| with: | |
| allure-results-path: ios-test-artifacts | |
| platform: iOS | |
| - name: Aggregate test results | |
| id: aggregate | |
| uses: LedgerHQ/ledger-live/tools/actions/composites/aggregate-shard-results@develop | |
| with: | |
| total_shards: ${{ fromJSON(needs.determine-builds.outputs.matrix_ios)[0].total }} | |
| status_1: ${{ needs.detox-tests-ios.outputs.status_1 }} | |
| status_2: ${{ needs.detox-tests-ios.outputs.status_2 }} | |
| status_3: ${{ needs.detox-tests-ios.outputs.status_3 }} | |
| status_4: ${{ needs.detox-tests-ios.outputs.status_4 }} | |
| status_5: ${{ needs.detox-tests-ios.outputs.status_5 }} | |
| status_6: ${{ needs.detox-tests-ios.outputs.status_6 }} | |
| status_7: ${{ needs.detox-tests-ios.outputs.status_7 }} | |
| status_8: ${{ needs.detox-tests-ios.outputs.status_8 }} | |
| status_9: ${{ needs.detox-tests-ios.outputs.status_9 }} | |
| status_10: ${{ needs.detox-tests-ios.outputs.status_10 }} | |
| status_11: ${{ needs.detox-tests-ios.outputs.status_11 }} | |
| status_12: ${{ needs.detox-tests-ios.outputs.status_12 }} | |
| # allure-report-android: | |
| # name: Allure Report Android | |
| # runs-on: [ledger-live-medium] | |
| # if: ${{ !cancelled() && needs.detox-tests-android.outputs.artifact && inputs.tests_type != 'iOS Only' }} | |
| # outputs: | |
| # report-url: ${{ steps.upload.outputs.report-url }} | |
| # result: ${{ steps.summary.outputs.test_result }} | |
| # finalStatus: ${{ steps.aggregate.outputs.finalStatus }} | |
| # missingShards: ${{ steps.aggregate.outputs.missingShards }} | |
| # needs: [determine-builds, detox-tests-android] | |
| # steps: | |
| # - name: Download Allure Report | |
| # uses: actions/download-artifact@v4 | |
| # with: | |
| # path: android-test-artifacts | |
| # pattern: android-test-artifacts* | |
| # merge-multiple: true | |
| # - uses: LedgerHQ/ledger-live/tools/actions/composites/upload-allure-report@develop | |
| # id: upload | |
| # if: ${{ !cancelled() }} | |
| # with: | |
| # platform: android-e2e | |
| # login: ${{ vars.ALLURE_USERNAME }} | |
| # password: ${{ secrets.ALLURE_LEDGER_LIVE_PASSWORD }} | |
| # path: android-test-artifacts | |
| # report_path_suffix: ${{ github.event_name == 'schedule' && '' || 'manual' }} | |
| # - name: Get summary | |
| # id: summary | |
| # if: ${{ !cancelled() }} | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/get-allure-summary@develop | |
| # with: | |
| # allure-results-path: android-test-artifacts | |
| # platform: android | |
| # - name: Aggregate test results | |
| # id: aggregate | |
| # uses: LedgerHQ/ledger-live/tools/actions/composites/aggregate-shard-results@develop | |
| # with: | |
| # total_shards: ${{ fromJSON(needs.determine-builds.outputs.matrix_android)[0].total }} | |
| # status_1: ${{ needs.detox-tests-android.outputs.status_1 }} | |
| # status_2: ${{ needs.detox-tests-android.outputs.status_2 }} | |
| # status_3: ${{ needs.detox-tests-android.outputs.status_3 }} | |
| # status_4: ${{ needs.detox-tests-android.outputs.status_4 }} | |
| # status_5: ${{ needs.detox-tests-android.outputs.status_5 }} | |
| # status_6: ${{ needs.detox-tests-android.outputs.status_6 }} | |
| # status_7: ${{ needs.detox-tests-android.outputs.status_7 }} | |
| # status_8: ${{ needs.detox-tests-android.outputs.status_8 }} | |
| # status_9: ${{ needs.detox-tests-android.outputs.status_9 }} | |
| # status_10: ${{ needs.detox-tests-android.outputs.status_10 }} | |
| # status_11: ${{ needs.detox-tests-android.outputs.status_11 }} | |
| # status_12: ${{ needs.detox-tests-android.outputs.status_12 }} | |
| # upload-to-xray: | |
| # name: "Test Mobile E2E > XRAY Report" | |
| # runs-on: [ledger-live-medium] | |
| # strategy: | |
| # matrix: | |
| # platform: | |
| # - android | |
| # - ios | |
| # exclude: | |
| # - platform: ${{ github.event.inputs.tests_type == 'Android Only' && 'ios' }} | |
| # | |
| # fail-fast: false | |
| # env: | |
| # XRAY_CLIENT_ID: ${{ secrets.XRAY_CLIENT_ID }} | |
| # XRAY_CLIENT_SECRET: ${{ secrets.XRAY_CLIENT_SECRET }} | |
| # XRAY_API_URL: https://xray.cloud.getxray.app/api/v2 | |
| # JIRA_URL: https://ledgerhq.atlassian.net/browse | |
| # TEST_EXECUTION: ${{ matrix.platform == 'android' && inputs.test_execution_android || inputs.test_execution_ios }} | |
| # needs: [detox-tests-android, detox-tests-ios] | |
| # if: ${{ !cancelled() && inputs.export_to_xray }} | |
| # steps: | |
| # - uses: actions/checkout@v4 | |
| # with: | |
| # ref: ${{ inputs.ref || github.sha }} | |
| # repository: LedgerHQ/ledger-live | |
| # | |
| # - name: Download Allure Results | |
| # uses: actions/download-artifact@v4 | |
| # with: | |
| # path: "artifacts-${{ matrix.platform }}" | |
| # pattern: ${{ matrix.platform }}-test-artifacts-* | |
| # merge-multiple: true | |
| # | |
| # - name: Format Xray results | |
| # run: e2e/mobile/xray.formater.sh artifacts-${{ matrix.platform }} ${{ matrix.platform }} ${{ env.TEST_EXECUTION}} | |
| # | |
| # - name: Upload aggregated xray results | |
| # uses: actions/upload-artifact@v4 | |
| # with: | |
| # retention-days: 1 | |
| # name: xray-reports-${{ matrix.platform }} | |
| # path: "artifacts-${{ matrix.platform }}/xray_report.json" | |
| # | |
| # - name: Authenticate to Xray | |
| # id: authenticate | |
| # run: | | |
| # response=$(curl -H "Content-Type: application/json" -X POST \ | |
| # --data '{"client_id": "${{ env.XRAY_CLIENT_ID }}", "client_secret": "${{ env.XRAY_CLIENT_SECRET }}"}' \ | |
| # ${{ env.XRAY_API_URL }}/authenticate) | |
| # echo "Xray Authentication Response: $response" | |
| # echo "xray_token=$response" >> $GITHUB_OUTPUT | |
| # - name: Publish report on Xray | |
| # id: publish-xray | |
| # run: | | |
| # response=$(curl -H "Content-Type: application/json" \ | |
| # -H "Authorization: Bearer ${{ steps.authenticate.outputs.xray_token }}" \ | |
| # -X POST \ | |
| # --data @artifacts-${{ matrix.platform }}/xray_report.json \ | |
| # ${{ env.XRAY_API_URL }}/import/execution) | |
| # echo "Xray Report Response: $response" | |
| # key=$(echo $response | jq -r '.key') | |
| # echo "xray_key=$key" >> $GITHUB_OUTPUT | |
| # - name: Write Xray report link in summary | |
| # shell: bash | |
| # run: echo "::notice title=${{ matrix.platform }} Xray report URL::${{ env.JIRA_URL }}/${{ steps.publish-xray.outputs.xray_key }}" | |
| # report-on-slack: | |
| # name: "Test Mobile E2E > Slack Report" | |
| # runs-on: ubuntu-22.04 | |
| # needs: [allure-report-android, allure-report-ios] | |
| # if: ${{ !cancelled() && (needs.allure-report-ios.outputs.report-url || needs.allure-report-android.outputs.report-url) }} | |
| # env: | |
| # IOS_STATUS: ${{ needs.allure-report-ios.outputs.finalStatus }} | |
| # IOS_REPORT_URL: ${{ needs.allure-report-ios.outputs.report-url }} | |
| # IOS_MISSING_SHARDS: ${{ needs.allure-report-ios.outputs.missingShards }} | |
| # ANDROID_STATUS: ${{ needs.allure-report-android.outputs.finalStatus }} | |
| # ANDROID_REPORT_URL: ${{ needs.allure-report-android.outputs.report-url }} | |
| # ANDROID_MISSING_SHARDS: ${{ needs.allure-report-android.outputs.missingShards }} | |
| # TESTS_TYPE: ${{ inputs.tests_type }} | |
| # steps: | |
| # - name: format message | |
| # uses: actions/github-script@v7 | |
| # id: message | |
| # with: | |
| # script: | | |
| # const fs = require("fs"); | |
| # const text = "Ledger Live Mobile E2E tests finished"; | |
| # const header = [ | |
| # { | |
| # "type": "header", | |
| # "text": { | |
| # "type": "plain_text", | |
| # "text": ":ledger-logo: Ledger Live Mobile E2E tests results on ${{ inputs.ref || github.ref_name }} - ${{ inputs.speculos_device || 'nanoX' }}", | |
| # "emoji": true | |
| # } | |
| # }, | |
| # { | |
| # "type": "divider" | |
| # } | |
| # ]; | |
| # | |
| # const iOSResult = [ | |
| # { | |
| # "type": "section", | |
| # "text": { | |
| # "type": "mrkdwn", | |
| # "text": `- 🍏 iOS - ${{ inputs.speculos_device }}: ${process.env.IOS_STATUS !== 'success' ? '❌' : '✅'} ${{ needs.allure-report-ios.outputs.result || 'No test results' }}` | |
| # } | |
| # } | |
| # ]; | |
| # | |
| # const androidResult = [ | |
| # { | |
| # "type": "section", | |
| # "text": { | |
| # "type": "mrkdwn", | |
| # "text": `- 🤖 Android - ${{ inputs.speculos_device }}: ${process.env.ANDROID_STATUS !== 'success' ? '❌' : '✅'} ${{ needs.allure-report-android.outputs.result || 'No test results' }}` | |
| # } | |
| # } | |
| # ]; | |
| # | |
| # const iOSInfo = [ | |
| # { | |
| # "type": "mrkdwn", | |
| # "text": process.env.IOS_REPORT_URL ? `*Allure Report iOS*\n<${process.env.IOS_REPORT_URL}|Allure Report iOS>` : '*Allure Report iOS*\nNo Allure Report' | |
| # } | |
| # ]; | |
| # | |
| # const androidInfo = [ | |
| # { | |
| # "type": "mrkdwn", | |
| # "text": process.env.ANDROID_REPORT_URL ? `*Allure Report Android*\n<${process.env.ANDROID_REPORT_URL}|Allure Report Android>` : '*Allure Report Android*\nNo Allure Report' | |
| # } | |
| # ]; | |
| # | |
| # const infoFields = [] | |
| # .concat(${{ env.TESTS_TYPE == 'Android Only' }} ? [] : iOSInfo) | |
| # .concat(${{ env.TESTS_TYPE == 'iOS Only' }} ? [] : androidInfo) | |
| # .concat([ | |
| # { | |
| # "type": "mrkdwn", | |
| # "text": `*Workflow*\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Workflow run>` | |
| # } | |
| # ]); | |
| # | |
| # const infoBlock = [ | |
| # { | |
| # "type": "divider" | |
| # }, | |
| # { | |
| # "type": "section", | |
| # "fields": infoFields | |
| # } | |
| # ]; | |
| # | |
| # // Warning block for failed shards | |
| # const warningBlocks = []; | |
| # if (process.env.IOS_MISSING_SHARDS) { | |
| # warningBlocks.push({ | |
| # "type": "section", | |
| # "text": { | |
| # "type": "mrkdwn", | |
| # "text": `⚠️ *Warning*: iOS - Missing results for shard(s): ${process.env.IOS_MISSING_SHARDS}.` | |
| # } | |
| # }); | |
| # } | |
| # if (process.env.ANDROID_MISSING_SHARDS) { | |
| # warningBlocks.push({ | |
| # "type": "section", | |
| # "text": { | |
| # "type": "mrkdwn", | |
| # "text": `⚠️ *Warning*: Android - Missing results for shard(s): ${process.env.ANDROID_MISSING_SHARDS}.` | |
| # } | |
| # }); | |
| # } | |
| # | |
| # const blocks = [] | |
| # .concat(header) | |
| # .concat(${{ env.TESTS_TYPE == 'Android Only' }} ? [] : iOSResult) | |
| # .concat(${{ env.TESTS_TYPE == 'iOS Only' }} ? [] : androidResult) | |
| # .concat(warningBlocks.length > 0 ? warningBlocks : []) | |
| # .concat(infoBlock); | |
| # | |
| # const result = { | |
| # attachments: [ | |
| # { | |
| # color: process.env.ANDROID_STATUS !== 'success' || (process.env.IOS_STATUS !== 'success' && process.env.ANDROID_ONLY == 'false') | |
| # ? "#FF333C" | |
| # : "#33FF39", | |
| # blocks, | |
| # }, | |
| # ], | |
| # }; | |
| # | |
| # fs.writeFileSync(`./payload-slack-content.json`, JSON.stringify(result, null, 2)); | |
| # - name: post to a Slack channel | |
| # id: slack | |
| # uses: slackapi/slack-github-action@v1.23.0 | |
| # with: | |
| # channel-id: "CTMQ0S5SB" | |
| # payload-file-path: "./payload-slack-content.json" | |
| # env: | |
| # SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }} | |
| # - name: post to a Slack channel | |
| # if: ${{ contains(fromJson('["release"]'), github.ref_name) || contains(fromJson('["release, develop"]'), inputs.ref) || github.event_name == 'schedule' }} | |
| # uses: slackapi/slack-github-action@v1.23.0 | |
| # with: | |
| # channel-id: "C05FKJ7DFAP" | |
| # payload-file-path: "./payload-slack-content.json" | |
| # env: | |
| # SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }} | |
| merge-ios-timings: | |
| name: Merge iOS Timing Files | |
| needs: [determine-builds, detox-tests-ios] | |
| runs-on: ubuntu-24.04 | |
| if: ${{ !cancelled() && (needs.detox-tests-ios.result == 'success' || needs.detox-tests-ios.result == 'failure') }} | |
| steps: | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| id: aws | |
| with: | |
| role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID_PROD }}:role/${{ secrets.AWS_CACHE_ROLE_NAME }} | |
| aws-region: ${{ secrets.AWS_CACHE_REGION }} | |
| - uses: LedgerHQ/ledger-live/tools/actions/composites/merge-e2e-detox-timings@develop | |
| with: | |
| platform: ios | |
| artifacts_dir: e2e/mobile/artifacts | |
| key: ${{ needs.determine-builds.outputs.ios_timing_cache_key }} | |
| aws_access_key_id: ${{ env.AWS_ACCESS_KEY_ID }} | |
| aws_secret_access_key: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| aws_session_token: ${{ env.AWS_SESSION_TOKEN }} | |
| aws_region: ${{ secrets.AWS_CACHE_REGION }} | |
| cache_bucket: ${{ env.cache-bucket }} | |
| github_ref: ${{ github.ref }} | |
| github_run_id: ${{ github.run_id }} | |
| roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} | |
| accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} | |
| # merge-android-timings: | |
| # name: Merge Android Timing Files | |
| # needs: [determine-builds, detox-tests-android] | |
| # runs-on: ubuntu-24.04 | |
| # if: ${{ !cancelled() && (needs.detox-tests-android.result == 'success' || needs.detox-tests-android.result == 'failure') }} | |
| # steps: | |
| # - name: Configure AWS credentials | |
| # uses: aws-actions/configure-aws-credentials@v4 | |
| # id: aws | |
| # with: | |
| # role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID_PROD }}:role/${{ secrets.AWS_CACHE_ROLE_NAME }} | |
| # aws-region: ${{ secrets.AWS_CACHE_REGION }} | |
| # - uses: LedgerHQ/ledger-live/tools/actions/composites/merge-e2e-detox-timings@develop | |
| # with: | |
| # platform: android | |
| # artifacts_dir: e2e/mobile/artifacts | |
| # key: ${{ needs.determine-builds.outputs.android_timing_cache_key }} | |
| # aws_access_key_id: ${{ env.AWS_ACCESS_KEY_ID }} | |
| # aws_secret_access_key: ${{ env.AWS_SECRET_ACCESS_KEY }} | |
| # aws_session_token: ${{ env.AWS_SESSION_TOKEN }} | |
| # aws_region: ${{ secrets.AWS_CACHE_REGION }} | |
| # cache_bucket: ${{ env.cache-bucket }} | |
| # github_ref: ${{ github.ref }} | |
| # github_run_id: ${{ github.run_id }} | |
| # roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} | |
| # accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} |