diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f419ade..fdd85e95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -133,13 +133,14 @@ jobs: # nothing runs, and Gradle still passes. Gradle uninstalls the app after each run, so # the local network test is run once more, on a fresh install again, if no test started. # The emulator's logs are saved after each run, by save_device_logs.sh, which reconnects - # first if adb lost the emulator during the run. + # first if adb lost the emulator during the run, and prints the lines that matter here + # when the run failed. script: | timeout 600 adb wait-for-device shell 'until pm path android > /dev/null 2>&1 && am get-current-user > /dev/null 2>&1; do sleep 2; done' scripts/smoke_test_release.sh app/build/outputs/apk/play/release/*.apk - for attempt in 1 2; do ./gradlew connectedFdroidDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=de.qspool.clementineremote.LocalNetworkPermissionDeviceTest; status=$?; if [ $status -ne 0 ] || find app/build/outputs/androidTest-results -name 'TEST-*.xml' -exec grep -q ' /dev/null 2>&1 && am get-current-user > /dev/null 2>&1; do sleep 2; done'; done; mkdir -p app/build/localNetworkPermission && cp -r app/build/outputs/androidTest-results app/build/reports/androidTests app/build/localNetworkPermission/; scripts/save_device_logs.sh app/build/localNetworkPermission; exit $status + for attempt in 1 2; do ./gradlew connectedFdroidDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=de.qspool.clementineremote.LocalNetworkPermissionDeviceTest; status=$?; if [ $status -ne 0 ] || find app/build/outputs/androidTest-results -name 'TEST-*.xml' -exec grep -q ' /dev/null 2>&1 && am get-current-user > /dev/null 2>&1; do sleep 2; done'; done; mkdir -p app/build/localNetworkPermission && cp -r app/build/outputs/androidTest-results app/build/reports/androidTests app/build/localNetworkPermission/; scripts/save_device_logs.sh app/build/localNetworkPermission $status; exit $status timeout 600 adb wait-for-device shell 'until pm path android > /dev/null 2>&1 && am get-current-user > /dev/null 2>&1; do sleep 2; done' - ./gradlew connectedFdroidDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.notClass=de.qspool.clementineremote.LocalNetworkPermissionDeviceTest; status=$?; scripts/save_device_logs.sh app/build/reports/androidTests; exit $status + ./gradlew connectedFdroidDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.notClass=de.qspool.clementineremote.LocalNetworkPermissionDeviceTest; status=$?; scripts/save_device_logs.sh app/build/reports/androidTests $status; exit $status # The test report is in the artifact below; the failures go in the log too, to be read # without downloading it. A skipped test is written down as a failure too (see below). - name: Show the failed tests diff --git a/scripts/save_device_logs.sh b/scripts/save_device_logs.sh index 66812390..98170523 100755 --- a/scripts/save_device_logs.sh +++ b/scripts/save_device_logs.sh @@ -7,10 +7,17 @@ # without logs: logcat can't be read from a device adb has lost. So it reconnects first, to save # the logs that say what happened. # -# Usage: save_device_logs.sh +# Given the run's exit status, and it isn't 0, it also prints what the logs say about the +# emulator's state into the job's log, in a group of its own: how long it has been up (a +# restart of Android shows there), its memory, logd's buffers and when the saved logs end, and +# the lines from adbd, the low memory killer, the test runner and crashes. The artifact has the +# whole logcat, but can't be downloaded from everywhere the job's log can be read. +# +# Usage: save_device_logs.sh [exit status of the run] set -uo pipefail dir=$1 +status=${2:-0} mkdir -p "$dir" if [ "$(adb get-state 2> /dev/null)" != device ]; then echo "::warning::adb lost the emulator; reconnecting to save its logs" @@ -18,3 +25,14 @@ if [ "$(adb get-state 2> /dev/null)" != device ]; then timeout 120 adb wait-for-device || echo "::warning::adb couldn't reconnect to the emulator" fi adb logcat -d -b all > "$dir/logcat.txt" + +if [ "$status" -ne 0 ]; then + echo "::group::The emulator's state after the failed run" + adb shell 'uptime; grep -E "^(MemTotal|MemFree|MemAvailable|SwapTotal|SwapFree):" /proc/meminfo; logcat -g' + # The saved logs of one failure ended 90 s before it, a minute after boot: logd's buffers + # (logcat -g, above) and this say whether the logs still reach the end of the run. + echo "The saved logs end at: $(grep -E '^[0-9]{2}-[0-9]{2} ' "$dir/logcat.txt" | cut -c1-18 | sort | tail -n 1)" + grep -E -i 'adbd|lowmemorykiller|lmkd|out of memory|oom-kill|watchdog|FATAL EXCEPTION|AndroidRuntime|TestRunner|am_crash|am_anr|Zygote *:.*(died|crash)|system_server' \ + "$dir/logcat.txt" | tail -n 300 + echo "::endgroup::" +fi