From 2ff48c08a931ccc4c4728d854e3630891103f228 Mon Sep 17 00:00:00 2001 From: Peter Abbondanzo Date: Mon, 22 Jun 2026 17:12:43 -0700 Subject: [PATCH] Fix helloworld e2e after core-cli-utils stopped publishing Summary: `private/helloworld` depends on `react-native/core-cli-utils` (it imports `android`, `app`, and `apple` from it to build the app), but that package is no longer published to npm nor to the local Verdaccio proxy that the e2e build installs against. Since `private/helloworld` is excluded from the workspace, it installs standalone, so its `"*"` dependency on `react-native/core-cli-utils` could not resolve and `npm install` failed with `E404`. Resolve `"*"`-pinned in-repo `react-native/*` dependencies to a local `file:` path in `_prepareHelloWorld()`, so helloworld consumes `core-cli-utils` directly from its in-repo reference implementation regardless of whether it is published. This mirrors how the `react-native` package itself is already wired up for the e2e build. Changelog: [Internal] Differential Revision: D109374920 --- scripts/e2e/init-project-e2e.js | 45 ++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/scripts/e2e/init-project-e2e.js b/scripts/e2e/init-project-e2e.js index 34468725f695..30db3b9c33d2 100644 --- a/scripts/e2e/init-project-e2e.js +++ b/scripts/e2e/init-project-e2e.js @@ -136,7 +136,11 @@ async function initNewProjectFromSource( if (useHelloWorld) { console.log('Preparing private/helloworld/ to be built'); - _prepareHelloWorld(version, pathToLocalReactNative); + const localPackages = await getPackages({ + includeReactNative: false, + includePrivate: true, + }); + _prepareHelloWorld(version, pathToLocalReactNative, localPackages); directory = path.join(PRIVATE_DIR, 'helloworld'); } else { const pathToTemplate = _prepareTemplate( @@ -209,6 +213,7 @@ async function installProjectUsingProxy(cwd /*: string */) { function _prepareHelloWorld( version /*: string */, pathToLocalReactNative /*: ?string*/, + packages /*: ProjectInfo */, ) { const helloworldDir = path.join(PRIVATE_DIR, 'helloworld'); const helloworldPackageJson = path.join(helloworldDir, 'package.json'); @@ -216,24 +221,28 @@ function _prepareHelloWorld( fs.readFileSync(helloworldPackageJson, 'utf8'), ); - // and update the dependencies and devDependencies of packages scoped as @react-native - // to the version passed as parameter - for (const key of Object.keys(packageJson.dependencies)) { - if ( - key.startsWith('@react-native/') && - packageJson.dependencies[key] !== '*' - ) { - packageJson.dependencies[key] = version; + // Point each in-repo @react-native/* dependency at the version published to + // the local proxy. Deps declared as `*` are unpublished reference packages + // (e.g. @react-native/core-cli-utils, which lives in private/) and are absent + // from the proxy, so resolve those to their local source via a `file:` path. + const updateDependencies = (deps /*: Record */) => { + for (const key of Object.keys(deps)) { + if (!key.startsWith('@react-native/')) { + continue; + } + if (deps[key] === '*') { + const localPackage = packages[key]; + if (localPackage != null) { + deps[key] = `file:${path.relative(helloworldDir, localPackage.path)}`; + } + } else { + deps[key] = version; + } } - } - for (const key of Object.keys(packageJson.devDependencies)) { - if ( - key.startsWith('@react-native/') && - packageJson.devDependencies[key] !== '*' - ) { - packageJson.devDependencies[key] = version; - } - } + }; + updateDependencies(packageJson.dependencies); + updateDependencies(packageJson.devDependencies); + if (pathToLocalReactNative != null) { packageJson.dependencies['react-native'] = `file:${pathToLocalReactNative}`; }