Skip to content
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

Pass extra arguments to npmClient during bootstrap #834

Merged
merged 2 commits into from
Jun 30, 2017

Conversation

xaka
Copy link
Contributor

@xaka xaka commented May 22, 2017

Description

Allow to pass npmClient arguments.

Motivation and Context

#813

How Has This Been Tested?

# npm version
{ lerna: '2.0.0-rc.4',
  npm: '3.10.10',
  ares: '1.10.1-DEV',
  http_parser: '2.7.0',
  icu: '57.1',
  modules: '48',
  node: '6.9.4',
  openssl: '1.0.2j',
  uv: '1.9.1',
  v8: '5.1.281.89',
  zlib: '1.2.8' }

# uname -a
Darwin pstrashkin-mbp 15.6.0 Darwin Kernel Version 15.6.0: Tue Apr 11 16:00:51 PDT 2017; root:xnu-3248.60.11.5.3~1/RELEASE_X86_64 x86_64

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

Copy link
Member

@evocateur evocateur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good start.

I'd really like to see an integration test to validate our usage of yargs.

README.md Outdated
Pass extra arguments to npm client.

```sh
$ lerna bootstrap --npm-client=yarn --npm-client-args=--ignore-engine
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you pass multiple flags to --npm-client-args?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As --npm-client-args is just a string and simply proxies everything to underlying npm client, it'll be:

lerna bootstrap --npm-client=yarn --npm-client-args='--ignore-engine --flag1 --flag2 ...'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately that's not how execa works, you need to pass an array of arguments (or push multiple, in this case) if there are multiple arguments.

README.md Outdated
@@ -790,6 +790,24 @@ May also be configured in `lerna.json`:
}
```

#### --npm-client-args [client]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be defined for yargs in the builder export of BootstrapCommand.

Even better, why not just accept all args after a -- to lerna bootstrap to be passed to the client execution?

lerna bootstrap -- --ignore-engine --silent

To pass it via lerna.json, you'd need to pass an array of strings instead of a string:

"npmClientArgs": ["--ignore-engine", "--silent"]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to isolate it to bootstrap command only? I thought it should be for all of them regardless of where npm client is used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bootstrap is currently the only place we alternate on the value of npmClient, and it seems cleaner that way (supporting multiple arguments properly without re-implementing yargs, for example)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems accepting all args after -- is the lottery winner. My only concern is it's not very explicit and bootstrap isn't just a proxy of [npm | yarn] install so it might be confusing whether args get appended to entire flow of bootstrap or particular parts of it.

I can live with that :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evocateur what if both npmClientArgs and -- are provided, should we append one to another or replace? I vote for append as it'll work like "common arguments you always want to pass".

@xaka xaka force-pushed the master branch 4 times, most recently from ec62e81 to e049d41 Compare May 23, 2017 00:00
@xaka
Copy link
Contributor Author

xaka commented May 23, 2017

@evocateur please take another look; i wanted to add integration tests, but couldn't find proper way to capture arguments and do assertion - feels like there is need for mock npm client for that

@evocateur
Copy link
Member

It would be sufficient to test whether it respects --production --no-optional, for example, by asserting that a modules under devDependencies and optionalDependencies didn't get installed.

@xaka
Copy link
Contributor Author

xaka commented May 23, 2017

Good call. Will do.

@@ -46,13 +46,19 @@ export default class BootstrapCommand extends Command {
}

initialize(callback) {
const { registry, npmClient } = this.options;
const { registry, npmClient, npmClientArgs } = this.options;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a npm-client-args config in the builder object above

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically, using this block starting at line 12:

export function handler(argv) {
  return new BootstrapCommand([...argv.npmClientArgs], argv).run();
}

export const command = "bootstrap [npm-client-args..]";

This pattern is used in lerna exec (and run): https://github.com/lerna/lerna/blob/master/src/commands/ExecCommand.js#L8

Thus you can alias a collection of all unparsed positional arguments, as well as unparsed remainders behind --.

lerna bootstrap --scope foo -- --bar
lerna bootstrap --hoist -- --no-optional

It should still be retrievable from this.options.npmClientArgs, but it's also always present as an array (which might be empty).

@evocateur
Copy link
Member

Also, don't worry about making several commits, I'll be squashing the PR anyway.

@xaka
Copy link
Contributor Author

xaka commented May 23, 2017

D'oh! Unfortunately we cannot move forward with yargs until there is fix for yargs/yargs#682. Next version (hasn't been released yet) adds populate-- option to change the behavior, but it's unclear when it'll become available. Until then it's difficult to distinguish between positional arguments and arguments that simply haven't been parsed.

@xaka
Copy link
Contributor Author

