Lerna 7+ breaks tools-workspaces functionality
poniraq opened this issue · 2 comments
What happened?
Problem
Lerna 7.0.0 introduced a breaking change that deprecates useWorkspaces
. Instead Lerna now relies on a npmClient
property to detect workspaces, unless package list is overriden by a packages
property.
This in turn breaks the @rnx-kit/metro-config
, since it is no longer able to correctly populate watchFolders
property for metro config.
Workarounds
- duplicate package list in
lerna.json
this "theoretically" should allowtools-workspaces
to proceed as usual. - manually populate
watchFolders
metro config property.
Solution
My initial impulse was to simply cut everything lerna-related from tools-workspaces
, as Lerna seemingly no longer considers itself a "sentinel". This presents 2 problems: a) how do we keep compatibility with Lerna pre-7 versions that still rely on useWorkspaces
? b) how do we keep compatibility with Lernas ability to override package list through packages
property?
Code in question (packages/tools-workspaces/src/lerna.ts):
// https://lerna.js.org/docs/configuration
export async function findWorkspacePackages(
configFile: string
): Promise<string[]> {
const { packages, useWorkspaces } = await readJSON(configFile);
if (!useWorkspaces) {
return await findPackages(packages, path.dirname(configFile));
}
const root = path.dirname(configFile);
const sentinels = filterSentinels();
for (const sentinel of sentinels) {
const filename = path.join(root, sentinel);
if (fileExists(filename)) {
const { findWorkspacePackages } = await getImplementation(filename);
return await findWorkspacePackages(filename);
}
}
return [];
}
so my way of thinking is that we:
- check for
packages
first -> proceed as usual if found - do not check for
useWorkspaces
-> try to fallback to other sentinels regardless
like this:
// https://lerna.js.org/docs/configuration
export async function findWorkspacePackages(
configFile: string
): Promise<string[]> {
const { packages } = await readJSON(configFile);
// respect the Lerna `packages` property
if (packages) {
return await findPackages(packages, path.dirname(configFile));
}
// fallback to alternative sentinels regardless of `useWorkspaces`
const root = path.dirname(configFile);
const sentinels = filterSentinels();
for (const sentinel of sentinels) {
const filename = path.join(root, sentinel);
if (fileExists(filename)) {
const { findWorkspacePackages } = await getImplementation(filename);
return await findWorkspacePackages(filename);
}
}
return [];
}
The only uncovered case is when user deliberately sets useWorkspaces
to false, does not provide lerna with packages
but still expects things to somehow magically work. Please tell me if you're aware of such a setup.
Affected Package
@rnx-kit/tools-workspaces
Version
0.1.3
Which platforms are you seeing this issue on?
- Android
- iOS
- macOS
- Windows
System Information
System:
OS: Windows 10 10.0.19045
CPU: (8) x64 Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
Memory: 18.37 GB / 31.93 GB
Binaries:
Node: 18.16.1 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.19 - C:\Program Files\nodejs\yarn.CMD
npm: 9.5.1 - C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK: Not Found
Windows SDK:
AllowAllTrustedApps: Enabled
Versions: 10.0.19041.0
IDEs:
Android Studio: AI-222.4459.24.2221.10121639
Visual Studio: 16.11.33801.447 (Visual Studio Community 2019)
Languages:
Java: 11.0.18
npmPackages:
@react-native-community/cli: ^10.0.0 => 10.2.5
react: 18.2.0 => 18.2.0
react-native: ^0.71.5 => 0.71.11
react-native-windows: Not Found
npmGlobalPackages:
*react-native*: Not Found
Steps to Reproduce
Here's the minimal reproduction example. I'm not familiar with yarn
workspaces, so the only limitation here is that it requires pnpm
.
https://github.com/poniraq/lerna7-tools-workspaces-bug-example
Code of Conduct
- I agree to follow this project's Code of Conduct
Thanks for reporting this @poniraq! And double thanks for writing it all in such details, providing a repro AND sending a PR!
Truly the pinnacle of OSS contribution 😍
Overall the report makes sense and the PR seems reasonable, I just want to check back with @tido64 before proceeding; he's currently on 🏝️ so we'll be a bit slow to do a new release. Can you rely on your workaround for a little longer?