Repository navigation
feat(platform-vega): support Vega SDK 0.24 and Fire TV devices - #196
hristototov wants to merge 4 commits into
Conversation
|
Someone is attempting to deploy a commit to the Callstack Team on Vercel. A member of the Team first needs to authorize it. |
|
|
||
| ## How to run React Native Harness? | ||
|
|
||
| Build a debug package first. Debug builds load the JavaScript bundle from Metro, which is what Harness needs. The app opts out of Vega system bundles (`kepler.useSystemJsBundles` in `package.json`) because Harness serves the whole bundle itself: |
There was a problem hiding this comment.
Amazon enabled system bundles by default since SDK v0.20 and it should not affect the code that is a part of the app project
Having RNHarness setup for Vega relying on that opt-out flag will limit the adoption in the projects that are using system bundles
There was a problem hiding this comment.
Removed the opt-out. The enhancer now applies Amazon's own applySystemBundleConfig, so the default split-bundle setup works
| bridgeTimeout: 120000, | ||
| testTimeout: 10000, | ||
| resetEnvironmentBetweenTestFiles: 'runtime', | ||
| unstable__enableMetroCache: true, |
There was a problem hiding this comment.
this flag is deprecated, and the default value for metro cache according to docs is already true
There was a problem hiding this comment.
Removed it (and the unused disableViewFlattening) from the app config
|
|
||
| ## Building and deploying the app | ||
|
|
||
| Harness serves the whole JavaScript bundle from its own Metro server, so the app must be built as a regular bundle rather than a split "system bundle" one. Opt out of system bundles in the `kepler` section of `package.json`: |
There was a problem hiding this comment.
If I get it right, the only thing Harness does with Metro is providing its own custom resolver. This should not be a reason to opt-out of the whole split bundles setup that Amazon implemented for Vega
There was a problem hiding this comment.
Dropped the opt-out instructions and documented that Harness honours system bundles, falling back to a regular bundle only when an app sets useSystemJsBundles: false
|
|
||
| - `@react-native-harness/ui` (`screen`, `userEvent`, screenshots) has no Vega native module yet, so test files importing it fail to load on Vega. | ||
| - Crash detection relies on the app process disappearing and on the device log stream (Vega OS reports the kill reason there, for example `AppNotResponding`). Minidumps are not collected. | ||
| - `Platform.OS` is `'kepler'` inside tests. The platform-specific file suffix for Harness stays `vega`, for example `settings.vega.harness.ts`. |
There was a problem hiding this comment.
That's not a limitation of Harness, that's just specific thing to Vega (Kepler is/was a working name and they never replaced that)
There was a problem hiding this comment.
Removed it from Limitations and kept the useful part
| - `@react-native-harness/ui` (`screen`, `userEvent`, screenshots) has no Vega native module yet, so test files importing it fail to load on Vega. | ||
| - Crash detection relies on the app process disappearing and on the device log stream (Vega OS reports the kill reason there, for example `AppNotResponding`). Minidumps are not collected. | ||
| - `Platform.OS` is `'kepler'` inside tests. The platform-specific file suffix for Harness stays `vega`, for example `settings.vega.harness.ts`. | ||
| - React Native for Vega 0.83 runs the New Architecture only. |
There was a problem hiding this comment.
again, that's not a limitation of Harness, that's how Vega apps were implemented from the beginning, there's no need to mention that here
|
|
||
| ## Vega in CI | ||
|
|
||
| The Vega SDK and the Vega Virtual Device are not available on GitHub-hosted runners, so Vega jobs need a self-hosted macOS or Ubuntu runner with the SDK installed (`source ~/vega/env` in the runner's shell) and either a virtual device or a Fire TV in developer mode on the runner's network. Build the Debug package in an earlier step and pass it through the `app` input (see the [Vega platform guide](/docs/platforms/vega)). The repository's own `e2e-tests.yml` has an `e2e-vega` job of this shape, gated on `workflow_dispatch` with `platform: vega` and a runner carrying the `vega` label. |
There was a problem hiding this comment.
Would be great to add a permalink to e2e-tests.yml for any person reading the docs to go straight to example yaml
There was a problem hiding this comment.
Linked e2e-tests.yml to its GitHub page on main
| ...metroConfig.resolver, | ||
| platforms: [ | ||
| ...new Set([ | ||
| ...(metroConfig.resolver?.platforms ?? ['ios', 'android']), |
There was a problem hiding this comment.
the default values should have 'kepler' preceding ios and android, otherwise it will try to require .android.[jt]s files first before looking for .kepler.[jt]s
There was a problem hiding this comment.
Put kepler first in resolver.platforms. The unit test asserts the order.
mateusz1913
left a comment
There was a problem hiding this comment.
Looks good now, I'll try to run it on my end on a device with production test suite and will let you know how it goes
| // Kepler first so its platform files win over the defaults. | ||
| platforms: [ | ||
| ...new Set([ | ||
| KEPLER_PLATFORM, |
There was a problem hiding this comment.
it should be in defaults, otherwise overriding is broken
...new Set([
...(metroConfig.resolver?.platforms ?? [KEPLER_PLATFORM, 'ios', 'android']),
'native',
])
mateusz1913
left a comment
There was a problem hiding this comment.
Works on my end with physical device, great job @hristototov!
V3RON
left a comment
There was a problem hiding this comment.
Reviewed the current head across all five axes. Ran locally on the PR branch: unit tests pass for platform-vega (51), runtime (128), config (27), bundler-metro (88) and jest (184); tsc -b is clean for all touched packages plus apps/playground-vega; eslint reports no new errors. No leftover react-native-url-polyfill references in code. The bundlePlatform plumbing, the serializer id pre-assignment (which mirrors Metro's baseJSBundle first loop exactly, with a proper regression test), the getWSServer rewrite (userinfo/IPv6/case all covered by tests), and the string module-id handling all check out. Docs are solid.
Everything else in my notes is Nit/Consider level — I'm only requesting changes for one thing:
The app session treats a CLI failure as an app exit. isAppState() returns false both for a confirmed "not running" answer and for any CLI failure (ok === false covers non-zero exit, the 30 s command timeout, and spawn errors). After the 10 s grace, a single transient probe failure — e.g. the device transport flap this PR itself documents around boot, or one runCommand timeout — is recorded as process-gone and fails the running test file with a false crash. The Android session guards exactly this two ways (catch around the poll treats an error as retryable, and process-gone is only declared after the process was observed running); this session has neither. Details and suggested fix on the inline comment.
Small fix, and the rest is good to go.
|
|
||
| const pollTask = (async () => { | ||
| while (!stopPolling) { | ||
| const running = await isAppRunning(); |
There was a problem hiding this comment.
isAppRunning() here cannot distinguish "the app is not running" from "the probe failed": isAppState() in vega.ts resolves to false whenever runVegaQuietly returns ok: false, which covers a non-zero CLI exit, the 30 s runCommand timeout, and spawn errors — not just a confirmed false answer. So after startGraceMs, one transient failure of vega device is-app-running — e.g. the transport flap this PR documents around device boot, or a single slow CLI call — sets process-gone and fails the running test file with what looks like an app crash.
The Android session is deliberately built the other way around this (platform-android/src/app-session.ts): the poll catches probe errors and just retries, and process-gone is only declared after the process was observed running at least once.
Suggested fix (either works, first is probably cleanest):
- Make the state probe three-valued — e.g. return
'unknown'whenokisfalsewithout a parseable affirmative/negative answer, and have the poll loop treat'unknown'likerunning(skip and retry) so only a confirmedfalsecan end the session. Optionally require 2–3 consecutive confirmed negatives before declaring the exit, which also covers a CLI that answersfalsewhile the transport is half-broken. - Or keep the boolean and wrap the poll in try/catch like Android does — but that alone isn't enough, because today a failed probe doesn't throw, it returns
false.
This is the session's own failure-direction concern: a false app_exited mid-run is indistinguishable from a real crash in the report, and the fix is small.
Description
Modernizes
@react-native-harness/platform-vegafor Vega SDK 0.24 (React Native 0.83 for Vega). The old runner shelled out to the retiredkeplerbinary, needed a running device with the app already installed, never forwarded the Metro port, and did not adapt Metro for Amazon's React Native fork, so it could not launch anything on current SDKs.The runner now drives the
vegaCLI: it starts the Vega Virtual Device when needed and waits until it accepts package manager commands, checks a Fire TV by its serial, installs the.vpkgfromHARNESS_APP_PATHwith--buildType Debug, keeps reverse port forwarding alive so the app reaches Metro onlocalhost:8081(falling back tovda reversefor other ports), launches and tracks the interactive component, streams device logs into the app session, and shuts down a virtual device it started.Also included: a new
apps/playground-vegaapp carrying the platform-agnostic playground suites, a Vega page on the website, a dispatch-only Vega job ine2e-tests.ymlfor a self-hosted runner, and removal of the dead Vega runner fromapps/playground.Related Issue
Closes #195
Context
Three changes outside the runner were necessary, and each was found by getting the app to run on the real device:
react-native startgets from@amazon-devices/kepler-cli-platform: thekeplerplatform, thereact-nativeto@amazon-devices/react-native-keplerredirect, and Kepler'sInitializeCoreas a run-before-main module. The default config points at upstream React Native'sInitializeCore, which the redirect keeps out of the graph, so Metro silently dropped it and the app never initialized.bundlePlatformonHarnessPlatform. Vega apps requestplatform=keplerfrom Metro while the harness platform id, test file suffix, and lock keys stayvega. Prewarming and startup detection now usebundlePlatform, defaulting toplatformId, so nothing changes for other platforms.react-native-url-polyfill. Importing it reads the legacyNativeModulesbridge, which bridgeless runtimes do not have, so Harness initialization threw on every launch. The dev server URL is now parsed by hand.Worth knowing before reviewing:
vega device install-appdefaults to Release. A Debug package installed that way never gets the debug sandbox overrides and Vega OS kills it asAppNotRespondingabout 15 s after launch, so the runner always passes--buildType.is-connected, so readiness requires three consecutive successful package manager probes and installs retry.kepler.useSystemJsBundles: false: Harness serves the whole bundle from its own Metro rather than Amazon's split system bundles.vdaidentifies devices by adb-style serials, so the non-8081 Metro port path works with a single attached device or a physical device whose serialvdareports. Documented on the Vega page.@react-native-harness/uihas no Vega native module yet, so theui/suites are not part of the Vega app.pnpm dedupe --checkreports a secondreact-native@0.82.1resolution introduced by the new app, alongside pre-existing unrelated candidates; left for a separate change.Testing
Unit tests: 47 in
platform-vega(runner flow, CLI wrapper parsing and retries, Metro enhancer, app session), new cases forbundlePlatforminconfigand the URL parsing inruntime.pnpm nx affected -t build,lint,test,typecheckis green for all 23 affected projects andnx release plan:checkpasses.On the Vega Virtual Device (SDK 0.24.12112, CLI 1.4.2, Apple Silicon):
vda reverse, and the mapping is removed on dispose.The physical Fire TV Select 4K run is still outstanding: it needs the developer-mode code from the device and an Amazon account login for
vega devmode login.