ci(e2e): capture logcat + emulator/system diagnostics across the E2E matrix (#387) #388

Merged
JMR-dev merged 2 commits from ci-387-e2e-diagnostics into main 2026-07-06 21:55:53 +00:00
JMR-dev commented 2026-07-06 20:54:23 +00:00 (Migrated from github.com)

What

Brings the #334 API-37 boot/E2E diagnostics to the e2e matrix (API 29-36) so any flake or failure in an emulator E2E leg is diagnosable. The trigger: E2E (31) recently died on a bare sdkmanager exit 1 with zero diagnostic trail, and emulator flakes across the matrix left nothing behind (the matrix uploaded only its test report).

Scoped to the e2e matrix job only — e2e-preview is deliberately untouched (PR #372 is restructuring/sharding it and it already has these diagnostics). reactivecircus/android-emulator-runner and the existing boot-race retry are kept; diagnostics are added around/inside them (no conversion to manual boot).

Changes (all in the e2e job)

  • Stream logcat per API level — adb logcat -v time > "$RUNNER_TEMP/logcat-api<level>.txt" 2>&1 & at the top of the script: in both the "Run E2E tests" and "Run E2E tests (retry…)" reactivecircus steps (the emulator is booted there). Backgrounded; ./gradlew connectedDebugAndroidTest stays the last foreground command so the step's exit status is still the test result.
  • Failure-time state dump — new if: failure() step prints (each guarded || true) adb devices, adb logcat -d tail, emulator -accel-check, ls -l /dev/kvm, free -h, df -h to the step log and tees them to a diagnostics-api<level>.txt file.
  • Always-upload artifact — new if: always() actions/upload-artifact (same pinned v7 SHA as the rest of the file) named e2e-diagnostics-api<level>, carrying the logcat + diagnostics files, if-no-files-found: warn.
  • SDK-install diagnosability — the E2E (31) failure was sdkmanager exit 1 with no trail. The step now retries up to 3× with backoff (self-heals a transient package-mirror/network hiccup) and prints sdkmanager --list_installed on a hard failure instead of a bare exit 1.

Validation

  • python -m yaml safe-load parses the whole workflow; all e2e steps present and ordered.
  • actionlint passes (exit 0) — expressions, ${{ matrix.api-level }} interpolation, block scalars, if: conditions all valid.
  • git diff --check clean (no whitespace/EOL issues); 5 hunks, all within the e2e job; e2e-preview unchanged.
  • Additive/diagnostic only — no boot-affecting emulator flags changed. The real validation is this PR's own CI run: the matrix must stay green and produce the e2e-diagnostics-api<level> artifacts.

Closes #387.

🤖 Generated with Claude Code

## What Brings the #334 API-37 boot/E2E diagnostics to the **`e2e` matrix (API 29-36)** so any flake or failure in an emulator E2E leg is diagnosable. The trigger: `E2E (31)` recently died on a bare `sdkmanager` exit 1 with **zero** diagnostic trail, and emulator flakes across the matrix left nothing behind (the matrix uploaded only its test report). Scoped to the `e2e` matrix job **only** — `e2e-preview` is deliberately untouched (PR #372 is restructuring/sharding it and it already has these diagnostics). `reactivecircus/android-emulator-runner` and the existing boot-race retry are kept; diagnostics are added around/inside them (no conversion to manual boot). ## Changes (all in the `e2e` job) - **Stream logcat per API level** — `adb logcat -v time > "$RUNNER_TEMP/logcat-api<level>.txt" 2>&1 &` at the top of the `script:` in **both** the "Run E2E tests" and "Run E2E tests (retry…)" reactivecircus steps (the emulator is booted there). Backgrounded; `./gradlew connectedDebugAndroidTest` stays the last foreground command so the step's exit status is still the test result. - **Failure-time state dump** — new `if: failure()` step prints (each guarded `|| true`) `adb devices`, `adb logcat -d` tail, `emulator -accel-check`, `ls -l /dev/kvm`, `free -h`, `df -h` to the step log **and** `tee`s them to a `diagnostics-api<level>.txt` file. - **Always-upload artifact** — new `if: always()` `actions/upload-artifact` (same pinned v7 SHA as the rest of the file) named `e2e-diagnostics-api<level>`, carrying the logcat + diagnostics files, `if-no-files-found: warn`. - **SDK-install diagnosability** — the `E2E (31)` failure was `sdkmanager` exit 1 with no trail. The step now retries up to 3× with backoff (self-heals a transient package-mirror/network hiccup) and prints `sdkmanager --list_installed` on a hard failure instead of a bare exit 1. ## Validation - `python -m yaml` safe-load parses the whole workflow; all `e2e` steps present and ordered. - `actionlint` passes (exit 0) — expressions, `${{ matrix.api-level }}` interpolation, block scalars, `if:` conditions all valid. - `git diff --check` clean (no whitespace/EOL issues); 5 hunks, all within the `e2e` job; `e2e-preview` unchanged. - Additive/diagnostic only — no boot-affecting emulator flags changed. The real validation is this PR's own CI run: the matrix must stay green **and** produce the `e2e-diagnostics-api<level>` artifacts. Closes #387. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.