Repository navigation
[build-tools] Start expo-device-hub with a session token and the website origins - #4578
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4578 +/- ##
==========================================
+ Coverage 74.44% 74.46% +0.03%
==========================================
Files 1029 1029
Lines 50370 50390 +20
Branches 10884 10891 +7
==========================================
+ Hits 37492 37519 +27
+ Misses 11887 11881 -6
+ Partials 991 990 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
gwdp
left a comment
There was a problem hiding this comment.
Requesting changes at Gabe's direction: the Android share-page health-check dependency must ship before enabling --require-token here. See the inline P1 comment.
The P2 token-log issue is covered by #4525: its process-output collector redacts the Hub startup token before returning diagnostics. Please ship that before or together with this change, and add the Android preview token to its mutable secrets list when combining the changes.
Codex reviewed 17fbdfa in an isolated checkout. 110 focused worker tests and 48 CLI utility tests passed. The Hub auth probe returned 401 for /healthz; the website failure was source-traced against Universe main at 5e80ae8fda. Website tests were blocked by the installed mise version; no hosted Android/browser E2E ran. Gabe discussed the findings and directed this review; this does not claim human inspection of the final diff.
— Codex
17fbdfa to
e0ad8de
Compare
|
eas-cli now uses changesets for changelogs (#4580). The required "Check for a changeset" check fails on PRs that edit To update this PR:
The release adds the PR link and the author to the entry. If this PR needs no changelog entry, revert the |
…ite origins Android sessions now start expo-device-hub with --require-token, --cors-origin, and --frame-ancestor, as iOS sessions start serve-sim, and read its session token from the Hub's state file. Needs an expo-device-hub release with expo/expo-device-hub#265. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…host output Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e0ad8de to
bec4c19
Compare
… its token from Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
✅ Thank you for adding a changeset! |
Why
The website streams Android simulator sessions with
@expo/hub-clientfrom its own origin (expo.dev,staging.expo.dev, deploy previews, and local*.expo.testservers). iOS sessions already allow this: the worker starts serve-sim with--require-tokenand--cors-origin/--frame-ancestorfor the website origins, and reads its session token from serve-sim's state file.Android sessions start
expo-device-hubwithout these flags. So the browser blocks most requests from the website, and the Hub runs on the public ngrok tunnel without a token.expo/expo-device-hub#292 (on expo/expo-device-hub#265) gives the Hub
--cors-originwith the same values as serve-sim, includinghttps://*.expo.dev, and expo/expo-device-hub#294 makes the CLI record its session token in a state file, as serve-sim does.How
In
packages/build-tools/src/steps/utils/deviceSessionHost.ts:createExpoDeviceHubArgsadds--require-tokenand the website origin args, in the same places ascreateServeSimArgs.websiteOriginServeSimArgsis renamedwebsiteOriginArgs, because both servers now take it. The values are unchanged./readyz, the host reads the Android session token from${tmpdir}/expo-device-hub/server-<port>.json(readExpoDeviceHubPreviewTokenAsync), as it reads serve-sim's from${tmpdir}/serve-sim/server-<udid>.json. Without a token, the session stops with the same error as on iOS, now naming the server.EXPO_DEVICE_HUB_STATE_DIR. Otherwise the Hub would resolve it from the step's env, and a step env that sets its ownTMPDIRorEXPO_DEVICE_HUB_STATE_DIRwould put the token where the host does not read it./?token=…) is printed before that, and the?token=rule inprocessOutput.tsredacts it.Unchanged: the recording stop route (
/_eas/android-recording/stop) has its own control token, and the Hub leaves it outside the session gate. The Android session preview captures throughadb, not the Hub.Release order: done. The default package is
expo-device-hub@latest, now 0.17.0. It has every change this needs: the state file (expo/expo-device-hub#294) and/healthz(expo/expo-device-hub#307) since 0.16.0, and--cors-origin(expo/expo-device-hub#292, on expo/expo-device-hub#265) since 0.17.0. A session that pins apackageVersionolder than 0.17.0 fails at startup, because that Hub does not know--cors-origin.Test Plan
Run by Claude Code on 2026-10-09:
packages/build-tools:yarn testpassed (1862 passed, 8 skipped). New tests: the Android host startsexpo-device-hubwith--require-tokenand the website origins and reports the token from the state file; it stops when no token was recorded;createExpoDeviceHubArgsappends the website args after the TURN args. The two new host tests failed against the previousdeviceSessionHost.ts.yarn typecheck,yarn lint, andyarn fmt:checkpassed.expo-device-hub --require-token --cors-origin 'https://*.expo.test'wroteserver-3400.json(mode 0600) with the token, allowedhttps://universe-3001.expo.test, refusedhttps://expo.testand other origins, and removed the file on SIGTERM.Run by Claude Code on 2026-10-15, after the rebase onto
main:main's newsecrets.push(previewToken)and moved it after the shared token check, so it covers Android too. The Android secrets test now also checks that the Hub's token is added to the array passed at spawn; it failed with the push limited to iOS.main's new test for a host that exits during the session now writes the Hub state file, as the other Android mocks do..changeset/expo-device-hub-website-flags.md,minor), becausemaingeneratesCHANGELOG.mdfrom changesets.packages/build-tools:yarn testpassed (174 suites, 2136 passed, 8 skipped). An earlier run on the same code reported 8 suites that failed to load, with no failed tests; the rerun passed.yarn typecheck,yarn lint, andyarn fmt:checkpassed.Run by Claude Code on 2026-10-15, after the state directory fix (d30aecd):
EXPO_DEVICE_HUB_STATE_DIRorTMPDIRto another directory; the spawn mock resolves the state directory from its env, as the Hub does. Both failed with the "wrote no session token" error without the fix, and pass with it.packages/build-tools:yarn testpassed (174 suites, 2138 passed, 8 skipped).yarn typecheck,yarn lint, andyarn fmt:checkpassed.Authorship: Claude Code (Claude Opus 5.5) wrote this change and description at Krystof Woldrich's direction.
🤖 Generated with Claude Code