Say whether an object is stuck, and which reference made it so #1482
Workflow file for this run
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: Main | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: read | |
| jobs: | |
| validation: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: gradle/actions/wrapper-validation@0723195856401067f7a2779048b490ace7a47d7c # v5 | |
| checks: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-java@v5 | |
| with: | |
| java-version: 17 | |
| distribution: 'zulu' | |
| - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 | |
| - name: Build project | |
| run: ./gradlew build --stacktrace | |
| instrumentation-tests: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| strategy: | |
| # Allow tests to continue on other devices if they fail on one device. | |
| fail-fast: false | |
| matrix: | |
| arch: [ x86_64 ] | |
| # AOSP images rather than google_apis: nothing here uses Google Play services, and the | |
| # Google apps that only ship in google_apis crash while the device boots. The resulting | |
| # "app has stopped" dialog holds window focus, and then every Espresso interaction fails | |
| # with RootViewWithoutFocusException until something dismisses it. | |
| target: [ default ] | |
| channel: [ stable ] | |
| # One emulator per major Android release, from androidMinSdk up to the newest system image | |
| # that exists. The point releases in between (25, 27, 32) are left out: for everything | |
| # LeakCanary reaches into they behave like the release they follow, so they cost a job and | |
| # cover nothing the neighbouring level doesn't. | |
| api-level: | |
| - 24 | |
| - 26 | |
| - 28 | |
| - 29 | |
| - 30 | |
| - 31 | |
| - 33 | |
| - 34 | |
| - 35 | |
| - 36 | |
| steps: | |
| - name: Enable KVM group perms | |
| run: | | |
| echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules | |
| sudo udevadm control --reload-rules | |
| sudo udevadm trigger --name-match=kvm | |
| ls /dev/kvm | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-java@v5 | |
| with: | |
| java-version: 17 | |
| distribution: 'zulu' | |
| - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 | |
| # Create the AVD and boot it from scratch on every run, rather than restoring a cached | |
| # snapshot. android-emulator-runner decides the device is ready when `getprop | |
| # sys.boot_completed` returns 1 and then immediately sends `input keyevent 82` to dismiss the | |
| # lock screen. `sys.boot_completed` is part of the state a snapshot captures, so on a restored | |
| # device it already reads 1 while adbd and zygote are still coming back, and that keyevent | |
| # races them: it loses often enough that this was the single largest source of red builds, | |
| # SIGKILLed with exit code 137 before the test script started. Booting for real makes the | |
| # readiness check mean something -- the poll then takes ~10s and several attempts -- and it | |
| # also means no run inherits frozen state from another. The snapshot cache saved roughly 20 | |
| # seconds of wall clock and had by then caused three separate classes of failure: stale test | |
| # APKs (#2801), an AVD directory saved from a force-killed emulator (#2855), and a crash | |
| # dialog frozen mid-boot holding window focus. | |
| - name: Instrumentation Tests | |
| uses: reactivecircus/android-emulator-runner@v2 | |
| with: | |
| api-level: ${{ matrix.api-level }} | |
| force-avd-creation: true | |
| target: ${{ matrix.target }} | |
| arch: ${{ matrix.arch }} | |
| emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -no-snapshot-load -no-snapshot-save | |
| script: | | |
| touch emulator.log | |
| chmod 777 emulator.log | |
| adb logcat >> emulator.log & | |
| # Stop a crashing process from putting up a dialog that holds window focus, which | |
| # fails every Espresso interaction with RootViewWithoutFocusException. Defence in | |
| # depth behind the AOSP image, and only on API 30+: ActivityTaskManagerService | |
| # observes this setting and applies it right away, while older releases decide | |
| # whether to show error dialogs from the configuration alone and ignore it. | |
| # `|| true` so this cannot itself become a new source of failures. | |
| adb shell settings put global hide_error_dialogs 1 || true | |
| # Espresso fails every interaction with RootViewWithoutFocusException when some other | |
| # window holds focus, and names only the window it wanted rather than the one that has | |
| # focus. Recording the focused window up front says which one that is. | |
| echo "Focused window before tests: $(adb shell dumpsys window | grep -E 'mCurrentFocus|mFocusedApp')" | |
| ./gradlew leakcanary:leakcanary-android-core:connectedCheck leakcanary:leakcanary-android:connectedCheck leakcanary:leakcanary-android-instrumentation:connectedCheck leakcanary:leakcanary-android-test:connectedCheck --no-build-cache --no-daemon --stacktrace | |
| # Force-kill the emulator before the action's post-step cleanup. | |
| # On API 26, the emulator process can hang for 20+ minutes after receiving | |
| # adb emu kill, causing the job to hit its 30-minute timeout. Killing the | |
| # qemu-system process here ensures the post-cleanup kill check exits immediately. | |
| # The [m] bracket trick avoids pkill matching its own parent shell process | |
| # (whose cmdline contains the literal string "qemu-system" as an argument). | |
| pkill -9 -f "qemu-syste[m]" || true | |
| - name: Upload results | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ${{ matrix.api-level }}-${{ matrix.arch }}-instrumentation-test-results | |
| path: | | |
| emulator.log | |
| ./**/build/reports/androidTests/connected/** | |
| snapshot-deployment: | |
| if: github.repository == 'square/leakcanary' && github.event_name == 'push' | |
| needs: [ checks ] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-java@v5 | |
| with: | |
| java-version: 17 | |
| distribution: 'zulu' | |
| - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 | |
| - name: Deploy snapshot | |
| run: ./gradlew publish | |
| env: | |
| ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }} | |
| ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }} | |
| - name: Cleanup secrets | |
| if: always() | |
| run: rm -rf ~/.gradle/gradle.properties |