xaka commented May 23, 2017

@evocateur ready for another round with integration tests included! thanks for patience 🍻

"packages/package-1/node_modules/clone",
"packages/package-1/node_modules/columnify",
"packages/package-1/node_modules/defaults",
"packages/package-1/node_modules/pify",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pify shouldn't be here, hmm

@xaka xaka force-pushed the master branch 2 times, most recently from b1bec8c to 0304745 Compare May 23, 2017 03:27
@xaka
Copy link
Contributor Author

xaka commented May 23, 2017

One test is failing and it says packages/package-1/node_modules/pify is expected to be installed, but when i manually run npm with same arguments, it doesn't happen. I'm confused...

@xaka
Copy link
Contributor Author

xaka commented May 23, 2017

Turned out it was lerna itself extracting and merging dependencies and devDependencies together, and passing it npm afterwards, which affected test at the end.

@evocateur
Copy link
Member

Yeah, it's because pify is a transitive dependency of tempy, and thus will always be installed no matter the flags. I'd recommend choosing dependencies that don't have any dependencies themselves, so that the scope of the assertion is tightly focused.

normalize-newline, remove-trailing-separator, and balanced-match all fit the bill.

That being said, you're correct! We might want to focus on different flags, perhaps? Perhaps it would be easier to use --ignore-engines instead?

@xaka xaka force-pushed the master branch 5 times, most recently from 765374b to 17a9bce Compare May 23, 2017 06:02
@xaka
Copy link
Contributor Author

xaka commented May 23, 2017

I ended up using fake npm client, which is less error prone, doesn't have side effects and comes with predictable behavior. Everything should stable now.

import normalizePath from "normalize-path";
import path from "path";
import tempy from "tempy";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sorted everything as I didn't know where to put new imports

@xaka
Copy link
Contributor Author

xaka commented May 24, 2017

@evocateur knock knock!

@DxCx
Copy link

DxCx commented Jun 5, 2017

@xaka thanks alot!
@evocateur any expectation when this will be released?

Copy link
Member

@evocateur evocateur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're going to need to change part of the bootstrap algorithm to make this fully-functional. (the part where we mangle the temporary package.jsons)

@@ -65,6 +67,22 @@ describe("lerna bootstrap", () => {
const stdout = await execa.stdout(LERNA_BIN, ["run", "test", "--", "--silent"], { cwd });
expect(stdout).toMatchSnapshot("--npm-client yarn: stdout");
});

test.concurrent("passes remaining arguments to npm client", async () => {
const cwd = await initFixture("BootstrapCommand/npm-client-args");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need an integration test that doesn't employ the npmClientArgs key in lerna.json (using the BootstrapCommand/basic fixture, for example). I'm pretty sure that fails right now, as is.

@@ -0,0 +1,3 @@
#!/usr/bin/env node

require("fs").writeFileSync(require("path").resolve(__dirname, "npm-debug.log"), process.argv.slice(2));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to write a file, just console.log the argv and assert on the command's stdout.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately bootstrap doesn't proxy npm client output

@evocateur
Copy link
Member

evocateur commented Jun 7, 2017 via email

@xaka
Copy link
Contributor Author

xaka commented Jun 7, 2017

@evocateur added another integration test for remaining arguments without npmClientArgs in lerna.json

@Timer
Copy link

Timer commented Jun 29, 2017

Hi! We'd love to see this merged for facebook/create-react-app#2673; is there anything I can do to help?

Specifically, we're trying to run yarn install --no-lockfile during bootstrap.

If not, take this as a friendly bump! 😄

@evocateur
Copy link
Member

I didn't realize the durable npmClientArgs from lerna.json and any additional CLI flags would be merged, not overridden, so my previous comment about the config naming is invalid. Still wish the integration test was a little less "fake out npm", but it works, and that's the ultimate goal.

Thanks @xaka for your patience. :)

@xaka
Copy link
Contributor Author

xaka commented Jun 30, 2017

@evocateur just couple months, no prob man 🍻 😄 next time i'll start with FB to bribe you first, hehe

@evocateur
Copy link
Member

Augh, AppVeyor is exasperating. 2 out of 3 pass, so I'm calling it good.

@evocateur evocateur changed the title Allow to pass npmClient arguments (#813) Pass extra arguments to npmClient during bootstrap Jun 30, 2017
@evocateur evocateur merged commit 52ad617 into lerna:master Jun 30, 2017
@Timer
Copy link

Timer commented Jun 30, 2017

Cheers, thanks so much!

@lock
Copy link

lock bot commented Dec 27, 2018

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.

@lock lock bot locked as resolved and limited conversation to collaborators Dec 27, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants