-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Fix: Prevents interpreting run options as yarn options #4152
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
Conversation
I remember talking about this but couldn't find the issue. Do you know if we have an open or closed issue around this? The problem with this approach is it makes yarn take no arguments at all such as |
Also, tests or didn't happen. |
No, this is an issue reported by the Oculus people, and something I personally struggle with on a daily basis. :p
Not really an issue since the only potential option concerned is |
Although it's convenient to not have to use the |
Hm I don't know, this behavior really is a pain, especially since it is completely silent, which means that unless people actually look at the command executed, they won't see that the options have been ignored. It's potentially dangerous (just imagine something like A less invasive possibility would be to only add this behavior when running |
I think I'm on board with this change, but agree that we need tests for it. We had an internal discussion about this at FB previously and would like to make sure other people are involved in a vote for this feature. I seem to remember that there were some issues with this approach that made this less workable, but I do think that @kaylieEB I think diverging here is ok, given that in scripts you'd write "yarn run …" instead of "npm run" or a generic command, like just "run", so it's clear that you are using either tool. |
I don't think we can - the only way I could see this working would be to add some kind of "if the command line doesn't begins with --, add one" (so that we wouldn't break people already using --), but that seems extremely confusing and unexpected. |
I think the point we ended up is pretty great so 👍 . Thanks everyone, especially @arcanis. We need to be very loud and clear about this change though. |
I think that's confusing and will break projects with people on different versions of Yarn. Can we add a deprecation warning to 1.0 if the command starts with |
I think if this could be supported, it would be great since devs don't have to alter their current use habits, similar to how we support both |
a1549ce
to
e620c48
Compare
e620c48
to
8dff818
Compare
src/reporters/lang/en.js
Outdated
@@ -188,6 +188,8 @@ const messages = { | |||
|
|||
execMissingCommand: 'Missing command name.', | |||
|
|||
dashDashDeprecation: | |||
"Using -- to pass arguments to your scripts isn't required anymore. Doing this may cause issues in future versions.", |
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.
How about: "Yarn does not require `--` to pass arguments to scripts. In a future version of Yarn, passing `--` will fail with an error." ?
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.
It won't fail, it will just be forwarded to the binary as-is.
$> yarn test -- --no-coverage
will become
$> jest -- --no-coverage
instead of (as before this PR, and until the deprecation wears off)
$> jest --no-coverage
This is important because in some case you really want to prevent something from being interpreted as an option.
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.
Right, in that case then, maybe this: "From Yarn 1.0, scripts do not require `--` to be passed. In a future version of Yarn, passing `--` will be forwarded to the script directly." ?
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.
Much better than the current text, thanks 👍
src/cli/index.js
Outdated
@@ -403,7 +418,7 @@ export default function start() { | |||
const doubleDashIndex = process.argv.findIndex(element => element === '--'); | |||
const startArgs = process.argv.slice(0, 2); | |||
const args = process.argv.slice(2, doubleDashIndex === -1 ? process.argv.length : doubleDashIndex); | |||
const endArgs = doubleDashIndex === -1 ? [] : process.argv.slice(doubleDashIndex + 1, process.argv.length); | |||
const endArgs = doubleDashIndex === -1 ? [] : process.argv.slice(doubleDashIndex, process.argv.length); |
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.
can you do process.argv.slice(doubleDashIndex)
since it'll just default to length of the array?
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.
Sure thing 👍
src/cli/index.js
Outdated
// we using "yarn <script> -abc" or "yarn run <script> -abc", we want -abc to be script options, not yarn options | ||
if (command === commands.run) { | ||
if (endArgs.length === 0) { | ||
endArgs = ['--', ...args.splice(1, args.length)]; |
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.
same for here? args.splice(1)
?
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.
looks great!
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.
This looks pretty nice but it is also a hack on the existing system that relies on --
style still. Do we have a long-term plan for making this more maintainable?
__tests__/integration.js
Outdated
@@ -73,6 +73,62 @@ test('--mutex network', async () => { | |||
]); | |||
}); | |||
|
|||
// Windows doesn't have the "echo" utility |
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.
How about node -p -e "process.argv.slice(1)"
for cross-platform compatibility? ;)
const stdoutPromise = misc.consumeStream(stdout); | ||
const stderrPromise = misc.consumeStream(stderr); | ||
|
||
const [stdoutOutput, stderrOutput] = await Promise.all([stdoutPromise, stderrPromise]); |
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.
Is there an advantage to this indirection instead of just doing
const stdoutOutput = await misc.consumeStream(stdout);
const stderrOutput = await misc.consumeStream(stderr);
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.
Problem with this writing is that it doesn't work, because the stdin and stdout streams are started and stopped as soon as the event loop gets a chance, ie. before the second line gets executed. Before of this, the second consumeStream
call never receives the end
event, and never returns. The synchronous version makes sure we attach both of our listeners before allowing the event loop to continue.
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.
Got it. I think this deserves a comment. Even better, find a way that doesn't require this workaround (not necessarily in this patch). Maybe use something else rather than the stream consumer? This may also help: https://nodejs.org/api/stream.html#stream_readable_resume
|
||
const [stdoutOutput, stderrOutput] = await Promise.all([stdoutPromise, stderrPromise]); | ||
|
||
expect(stdoutOutput.toString().trim()).toEqual('--opt'); |
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.
Are we testing the "$ " echo string here? If so we may wanna add a comment since this may change.
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.
No, because we run with YARN_SILENT: 1
, so Yarn doesn't print the yarn run
header.
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.
Oh, nice. Then what are we testing here? I'm confused :D
const stdoutPromise = misc.consumeStream(stdout); | ||
const stderrPromise = misc.consumeStream(stderr); | ||
|
||
const [stdoutOutput, stderrOutput] = await Promise.all([stdoutPromise, stderrPromise]); |
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.
Lots of repeated code here. You may clean it up with beforeEach
and afterEach
hooks with a describe('run with arguments',
block.
src/cli/index.js
Outdated
@@ -110,6 +110,16 @@ export function main({ | |||
command = commands.run; | |||
} | |||
|
|||
let warnAboutRunDashDash = false; | |||
// we using "yarn <script> -abc" or "yarn run <script> -abc", we want -abc to be script options, not yarn options |
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.
we are using
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.
me hulk
@@ -171,6 +181,11 @@ export function main({ | |||
// | |||
const run = (): Promise<void> => { | |||
invariant(command, 'missing command'); | |||
|
|||
if (warnAboutRunDashDash) { | |||
reporter.warn(reporter.lang('dashDashDeprecation')); |
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.
Arguably, this should be an info
message, not a warning
since with the --strict
option it will break and I don't think should break just because you are still using the harmless --
thing. What do you think?
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.
Makes sense, but the PR that will implement the --strict
feature will need to revisit all the loglevels anyway.
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.
Eh, fair point. I'd still get certain things "right" from the start. That said we don't show info
messages in normal mode, are we? Then I'm okay with warnings.
@BYK Long term plan is to switch to a different command line parser more suited to our use cases. I have it on my backlog, but time has been a scarce resource lately :p |
Shall we make it explicit by creating an issue? |
* Prevents interpreting run options as yarn options * Implements a deprecation warning * Adds tests * Feedback * Wording * Enables a test on Linux * Disables the tests again on Windows
**Summary** Fixes yarnpkg#4383. This patch makes argument parsing a bit tidier, and starts supporting `yarn --silent custom-script` style commands as initiall intended by yarnpkg#4152. **Test plan** Existing unit tests. Should ideally add a few more.
Summary
Running the following command doesn't have the expected effect, because the
--no-coverage
option is interpreter by Yarn instead of being forwarded to the script. This patch fix this.This is a breaking change: it will change some edge-case behaviors.