Capture Android emulator logcat output - #3627
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3627 +/- ##
==========================================
+ Coverage 62.50% 62.56% +0.07%
==========================================
Files 1008 1008
Lines 45815 45864 +49
Branches 9649 9655 +6
==========================================
+ Hits 28630 28691 +61
+ Misses 15724 15714 -10
+ Partials 1461 1459 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
7945c7d to
6c0f797
Compare
There was a problem hiding this comment.
Pull request overview
Adds early, continuous Android emulator logcat capture during eas/start_android_emulator so logs are preserved even if the emulator dies before later diagnostics can run.
Changes:
- Introduces a build-logs staging directory for Android emulator logcat output.
- Starts
adb logcat -v threadtimestreaming immediately after each emulator boot and writes output to staged files. - Adds/updates unit tests for the new streaming behavior and step integration.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| packages/build-tools/src/utils/AndroidEmulatorUtils.ts | Adds logcat staging path helper and startLogcatStreamingAsync implementation. |
| packages/build-tools/src/steps/functions/startAndroidEmulator.ts | Starts logcat streaming for each emulator (including clones) using the build logs staging directory. |
| packages/build-tools/src/utils/tests/AndroidEmulatorUtils.test.ts | Adds unit tests for logcat streaming success/failure. |
| packages/build-tools/src/steps/functions/tests/startAndroidEmulator.test.ts | Updates mocks/assertions to cover logcat streaming integration and failure tolerance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const safeSerialId = serialId.replace(/[^a-zA-Z0-9_.-]/g, '_'); | ||
| const outputPath = path.join(outputDir, `${child.pid}-${safeSerialId}.log`); | ||
| const writeStream = fs.createWriteStream(outputPath); | ||
| child.stdout.pipe(writeStream); | ||
| child.stdout.on('error', err => { | ||
| logger.warn({ err }, `Failed to read Android emulator logcat for ${serialId}.`); | ||
| }); | ||
| writeStream.on('error', err => { | ||
| logger.warn({ err }, `Failed to write Android emulator logcat for ${serialId}.`); | ||
| }); | ||
| child.on('close', () => { | ||
| writeStream.end(); | ||
| }); | ||
| child.unref(); | ||
|
|
||
| void logcatPromise.catch(err => { | ||
| logger.warn({ err }, `Android emulator logcat stream for ${serialId} stopped.`); | ||
| }); | ||
|
|
||
| logger.info(`Streaming Android emulator logcat for ${serialId} to ${outputPath}.`); | ||
|
|
||
| return { outputPath }; | ||
| } catch (err) { |
There was a problem hiding this comment.
Keeping this as-is intentionally. We split the work so PR 1 only starts staging logcat for every emulator, and PR 2 only copies the staged .log files into Maestro artifacts. The collection step no longer stops logcat or needs per-stream metadata, so returning outputPath is enough for this branch and avoids reintroducing the metadata/stop path we explicitly removed in the follow-up PR.
There was a problem hiding this comment.
Pull request overview
This PR adds best-effort, continuous adb logcat streaming for Android emulators started by the eas/start_android_emulator build function, writing output into a predictable subdirectory under the build logs directory so logs are preserved even if the emulator disappears later.
Changes:
- Added
AndroidEmulatorUtils.startLogcatStreamingAsyncto startadb logcat -v threadtimestreaming into a staged.logfile. - Added
AndroidEmulatorUtils.getLogcatStagingDirectoryPathand wired it intoeas/start_android_emulatorso every started emulator begins streaming logcat immediately. - Added/updated unit tests covering the streaming behavior and the build function integration.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/build-tools/src/utils/AndroidEmulatorUtils.ts | Adds logcat staging path helper and a new async helper to start streaming logcat to a file. |
| packages/build-tools/src/utils/tests/AndroidEmulatorUtils.test.ts | Adds tests validating logcat streaming writes to a staged file and handles spawn failures. |
| packages/build-tools/src/steps/functions/startAndroidEmulator.ts | Starts logcat streaming for base emulators and clones immediately after each startAsync. |
| packages/build-tools/src/steps/functions/tests/startAndroidEmulator.test.ts | Updates mocks/assertions to verify logcat streaming is invoked during emulator startup and failures don’t block readiness waits. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Adds early, continuous Android emulator adb logcat streaming to a predictable staging directory under the build logs directory so logs are preserved even if the emulator crashes before later diagnostics.
Changes:
- Add
AndroidEmulatorUtils.getLogcatStagingDirectoryPath()andAndroidEmulatorUtils.startLogcatStreamingAsync()to start and persist logcat streaming to disk. - Invoke logcat streaming during base emulator startup and during clone startup in
eas/start_android_emulator. - Add unit tests for the new utility and update
startAndroidEmulatorstep tests to assert logcat streaming behavior and ordering.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/build-tools/src/utils/tests/AndroidEmulatorUtils.test.ts | Adds tests for startLogcatStreamingAsync and temp-dir cleanup. |
| packages/build-tools/src/utils/AndroidEmulatorUtils.ts | Introduces logcat staging path helper and streaming implementation. |
| packages/build-tools/src/steps/functions/startAndroidEmulator.ts | Starts logcat streaming as part of emulator bring-up (base + clones). |
| packages/build-tools/src/steps/functions/tests/startAndroidEmulator.test.ts | Extends step tests to cover logcat streaming calls and failure tolerance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
This PR adds continuous adb logcat streaming for Android emulators started by the eas/start_android_emulator build function, staging log output under the build logs directory so logs survive emulator crashes.
Changes:
- Add
AndroidEmulatorUtils.getLogcatStagingDirectoryPath()andstartLogcatStreamingAsync()to streamadb logcat -v threadtimeinto staged files. - Wire logcat streaming into the emulator startup flow (including cloned emulators).
- Add unit tests for the new utility and update step tests to assert streaming is invoked before readiness checks and that failures don’t block startup.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/build-tools/src/utils/AndroidEmulatorUtils.ts | Introduces staging path helper and logcat streaming implementation. |
| packages/build-tools/src/steps/functions/startAndroidEmulator.ts | Starts logcat streaming immediately after emulator start (base + clones) using the build logs directory. |
| packages/build-tools/src/utils/tests/AndroidEmulatorUtils.test.ts | Adds unit coverage for streaming success and failure paths. |
| packages/build-tools/src/steps/functions/tests/startAndroidEmulator.test.ts | Verifies streaming is invoked for each emulator and does not block startup when it fails. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const childStdout = child.stdout; | ||
| const safeSerialId = serialId.replace(/[^a-zA-Z0-9_.-]/g, '_'); | ||
| const outputPath = path.join(outputDir, `${child.pid}-${safeSerialId}.log`); | ||
| const writeStream = fs.createWriteStream(outputPath); |
7903f38 to
c9deda0
Compare
c9deda0 to
968a67e
Compare
968a67e to
6f014a3
Compare
|
⏩ The changelog entry check has been skipped since the "no changelog" label is present. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (1)
packages/build-tools/src/utils/tests/AndroidEmulatorUtils.test.ts:106
- This assertion uses
rejects.toEqual(new SystemError(..., { cause })), but Jest’s error equality often compares onlyname/messageand may ignore non-enumerable fields likecause. That means the test may pass even if the thrownSystemErrordoes not actually preservemkdirErroras its cause. Prefer asserting the error type/message and separately matchingcauseon the rejected error object.
).rejects.toEqual(
new SystemError('Failed to prepare Android emulator logcat output for eas-simulator.', {
cause: mkdirError,
})
);
Why
Workflow Maestro tests currently collect Android logs with
adb logcatafter the tests. This depends on the ADB server and can lose logs when ADB becomes unavailable.How
-logcat '*:v'and-logcat-outputarguments.logcat_directoryoutput ofeas/start_android_emulator.The matching
expo/universechange copies this output into the Maestro test-results directory before the existing artifact upload.Test Plan
yarn workspace @expo/build-tools jest-unit src/steps/functions/__tests__/startAndroidEmulator.test.ts src/utils/__tests__/AndroidEmulatorUtils.test.ts --runInBandyarn workspace @expo/build-tools typecheckyarn fmt:check