-
Notifications
You must be signed in to change notification settings - Fork 2.1k
fix(berry arg parsing) #1612
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(berry arg parsing) #1612
Conversation
@chris-olszewski is attempting to deploy a commit to the Vercel Team on Vercel. A member of the Team first needs to authorize it. |
638729d
to
12f6679
Compare
Failures are not due to this. Have some kind of config mishap with versioning |
e1d20ea
to
dcb919a
Compare
dcb919a
to
09b0e06
Compare
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.
Mostly: lots and lots more test scenarios!
cli/scripts/monorepo.ts
Outdated
@@ -184,6 +184,7 @@ importers: | |||
test: `${turboPath} run test`, | |||
lint: `${turboPath} run lint`, | |||
special: "echo root task", | |||
args: 'node -e "console.log(process.argv)" --', |
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 help me understand why we should include --
here? I'm assuming that it's there for for a reason and I'd like to have it be a bit more fleshed-out to help with detection of issues.
node -e "console.log(process.argv)" --before-separator=thing -- --after-separator=thing
We can also add additional scripts for "has separator" and "doesn't have separator."
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.
I had the trailing --
so that we could detect when turbo was passing an unnecessary separator since Node swallows the first --
:
olszewski@chriss-mbp cli % node -e "console.log(JSON.stringify(process.argv))" -- foo
["/Users/olszewski/.nvm/versions/node/v16.16.0/bin/node","foo"]
olszewski@chriss-mbp cli % node -e "console.log(JSON.stringify(process.argv))" -- -- foo
["/Users/olszewski/.nvm/versions/node/v16.16.0/bin/node","--","foo"]
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.
Wow, it's turtles all the way down. Can you add this information in as a comment?
I still would like to have a before
and after
sentinel argument here, just to monitor for behavior changes.
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 elaborate on having a before
/after
sentinel arguments for this script?
Unsure if it relates but, once node encounters an arg it doesn't recognize it treats that and every arg after it as a pass through:
olszewski@chriss-mbp cli % node -e "console.log(JSON.stringify(process.argv))" before -- after
["/Users/olszewski/.nvm/versions/node/v16.16.0/bin/node","before","--","after"]
olszewski@chriss-mbp cli % node -e "console.log(JSON.stringify(process.argv))" --zero-fill-buffers before
["/Users/olszewski/.nvm/versions/node/v16.16.0/bin/node","before"]
olszewski@chriss-mbp cli % node -e "console.log(JSON.stringify(process.argv))" before --zero-fill-buffers
["/Users/olszewski/.nvm/versions/node/v16.16.0/bin/node","before","--zero-fill-buffers"]
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.
(Read in thread context.)
Good callout that node
itself blows up here. Thanks for that! This is fine as is.
@@ -36,6 +36,10 @@ type PackageManager struct { | |||
// The directory in which package assets are stored by the Package Manager. | |||
PackageDir string | |||
|
|||
// The separator that the Package Manger uses to identify arguments that | |||
// should be passed through to the underlying script. | |||
ArgSeparator []string |
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.
I know this maps to the previous, but can this be changed to not be an array of strings?
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.
What's the most Go-like way to represent this? The comment on the pnpm 6/7 split:
// We are allowed to use nil here because argSeparator already has a type, so it's a typed nil,
// vs if we tried to call "args = append(args, nil...)", which would not work. This could
// just as easily be []string{}, but the style guide says to prefer nil for empty slices.
Would it be best practice/common to use the empty string as the nil value and check it before appending to the arg slice?
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.
The existing solution is too clever by half, but I understand now why it exists.
- String types can't be
nil
(only empty string) []string{}
's "zero value" isnil
.
I'm ... comfortable leaving it the way it is. 🤷♂️ The only other reasonable options are:
- check for "" (not ideal since it's an in-band sentinel)
- far more-invasive (a whole new struct just for arg separator, and a method to get it, guards at the
append
, and then it's all just a mess)
So, yeah, let's add more to the comment and call it done.
cli/scripts/e2e/e2e.ts
Outdated
const result = getCommandOutputAsArray( | ||
repo.turbo( | ||
"run", | ||
["args", "--filter=//", "--", "--script-arg=42"], |
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.
Good call on choosing filter
as a name.
cli/scripts/e2e/e2e.ts
Outdated
const result = getCommandOutputAsArray( | ||
repo.turbo( | ||
"run", | ||
["args", "--filter=//", "--", "--script-arg=42"], |
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 we do quite a few more variations on this with varying argument patterns? That'll likely make the rest of the stuff here need to become utility functions of some sort.
I'm thinking mostly edge cases:
-- -- --
- ``
-f --f ---f ----f
--same -- --same
--zero -- --one -- --two -- --three
-------------------------
In terms of test understandability, I'd love to be able to spec the input like this and then the output expected adjacent to it. (e.g. Go table tests)
We might should also create multiple scripts in package.json
that log out argv
with and without their own separator.
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 might should also create multiple scripts in package.json that log out argv with and without their own separator.
Could you elaborate on this?
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.
(Read in thread context.)
This is really an unnecessary, overly-defensive idea. Basically, we have a script called argv
in the root package.json
now that is just an argv
echo service.
We could create variations on that script that had other --
setups to detect if node itself changes the way it works.
But that'll realistically break way more than us and I can't see that being something we truly need to test.
9a08855
to
69a0d66
Compare
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 is a fixship!
- The only open things remaining are something trivial. (e.g. all comments, naming, light refactoring, or just ... unimportant)
- So, once you're happy with it, ship it!
// pnpm v7+ changed their handling of '--'. We no longer need to pass it to pass args to | ||
// the script being run, and in fact doing so will cause the '--' to be passed through verbatim, | ||
// potentially breaking scripts that aren't expecting it. | ||
ArgSeparator: nil, |
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.
Let's add information about this being a typed nil ([]string{}
) here.
@@ -929,7 +914,7 @@ func (e *execContext) exec(ctx gocontext.Context, pt *nodes.PackageTask, deps da | |||
argsactual := append([]string{"run"}, pt.Task) | |||
if len(passThroughArgs) > 0 { | |||
// This will be either '--' or a typed nil | |||
argsactual = append(argsactual, e.argSeparator...) | |||
argsactual = append(argsactual, e.packageManager.ArgSeparator...) |
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.
I love that the entire change is this single line.
assert.equal(args, passedArgs); | ||
}; | ||
|
||
const tests = [ |
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 is perfect, thank you. ❤️
cli/scripts/monorepo.ts
Outdated
if (this.npmClient === "pnpm6") { | ||
fs.mkdirSync(path.join(this.binDir, "node_modules"), { recursive: true }); | ||
execa.sync("npm", ["install", "--no-save", "pnpm@6.22.2"], { | ||
cwd: this.binDir, | ||
}); | ||
} |
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.
You're right, corepack is a better story.
cli/scripts/e2e/e2e.ts
Outdated
const result = getCommandOutputAsArray( | ||
repo.turbo( | ||
"run", | ||
["args", "--filter=//", "--", "--script-arg=42"], |
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.
(Read in thread context.)
This is really an unnecessary, overly-defensive idea. Basically, we have a script called argv
in the root package.json
now that is just an argv
echo service.
We could create variations on that script that had other --
setups to detect if node itself changes the way it works.
But that'll realistically break way more than us and I can't see that being something we truly need to test.
cli/scripts/monorepo.ts
Outdated
@@ -184,6 +184,7 @@ importers: | |||
test: `${turboPath} run test`, | |||
lint: `${turboPath} run lint`, | |||
special: "echo root task", | |||
args: 'node -e "console.log(process.argv)" --', |
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.
(Read in thread context.)
Good callout that node
itself blows up here. Thanks for that! This is fine as is.
A quick and dirty switch to use corepack for managing package managers for our e2e tests. A few things to note: - Running these tests on a local machine will enable corepack on that machine, this could be undesired for some devs. - I found that it is necessary to forcibly add the corepack install dir to the top of $PATH in case a dev has a package manager installed elsewhere that would take priority. At the moment this is only useful for the Yarn/Berry split, but it would simplify #1612 which adds pnpm6 to e2e tests quite a bit.
The initial testing script had a hidden dependency on the length of the node path which would trigger the output to be spread over multiple lines. This lead to confusing logic around handling the case when it all fit onto one line. This commit changes the script to now always output all information on a single line.
69a0d66
to
a782a5f
Compare
This PR adds:
--
(ignore-option) as first argument to script. #1477)I'm not happy with how I'm going about getting pnpm@6.22.2 for the e2e tests which involves installing it to a tempdir and then adding that to
$PATH
whenever we shell out, but it's what I got working that didn't mess with any global installs.