name: Testing E2E Android on: workflow_dispatch: inputs: clearCaches: description: "Clear workflow caches where possible" required: false type: string pull_request: branches: - '**' paths-ignore: - 'docs/**' - 'website/**' - '.spellcheck.dict.txt' # - '**/*.md' push: branches: - master paths-ignore: - 'docs/**' - 'website/**' - '.spellcheck.dict.txt' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: android: name: Android runs-on: macos-12 timeout-minutes: 90 strategy: fail-fast: false matrix: # Refactor to make these dynamic with a low/high bracket only on schedule, not push # For now this is just the fastest combo (api/arch/target/snapshot-warm-time) based on testing api-level: [30] arch: [x86_64] target: [google_apis] first-boot-delay: [600] # This is useful for benchmarking, do 0, 1, 2, etc (up to 256 max job-per-matrix limit) for averages iteration: [0] env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} EMULATOR_COMMAND: "-avd TestingAVD -noaudio -gpu swiftshader_indirect -camera-back none -no-snapshot -no-window -no-boot-anim -nojni -memory 2048 -timezone 'Europe/London' -cores 2" EMULATOR_EXECUTABLE: qemu-system-x86_64-headless steps: - uses: actions/checkout@v3 with: fetch-depth: 50 # Set up tool versions - uses: actions/setup-node@v3 with: node-version: 16 - name: Configure JDK 1.11 uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: '11' # Set path variables needed for caches - name: Set workflow variables id: workflow-variables run: | echo "metro-cache=$HOME/.metro" >> $GITHUB_OUTPUT echo "yarn-cache-dir=$(yarn cache dir)" >> $GITHUB_OUTPUT echo "tempdir=$TMPDIR" >> $GITHUB_OUTPUT - uses: actions/cache@v3 name: Yarn Cache id: yarn-cache with: path: ${{ steps.workflow-variables.outputs.yarn-cache-dir }} key: ${{ runner.os }}-yarn-v1-${{ hashFiles('yarn.lock') }} restore-keys: ${{ runner.os }}-yarn-v1 - name: Yarn Install uses: nick-invision/retry@v2 with: timeout_minutes: 10 retry_wait_seconds: 60 max_attempts: 3 command: DETOX_DISABLE_POSTINSTALL=1 yarn --no-audit --prefer-offline - name: Cache pushy Emulator uses: actions/cache@v3 with: path: ~/.cache/pushy/emulators key: pushy-emulators-v1-${{ github.run_id }} restore-keys: pushy-emulators-v1 - name: Start pushy Emulator run: yarn tests:emulator:start-ci - uses: actions/cache@v3 name: Gradle Cache with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-v1-${{ hashFiles('**/*.gradle*') }} restore-keys: ${{ runner.os }}-gradle-v1 # This appears to be 'Cache Size: ~1230 MB (1290026823 B)' based on watching action logs # Repo limit is 10GB; branch caches are independent; branches may read default branch cache. # We don't want branches to evict master branch snapshot, so save on master, read-only all else - name: AVD cache uses: actions/cache@v3 id: avd-cache with: path: | ~/.android/avd/* ~/.android/adb* key: avd-${{ matrix.api-level }}-${{ matrix.arch }}-${{matrix.target}}-v1-${{ github.event.inputs.clearCaches }} restore-keys: | avd-${{ matrix.api-level }}-${{ matrix.arch }}-${{matrix.target}}-v1 - name: Clear Caches Optionally if: "${{ github.event.inputs.clearCaches != '' }}" shell: bash run: | du -sk ~/.gradle du -sk ~/.android rm -fr ~/.gradle rm -fr ~/.android du -sk ~/.gradle || echo ~/.gradle is gone du -sk ~/.android || echo ~/.android is gone - name: Build Android App uses: nick-invision/retry@v2 with: timeout_minutes: 25 retry_wait_seconds: 60 max_attempts: 3 command: yarn build:android-release - name: Metro Bundler Cache uses: actions/cache@v3 with: path: ${{ steps.workflow-variables.outputs.metro-cache }} key: ${{ runner.os }}-metro-v1-${{ github.run_id }} restore-keys: ${{ runner.os }}-metro-v1 - name: AVD Boot and Snapshot Creation # Only generate a snapshot with a cache miss # Comment the if out to generate snapshots on branch for performance testing if: "${{ github.event.inputs.clearCaches != '' || (steps.avd-cache.outputs.cache-hit != 'true' && github.ref == 'refs/heads/master') }}" uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} avd-name: TestingAVD force-avd-creation: false target: ${{ matrix.target }} arch: ${{ matrix.arch }} emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none sdcard-path-or-size: 100M disable-animations: true # Give the emulator a little time to run and do first boot stuff before taking snapshot script: | $ANDROID_HOME/platform-tools/adb logcat '*:D' -d > adb-snapshot-log.txt $ANDROID_HOME/platform-tools/adb logcat --clear echo "Generated AVD snapshot for caching." # This step is separate so pure install time may be calculated as a step - name: Emulator Snapshot After Firstboot Warmup # Only generate a snapshot for saving with a cache miss # Switch the if statements via comment if generating snapshots for performance testing # if: matrix.first-boot-delay != '0' if: "${{ github.event.inputs.clearCaches != '' || (steps.avd-cache.outputs.cache-hit != 'true' && github.ref == 'refs/heads/master') }}" env: FIRST_BOOT_DELAY: ${{ matrix.first-boot-delay }} uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} avd-name: TestingAVD force-avd-creation: false target: ${{ matrix.target }} arch: ${{ matrix.arch }} emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none sdcard-path-or-size: 100M disable-animations: true # Give the emulator a little time to run and do first boot stuff before taking snapshot # The zygote restart makes sure zygote has correct heap size as a workaround for android emulator init bug script: | $ANDROID_HOME/platform-tools/adb shell su root "setprop ctl.restart zygote" sleep $FIRST_BOOT_DELAY $ANDROID_HOME/platform-tools/adb logcat '*:D' -d > adb-warmup-log.txt $ANDROID_HOME/platform-tools/adb logcat --clear echo "First boot warmup completed." - name: Test Tapper # Run this outside the emulator runner so the emulator runner does not wait on it for cleanup run: | nohup sh -c "until false; do $ANDROID_HOME/platform-tools/adb shell input tap 100 800; sleep 0.2; done" & shell: bash - name: Detox Tests uses: reactivecircus/android-emulator-runner@v2 timeout-minutes: 60 with: api-level: ${{ matrix.api-level }} avd-name: TestingAVD force-avd-creation: false target: ${{ matrix.target }} arch: ${{ matrix.arch }} emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none sdcard-path-or-size: 100M disable-animations: true # Detox uses Espresso to choreograph steps in reaction to UI events, so we need to send a stream of taps. script: | $ANDROID_HOME/platform-tools/adb devices nohup sh -c "$ANDROID_HOME/platform-tools/adb logcat '*:D' > adb-log.txt" & sudo yarn test:android-release