-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: always install leaves using npm --global-style
#775
Conversation
In the event that an explicit dependency (`dep1@X`) of a package is hoisted but other dependencies with a common sub-dependency on a different version of `dep1@Y` cannot be hoisted, npm will attempt to share that package by installing `dep1@Y` in the root of the package's `node_modules` directory. As a result, the incorrect version of dep1 will be available to the package rather than the hoisted dependency it requires. To avoid this, always use `npm install --global-style` for "leaves" in a hoisted context. This results in more consistently correct behavior at the cost of increased duplication of some packages. See: lerna#677
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ricky This looks great so far, thanks! A couple more simple tests and we're good to go.
|
||
if (npmGlobalStyle) { | ||
cmd = "npm"; | ||
args.push("--global-style"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An NpmUtilities.installInDir()
test case with an assertion similar to this one would help keep our coverage up.
const config = { npmClient: "yarn" };
const npmGlobalStyle = true;
NpmUtilities.installInDir(directory, dependencies, config, npmGlobalStyle, (err) => {
// ...
expect(ChildProcessUtilities.exec).lastCalledWith("npm", ["install", "--global-style"], {
// ...
@@ -439,6 +441,7 @@ export default class BootstrapCommand extends Command { | |||
pkg.location, | |||
deps.map(({ dependency }) => dependency), | |||
this.npmConfig, | |||
npmGlobalStyle, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An assertion in this test would be helpful:
expect(NpmUtilities.installInDir).toBeCalledWith(
expect.stringContaining("package-dirname"),
expect.arrayContaining(["non-hoisted-dependency-name"]),
expect.any(Object),
true, // npmGlobalStyle
expect.any(Function)
);
Of course, this means our BootstrapCommand/basic
fixture (or a new, hoist-focused variant) needs a non-hoistable external dependency in one of its packages.
We can backfill the tests later, the gist you made clearly shows that this works as intended. |
Thanks. I'll get those test put together by Monday. |
@ricky Awesome! |
Nice work @ricky, thanks for the fix! |
This thread has been automatically locked because there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Description
Use
npm install --global-style
underlerna bootstrap --hoist
for packages which cannot be hoisted. This results in more consistently correct behavior at the cost of increased duplication of some packages.Motivation and Context
In the event that an explicit dependency (
dep1@X
) of a package is hoisted but other dependencies with a common sub-dependency on a different version ofdep1@Y
cannot be hoisted, npm will attempt to share that package by installingdep1@Y
in the root of the package'snode_modules
directory. As a result, the incorrect version ofdep1
will be available to the package rather than the hoisted dependency it requires.Scenario
[email protected]
,dep2
, anddep3
.dep2
&dep3
have a transitive dependency on a different version ofdep1
([email protected]
)[email protected]
can be hoisted, butdep2
&dep3
cannot (either due to version mismatches or explict--nohoist
directives).Current Result
Desired result
Result without hoisting
See: #677
How Has This Been Tested?
Basic test project and manual validation steps outlined here:
https://gist.github.com/ricky/ff42dd94d52f2c3e25218d6dcb0a5372
Types of changes
From the perspective of
npm
users, this probably qualifies as a non-breaking change. Foryarn
users, the client override would constitute a change in functionality.Checklist:
I had some difficulty crafting a unit test to cover this case. With the way the mocks & fixtures are set up, it's not immediately clear how to represent the transitive dependency of an external dependency.