diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 85ec13707a31..3960da8db423 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -9,6 +9,8 @@ self-hosted-runner: - "macos-15" - "ghcr.io/cirruslabs/macos-runner:sequoia" - "ghcr.io/cirruslabs/macos-runner:sequoia-xl" + - "ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg" + - "ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-xl" - "low-priority" # Configuration variables in array of strings defined in your repository or diff --git a/.github/workflows/temp-android-workflow.yml b/.github/workflows/temp-android-workflow.yml new file mode 100644 index 000000000000..8f91735a5d5e --- /dev/null +++ b/.github/workflows/temp-android-workflow.yml @@ -0,0 +1,43 @@ +# Temporary workflow to test Android builds and E2E tests on Cirrus Ubuntu runners + +name: TEMPORARY Android Workflow (Cirrus Testing) + +on: + push: + branches: [main] + pull_request: + + schedule: + - cron: '0 2-6 * * *' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ !(contains(github.ref, 'refs/heads/main') || contains(github.ref, 'refs/heads/stable')) }} + +jobs: + needs_e2e_build: + name: "Detect Mobile Build Changes" + if: ${{ github.event_name != 'merge_group' }} + uses: ./.github/workflows/needs-e2e-build.yml + + build-android-apps: + name: "Build Android Apps (Cirrus)" + if: ${{ github.event_name != 'merge_group' && needs.needs_e2e_build.outputs.android_changed == 'true' }} + permissions: + contents: read + id-token: write + needs: [needs_e2e_build] + uses: ./.github/workflows/temp-build-android-e2e-cirrus.yml + secrets: inherit + + e2e-smoke-tests-android: + name: "Android E2E Smoke Tests (Cirrus)" + if: ${{ github.event_name != 'merge_group' && needs.needs_e2e_build.outputs.android_changed == 'true' }} + permissions: + contents: read + id-token: write + needs: [needs_e2e_build, build-android-apps] + uses: ./.github/workflows/temp-run-e2e-smoke-tests-android-cirrus.yml + with: + changed_files: ${{ needs.needs_e2e_build.outputs.changed_files }} + secrets: inherit diff --git a/.github/workflows/temp-build-android-e2e-cirrus.yml b/.github/workflows/temp-build-android-e2e-cirrus.yml new file mode 100644 index 000000000000..b314cfb9ba1c --- /dev/null +++ b/.github/workflows/temp-build-android-e2e-cirrus.yml @@ -0,0 +1,148 @@ +# TEMPORARY Cirrus-specific Android E2E build workflow - builds APKs using Cirrus Ubuntu runners +# Temporary workflow for testing Cirrus runners vs self-hosted + +name: TEMP Build Android E2E APKs (Cirrus) + +on: + workflow_call: + outputs: + apk-uploaded: + description: 'Whether the APK was successfully uploaded' + value: ${{ jobs.build-android-apks-cirrus.outputs.apk-uploaded }} + aab-uploaded: + description: 'Whether the AAB was successfully uploaded' + value: ${{ jobs.build-android-apks-cirrus.outputs.aab-uploaded }} + sourcemap-uploaded: + description: 'Whether the sourcemap was successfully uploaded' + value: ${{ jobs.build-android-apks-cirrus.outputs.sourcemap-uploaded }} + +jobs: + build-android-apks-cirrus: + name: Build Android E2E APKs (Cirrus) + runs-on: ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-xl + env: + GRADLE_USER_HOME: /home/admin/_work/.gradle + outputs: + apk-uploaded: ${{ steps.upload-apk.outcome == 'success' }} + aab-uploaded: ${{ steps.upload-aab.outcome == 'success' }} + sourcemap-uploaded: ${{ steps.upload-sourcemap.outcome == 'success' }} + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Install Android System Images + run: | + echo "📱 Installing Android system images for AVD..." + "$ANDROID_SDK_ROOT"/cmdline-tools/latest/bin/sdkmanager "system-images;android-34;google_apis;x86_64" + echo "✅ System images installed" + + - name: Setup Android Build Environment + uses: MetaMask/github-tools/.github/actions/setup-e2e-env@2e4ce39610e441f28d50f30af8725ecf6bd540b8 + with: + platform: android + setup-simulator: false + configure-keystores: true + target: qa + + - name: Cache Gradle dependencies + uses: actions/cache@v4 + with: + path: | + /home/admin/_work/.gradle/caches + /home/admin/_work/.gradle/wrapper + android/.gradle + key: gradle-cirrus-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + gradle-cirrus-${{ runner.os }}- + + - name: Setup project dependencies with retry + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 #v3.0.2 + with: + timeout_minutes: 10 + max_attempts: 3 + retry_wait_seconds: 30 + command: | + echo "🚀 Setting up project..." + yarn setup:github-ci --no-build-ios + + - name: Build Android E2E APKs + run: | + echo "🏗 Building Android E2E APKs on Cirrus..." + export NODE_OPTIONS="--max-old-space-size=8192" + cp android/gradle.properties.github android/gradle.properties + yarn build:android:main:e2e + shell: bash + env: + PLATFORM: android + METAMASK_ENVIRONMENT: qa + METAMASK_BUILD_TYPE: main + IS_TEST: true + E2E: 'true' + IGNORE_BOXLOGS_DEVELOPMENT: true + GITHUB_CI: 'true' + CI: 'true' + NODE_OPTIONS: '--max-old-space-size=8192' + MM_UNIFIED_SWAPS_ENABLED: 'true' + MM_BRIDGE_ENABLED: 'true' + BRIDGE_USE_DEV_APIS: 'true' + RAMP_INTERNAL_BUILD: 'true' + SEEDLESS_ONBOARDING_ENABLED: 'true' + MM_NOTIFICATIONS_UI_ENABLED: 'true' + MM_SECURITY_ALERTS_API_ENABLED: 'true' + MM_REMOVE_GLOBAL_NETWORK_SELECTOR: 'true' + BLOCKAID_FILE_CDN: 'static.cx.metamask.io/api/v1/confirmations/ppom' + FEATURES_ANNOUNCEMENTS_ACCESS_TOKEN: ${{ secrets.FEATURES_ANNOUNCEMENTS_ACCESS_TOKEN }} + FEATURES_ANNOUNCEMENTS_SPACE_ID: ${{ secrets.FEATURES_ANNOUNCEMENTS_SPACE_ID }} + SEGMENT_WRITE_KEY_QA: ${{ secrets.SEGMENT_WRITE_KEY_QA }} + SEGMENT_PROXY_URL_QA: ${{ secrets.SEGMENT_PROXY_URL_QA }} + SEGMENT_DELETE_API_SOURCE_ID_QA: ${{ secrets.SEGMENT_DELETE_API_SOURCE_ID_QA }} + SEGMENT_REGULATIONS_ENDPOINT_QA: ${{ secrets.SEGMENT_REGULATIONS_ENDPOINT_QA }} + MM_SENTRY_DSN_TEST: ${{ secrets.MM_SENTRY_DSN_TEST }} + MM_SENTRY_AUTH_TOKEN: ${{ secrets.MM_SENTRY_AUTH_TOKEN }} + MAIN_IOS_GOOGLE_CLIENT_ID_UAT: ${{ secrets.MAIN_IOS_GOOGLE_CLIENT_ID_UAT }} + MAIN_IOS_GOOGLE_REDIRECT_URI_UAT: ${{ secrets.MAIN_IOS_GOOGLE_REDIRECT_URI_UAT }} + MAIN_ANDROID_APPLE_CLIENT_ID_UAT: ${{ secrets.MAIN_ANDROID_APPLE_CLIENT_ID_UAT }} + MAIN_ANDROID_GOOGLE_CLIENT_ID_UAT: ${{ secrets.MAIN_ANDROID_GOOGLE_CLIENT_ID_UAT }} + MAIN_ANDROID_GOOGLE_SERVER_CLIENT_ID_UAT: ${{ secrets.MAIN_ANDROID_GOOGLE_SERVER_CLIENT_ID_UAT }} + GOOGLE_SERVICES_B64_IOS: ${{ secrets.GOOGLE_SERVICES_B64_IOS }} + GOOGLE_SERVICES_B64_ANDROID: ${{ secrets.GOOGLE_SERVICES_B64_ANDROID }} + MM_INFURA_PROJECT_ID: ${{ secrets.MM_INFURA_PROJECT_ID }} + + - name: Upload Android APK + id: upload-apk + uses: actions/upload-artifact@v4 + with: + name: app-prod-release-cirrus.apk + path: android/app/build/outputs/apk/prod/release/app-prod-release.apk + retention-days: 7 + if-no-files-found: error + + - name: Upload Android Test APK + id: upload-test-apk + uses: actions/upload-artifact@v4 + with: + name: app-prod-release-androidTest-cirrus.apk + path: android/app/build/outputs/apk/androidTest/prod/release/app-prod-release-androidTest.apk + retention-days: 7 + if-no-files-found: error + + - name: Upload Android AAB + id: upload-aab + uses: actions/upload-artifact@v4 + with: + name: app-prod-release-cirrus.aab + path: android/app/build/outputs/bundle/prodRelease/app-prod-release.aab + retention-days: 7 + if-no-files-found: warn + continue-on-error: true + + - name: Upload Android Source Map + id: upload-sourcemap + uses: actions/upload-artifact@v4 + with: + name: index.android.bundle-cirrus.map + path: sourcemaps/android/index.android.bundle.map + retention-days: 7 + if-no-files-found: warn + continue-on-error: true diff --git a/.github/workflows/temp-run-e2e-smoke-tests-android-cirrus.yml b/.github/workflows/temp-run-e2e-smoke-tests-android-cirrus.yml new file mode 100644 index 000000000000..5eedc2bfcdeb --- /dev/null +++ b/.github/workflows/temp-run-e2e-smoke-tests-android-cirrus.yml @@ -0,0 +1,211 @@ +name: TEMP Android E2E Smoke Tests (Cirrus) + +on: + workflow_call: + inputs: + changed_files: + description: 'Changed files' + required: false + type: string + default: '' + +permissions: + contents: read + id-token: write + +jobs: + confirmations-android-smoke: + strategy: + matrix: + split: [1, 2, 3] + fail-fast: false + uses: ./.github/workflows/temp-run-e2e-workflow-cirrus.yml + with: + test-suite-name: confirmations-android-smoke-cirrus-${{ matrix.split }} + platform: android + test_suite_tag: "SmokeConfirmations" + split_number: ${{ matrix.split }} + total_splits: 3 + changed_files: ${{ inputs.changed_files }} + secrets: inherit + + trade-android-smoke: + strategy: + matrix: + split: [1, 2] + fail-fast: false + uses: ./.github/workflows/temp-run-e2e-workflow-cirrus.yml + with: + test-suite-name: trade-android-smoke-cirrus-${{ matrix.split }} + platform: android + test_suite_tag: "SmokeTrade" + split_number: ${{ matrix.split }} + total_splits: 2 + changed_files: ${{ inputs.changed_files }} + secrets: inherit + + wallet-platform-android-smoke: + strategy: + matrix: + split: [1, 2] + fail-fast: false + uses: ./.github/workflows/temp-run-e2e-workflow-cirrus.yml + with: + test-suite-name: wallet-platform-android-smoke-cirrus-${{ matrix.split }} + platform: android + test_suite_tag: "SmokeWalletPlatform" + split_number: ${{ matrix.split }} + total_splits: 2 + changed_files: ${{ inputs.changed_files }} + secrets: inherit + + identity-android-smoke: + strategy: + matrix: + split: [1, 2] + fail-fast: false + uses: ./.github/workflows/temp-run-e2e-workflow-cirrus.yml + with: + test-suite-name: identity-android-smoke-cirrus-${{ matrix.split }} + platform: android + test_suite_tag: "SmokeIdentity" + split_number: ${{ matrix.split }} + total_splits: 2 + changed_files: ${{ inputs.changed_files }} + secrets: inherit + + accounts-android-smoke: + strategy: + matrix: + split: [1, 2] + fail-fast: false + uses: ./.github/workflows/temp-run-e2e-workflow-cirrus.yml + with: + test-suite-name: accounts-android-smoke-cirrus-${{ matrix.split }} + platform: android + test_suite_tag: "SmokeAccounts" + split_number: ${{ matrix.split }} + total_splits: 2 + changed_files: ${{ inputs.changed_files }} + secrets: inherit + + network-abstraction-android-smoke: + strategy: + matrix: + split: [1, 2] + fail-fast: false + uses: ./.github/workflows/temp-run-e2e-workflow-cirrus.yml + with: + test-suite-name: network-abstraction-android-smoke-cirrus-${{ matrix.split }} + platform: android + test_suite_tag: "SmokeNetworkAbstractions" + split_number: ${{ matrix.split }} + total_splits: 2 + changed_files: ${{ inputs.changed_files }} + secrets: inherit + + network-expansion-android-smoke: + strategy: + matrix: + split: [1, 2] + fail-fast: false + uses: ./.github/workflows/temp-run-e2e-workflow-cirrus.yml + with: + test-suite-name: network-expansion-android-smoke-cirrus-${{ matrix.split }} + platform: android + test_suite_tag: "SmokeNetworkExpansion" + split_number: ${{ matrix.split }} + total_splits: 2 + changed_files: ${{ inputs.changed_files }} + secrets: inherit + + confirmations-redesigned-android-smoke: + strategy: + matrix: + split: [1, 2] + fail-fast: false + uses: ./.github/workflows/temp-run-e2e-workflow-cirrus.yml + with: + test-suite-name: confirmations-redesigned-android-smoke-cirrus-${{ matrix.split }} + platform: android + test_suite_tag: "SmokeConfirmationsRedesigned" + split_number: ${{ matrix.split }} + total_splits: 2 + changed_files: ${{ inputs.changed_files }} + secrets: inherit + + report-android-smoke-tests: + name: Report Android Smoke Tests (Cirrus) + runs-on: ubuntu-latest + if: ${{ !cancelled() }} + needs: + - confirmations-android-smoke + - trade-android-smoke + - wallet-platform-android-smoke + - identity-android-smoke + - accounts-android-smoke + - network-abstraction-android-smoke + - network-expansion-android-smoke + - confirmations-redesigned-android-smoke + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + + - name: Download all test results + uses: actions/download-artifact@v4 + with: + path: all-test-results/ + pattern: "*-android-*-cirrus-*-test-results" + + - name: Post Test Report + uses: dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3 + with: + name: "Android E2E Smoke Test Results (Cirrus)" + path: "all-test-results/**/*.xml" + reporter: "jest-junit" + fail-on-error: false + list-suites: "failed" + list-tests: "failed" + + - name: Create mobile test report + id: create-json-report + continue-on-error: true + run: | + # Create a temporary directory for xml2js to avoid conflicts + mkdir -p temp-deps && cd temp-deps + npm init -y + npm install xml2js@0.5.0 --no-audit --no-fund + + # Copy node_modules to workspace + cp -r node_modules ${{ github.workspace }}/ + + # Run the mobile test report generator + cd ${{ github.workspace }} + TEST_RESULTS_PATH=all-test-results \ + TEST_RUNS_PATH=test/test-results/test-runs-android-cirrus.json \ + RUN_ID=${{ github.run_id }} \ + PR_NUMBER=${{ github.event.pull_request.number || '0' }} \ + GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \ + node .github/scripts/create-e2e-test-report.mjs + + # Clean up temporary node_modules + rm -rf node_modules + + - name: Upload test runs JSON + if: steps.create-json-report.outcome == 'success' + uses: actions/upload-artifact@v4 + with: + name: test-e2e-android-cirrus-report + path: test/test-results/test-runs-android-cirrus.json + + - name: Upload merged XML report + uses: actions/upload-artifact@v4 + with: + name: android-cirrus-merged-test-report + path: all-test-results/**/*.xml diff --git a/.github/workflows/temp-run-e2e-workflow-cirrus.yml b/.github/workflows/temp-run-e2e-workflow-cirrus.yml new file mode 100644 index 000000000000..884d5a1ce477 --- /dev/null +++ b/.github/workflows/temp-run-e2e-workflow-cirrus.yml @@ -0,0 +1,242 @@ +# TEMPORARY workflow that runs mobile E2E tests on Cirrus runners for testing purposes +# It's a copy of run-e2e-workflow.yml but uses Cirrus Ubuntu runners for Android + +name: TEMP Run E2E (Cirrus) + +on: + workflow_call: + inputs: + test-suite-name: + description: 'Name of the test suite' + required: true + type: string + platform: + description: 'Platform to test (ios or android)' + required: true + type: string + test_suite_tag: + description: 'The Cucumber tag expression to use for filtering tests' + required: true + type: string + split_number: + description: 'Which split number to run (1-based index)' + required: false + type: number + default: 1 + total_splits: + description: 'Total number of splits to divide tests into' + required: false + type: number + default: 1 + test-timeout-minutes: + description: 'The timeout in minutes for the test command' + required: false + type: number + default: 30 + changed_files: + description: 'Changed files' + required: false + type: string + default: '' + +jobs: + test-e2e-mobile: + name: ${{ inputs.test-suite-name }} + runs-on: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg' + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.platform }}-${{ inputs.test-suite-name }}-${{ inputs.split_number }} + cancel-in-progress: ${{ !(contains(github.ref, 'refs/heads/main') || contains(github.ref, 'refs/heads/stable')) }} + + env: + PREBUILT_IOS_APP_PATH: artifacts/MetaMask.app + METAMASK_ENVIRONMENT: 'qa' + METAMASK_BUILD_TYPE: 'main' + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PLATFORM: ${{ inputs.platform }} + TEST_SUITE_TAG: ${{ inputs.test_suite_tag }} + CHANGED_FILES: ${{ inputs.changed_files }} + GITHUB_CI: 'true' + SPLIT_NUMBER: ${{ inputs.split_number }} + TOTAL_SPLITS: ${{ inputs.total_splits }} + MM_UNIFIED_SWAPS_ENABLED: 'true' + RAMP_INTERNAL_BUILD: 'true' + MM_BRIDGE_ENABLED: 'true' + BRIDGE_USE_DEV_APIS: 'true' + MM_SECURITY_ALERTS_API_ENABLED: 'true' + MM_NOTIFICATIONS_UI_ENABLED: 'true' + FEATURES_ANNOUNCEMENTS_ACCESS_TOKEN: ${{ secrets.FEATURES_ANNOUNCEMENTS_ACCESS_TOKEN }} + FEATURES_ANNOUNCEMENTS_SPACE_ID: ${{ secrets.FEATURES_ANNOUNCEMENTS_SPACE_ID }} + MM_TEST_WALLET_SRP: ${{ secrets.MM_TEST_WALLET_SRP }} + SEEDLESS_ONBOARDING_ENABLED: 'true' + MM_REMOVE_GLOBAL_NETWORK_SELECTOR: 'true' + SEGMENT_WRITE_KEY_QA: ${{ secrets.SEGMENT_WRITE_KEY_QA }} + SEGMENT_PROXY_URL_QA: ${{ secrets.SEGMENT_PROXY_URL_QA }} + SEGMENT_DELETE_API_SOURCE_ID_QA: ${{ secrets.SEGMENT_DELETE_API_SOURCE_ID_QA }} + MAIN_IOS_GOOGLE_CLIENT_ID_UAT: ${{ secrets.MAIN_IOS_GOOGLE_CLIENT_ID_UAT }} + MAIN_IOS_GOOGLE_REDIRECT_URI_UAT: ${{ secrets.MAIN_IOS_GOOGLE_REDIRECT_URI_UAT }} + MAIN_ANDROID_APPLE_CLIENT_ID_UAT: ${{ secrets.MAIN_ANDROID_APPLE_CLIENT_ID_UAT }} + MAIN_ANDROID_GOOGLE_CLIENT_ID_UAT: ${{ secrets.MAIN_ANDROID_GOOGLE_CLIENT_ID_UAT }} + MAIN_ANDROID_GOOGLE_SERVER_CLIENT_ID_UAT: ${{ secrets.MAIN_ANDROID_GOOGLE_SERVER_CLIENT_ID_UAT }} + SEGMENT_REGULATIONS_ENDPOINT_QA: ${{ secrets.SEGMENT_REGULATIONS_ENDPOINT_QA }} + MM_SENTRY_DSN_TEST: ${{ secrets.MM_SENTRY_DSN_TEST }} + MM_SENTRY_AUTH_TOKEN: ${{ secrets.MM_SENTRY_AUTH_TOKEN }} + GOOGLE_SERVICES_B64_IOS: ${{ secrets.GOOGLE_SERVICES_B64_IOS }} + GOOGLE_SERVICES_B64_ANDROID: ${{ secrets.GOOGLE_SERVICES_B64_ANDROID }} + MM_SOLANA_E2E_TEST_SRP: ${{ secrets.MM_SOLANA_E2E_TEST_SRP }} + MM_INFURA_PROJECT_ID: ${{ secrets.MM_INFURA_PROJECT_ID }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'merge_group' && github.event.merge_group.head_sha || github.event.pull_request.head.sha || github.sha }} + clean: true + fetch-depth: 0 + + - name: Install Android System Images + if: ${{ inputs.platform == 'android' }} + run: | + echo "📱 Installing Android system images for E2E tests..." + "$ANDROID_SDK_ROOT"/cmdline-tools/latest/bin/sdkmanager "system-images;android-34;google_apis;x86_64" + echo "✅ System images installed" + + - name: Set up E2E environment + uses: MetaMask/github-tools/.github/actions/setup-e2e-env@2e4ce39610e441f28d50f30af8725ecf6bd540b8 + with: + platform: ${{ inputs.platform }} + setup-simulator: ${{ inputs.platform == 'ios' }} + android-avd-name: emulator + configure-keystores: false + + - name: Build Detox framework cache (iOS) + if: ${{ inputs.platform == 'ios' }} + run: | + echo "Building Detox framework cache for iOS..." + yarn detox clean-framework-cache + yarn detox build-framework-cache + + - name: Setup Android artifacts from build job + if: ${{ inputs.platform == 'android' }} + run: | + echo "🏗 Setting up Android artifacts from build job (Cirrus)..." + + # Create required directories + mkdir -p android/app/build/outputs/apk/prod/release/ + + - name: Download Android build artifacts + if: ${{ inputs.platform == 'android' }} + uses: actions/download-artifact@v4 + with: + path: artifacts/ + + - name: Move Android artifacts to expected locations + if: ${{ inputs.platform == 'android' }} + run: | + # Move main APK (Cirrus-specific artifact names) + if [[ -f "artifacts/app-prod-release-cirrus.apk/app-prod-release.apk" ]]; then + mkdir -p "android/app/build/outputs/apk/prod/release/" + cp "artifacts/app-prod-release-cirrus.apk/app-prod-release.apk" "android/app/build/outputs/apk/prod/release/" + echo "✅ Android main APK ready for E2E tests (Cirrus)" + else + echo "❌ Android main APK not found (Cirrus artifacts)" + ls -la artifacts/ + exit 1 + fi + + # Move test APK (Cirrus-specific artifact names) + if [[ -f "artifacts/app-prod-release-androidTest-cirrus.apk/app-prod-release-androidTest.apk" ]]; then + mkdir -p "android/app/build/outputs/apk/androidTest/prod/release/" + cp "artifacts/app-prod-release-androidTest-cirrus.apk/app-prod-release-androidTest.apk" "android/app/build/outputs/apk/androidTest/prod/release/" + echo "✅ Android test APK ready for E2E tests (Cirrus)" + else + echo "❌ Android test APK not found (Cirrus artifacts)" + ls -la artifacts/ + exit 1 + fi + + - name: Setup iOS artifacts from build job + if: ${{ inputs.platform == 'ios' }} + run: | + echo "🏗 Setting up iOS artifacts from build job..." + + # Create required directories + mkdir -p ios/build/Build/Products/Release-iphonesimulator/ + + - name: Download iOS build artifacts + if: ${{ inputs.platform == 'ios' }} + uses: actions/download-artifact@v4 + with: + path: artifacts/ + + - name: Run E2E tests + timeout-minutes: ${{ inputs.test-timeout-minutes }} + run: | + platform="${{ inputs.platform }}" + test_suite_tag="${{ inputs.test_suite_tag }}" + + echo "🚀 Running ${{ inputs.test-suite-name }} tests on $platform (Cirrus runner)" + + # Validate required test suite tag + if [[ -z "$test_suite_tag" ]]; then + echo "❌ Error: test_suite_tag is required for non-api-specs tests" + exit 1 + fi + + export TEST_SUITE_TAG="$test_suite_tag" + echo "Using TEST_SUITE_TAG: $TEST_SUITE_TAG" + + # Run tests (Detox/Jest handle retries internally) + echo "🚀 Starting E2E tests..." + + # Always use the splitting script (handles both split and non-split cases) + echo "Running split ${{ inputs.split_number }} of ${{ inputs.total_splits }}" + + node .github/scripts/run-e2e-tags-gha.mjs + + echo "✅ Test execution completed" + env: + JOB_NAME: ${{ inputs.test-suite-name }} + RUN_ID: ${{ github.run_id }} + PR_NUMBER: ${{ github.event.pull_request.number || '' }} + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.test-suite-name }}-test-results + path: e2e/reports/ + retention-days: 7 + + - name: Prepare screenshots + if: failure() + run: | + echo "🔎 Pruning artifacts while preserving platform Detox artifacts and debug assets..." + + case "${{ inputs.platform }}" in + android) + KEEP_PREFIX="android" + ;; + ios) + KEEP_PREFIX="ios" + ;; + *) + echo "⚠️ Unknown platform '${{ inputs.platform }}'; skipping pruning to avoid accidental deletion." + exit 0 + ;; + esac + + # Remove all artifacts except the ones that match the keep prefix. We should later on improve this to avoid having rm -rf references. + find artifacts -mindepth 1 -prune \ + ! -name "${KEEP_PREFIX}*" \ + ! -name 'coverage-*' \ + -exec echo "Removing:" {} \; \ + -exec rm -rf {} + 2>/dev/null || true + continue-on-error: true + + - name: Upload screenshots + if: failure() + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.test-suite-name }}-screenshots + path: artifacts/ + retention-days: 7 diff --git a/.github/workflows/test-android-build-app.yml b/.github/workflows/test-android-build-app.yml index 8c3c8346a6f7..5a91cbf76ec6 100644 --- a/.github/workflows/test-android-build-app.yml +++ b/.github/workflows/test-android-build-app.yml @@ -28,6 +28,12 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 + - name: Install Android System Images + run: | + echo "📱 Installing Android system images for AVD..." + "$ANDROID_SDK_ROOT"/cmdline-tools/latest/bin/sdkmanager "system-images;android-34;google_apis;x86_64" + echo "✅ System images installed" + # Install Android SDK, Node.js, and other Android development dependencies - name: Installing Android Environment Setup # uses: MetaMask/github-tools/.github/actions/setup-e2e-env@e2e-env-actions diff --git a/android/app/src/androidTest/java/com/metamask/DetoxTest.java b/android/app/src/androidTest/java/com/metamask/DetoxTest.java index 3ae641c90efc..83f6f15a6617 100644 --- a/android/app/src/androidTest/java/com/metamask/DetoxTest.java +++ b/android/app/src/androidTest/java/com/metamask/DetoxTest.java @@ -17,7 +17,7 @@ public class DetoxTest { @Rule public ActivityTestRule mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false); - + @Test public void runDetoxTests() { DetoxConfig detoxConfig = new DetoxConfig();