-
Notifications
You must be signed in to change notification settings - Fork 4k
143 lines (137 loc) · 6.71 KB
/
Copy pathmain.yml
File metadata and controls
143 lines (137 loc) · 6.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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