-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
cli: accept csv for array values #8933
Conversation
connorjclark
commented
May 11, 2019
•
edited
Loading
edited
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.
nice! no better motivation than a dev scorned 😆
lighthouse-cli/cli-flags.js
Outdated
@@ -152,6 +161,17 @@ function getFlags(manualArgv) { | |||
.default('enable-error-reporting', undefined) // Undefined so prompted by default | |||
.default('channel', 'cli') | |||
.check(/** @param {LH.CliFlags} argv */ (argv) => { | |||
// ".middleware" does not exist in this version of yargs, so do some preprocessing here. | |||
for (const _key of Object.keys(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.
I don't love that this is here and I'm not sure we can actually do this across the board.
(for example --chrome-flags="--window-size 800,600"
)
WDYT about just doing this to our specific .array
properties minus blockedUrlPatterns
?
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.
ah ok. sounds like either way we need a hard coded list (either a blacklist of a whitelist). Whitelist is easier to reason about so let's do that :)
@@ -28,4 +28,14 @@ describe('CLI bin', function() { | |||
assert.ok(optionsWithDescriptions.includes(opt), `cli option '${opt}' has no description`); | |||
}); | |||
}); | |||
|
|||
it('array values support csv', () => { | |||
const flags = getFlags( |
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.
once we figure out other feedback would love the --window-size
and blockedUrlPattern
counter examples here too :)
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.
blockedUrlPattern
just b/c comma could be in a pattern? what if we could escape it?
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.
nvm lets not do that :)
This reverts commit 9fe961a.
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.
lint is unhappy about the tests, but other than .check
I think this LGTM! :)
lighthouse-cli/cli-flags.js
Outdated
@@ -152,6 +161,22 @@ function getFlags(manualArgv) { | |||
.default('enable-error-reporting', undefined) // Undefined so prompted by default | |||
.default('channel', 'cli') | |||
.check(/** @param {LH.CliFlags} argv */ (argv) => { | |||
// ".middleware" does not exist in this version of yargs, so do some preprocessing here. |
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.
still not 100% sure that I love mutating the arguments in a .check
method
WDYT of just saving the .argv
to a variable and mutating that before we return in getFlags
?
I think that might help make it more explicit that we are doing some non-standard yargs mutations
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.
done
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.
LGTM!
Not sure if we want to add an example to show off our new muscles :)
lighthouse-cli/cli-flags.js
Outdated
@@ -171,6 +181,24 @@ function getFlags(manualArgv) { | |||
'For more information on Lighthouse, see https://developers.google.com/web/tools/lighthouse/.') | |||
.wrap(yargs.terminalWidth()) | |||
.argv; | |||
|
|||
// ".middleware" does not exist in this version of yargs, so do some post-processing here. | |||
/** @type {(keyof LH.CliFlags)[]} */ |
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 think we're settling on Array<keyof LH.CliFlags>
for complex types that aren't just string[]
or w/e, though if you ask @brendankenny we're always settling on 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.
though if you ask @brendankenny we're always settling on Array<*> ;)
well, yes, because it's an array, not a string, so why would you put that information last? :P They could have gone [string]
, but they used that up on tuples
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.
typing is hard for cli-flags.js...
lighthouse-cli/cli-flags.js
Outdated
return y.help('help') | ||
function getFlags(...manualArgv) { | ||
const y = manualArgv.length ? yargs(manualArgv) : yargs; | ||
/** @type {LH.CliFlags} */ |
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 doesn't buy us much except having to coerce with /** @type {string[]} */
below
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.
would like to keep /** @type {string[]} */
otherwise more errors come up. I added a comment saying why we can assume it to be a string[].
LH.CliFlags
one could be removed if you want.
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.
would like to keep /** @type {string[]} */ otherwise more errors come up.
but it's wrong because all of this is wrong :)
The ts-ignore was suppressing a different error than it said (I assume/hope it changed at some point), but the comment was still correct ('yargs()
is incorrectly typed as not returning itself'): all the calls on yargs after help()
are of type any
and return any
. In addition:
- the type of
LH.CliFlags[keyof LH.CliFlags]
is definitely not a string array, really it should beLH.CliFlags['onlyAudits'|'onlyCategories'|'output'|'plugins'|'skipAudits']
- if we pretend the type is
string[]
because yargs is returning that for the subset of keys we care about, assigning back asstring[]
is still not correct even for that subset because e.g.output
isLH.OutputMode[]
, notstring[]
(and that's ignoring trying to reassign back toLH.CliFlags[keyof LH.CliFlags]
). This will be an error in tsc 3.5+.
I think the most honest thing is to just leave as any
internal to getFlags
with a note about why and leave it up to tests to verify that getFlags
really is returning LH.CliFlags
.
lighthouse-cli/cli-flags.js
Outdated
const y = manualArgv ? yargs(manualArgv) : yargs; | ||
return y.help('help') | ||
function getFlags(...manualArgv) { | ||
const y = manualArgv.length ? yargs(manualArgv) : yargs; |
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 ends up somewhat confusing from the caller's perspective since it's no longer explicitly optional (even though we usually call it with no args) and when we do pass an argument it's still a single string (it's annoying that the yargs
types require this because yargs
definitely supports parsing just a string).
What about keeping it string=
and doing const y = manualArgv ? yargs([manualArgv]) : yargs;
instead?
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'm confused on how it's confusing to the caller?
if reverting the change, would you want the code using multiple args (admittedly it's just test code) to look like this?
getFlags([
'http://www.example.com',
'--only-categories=performance,seo',
'--skipAudits=unused-javascript,redirects',
'--skipAudits=bootup-time',
].join(' '));
or this?
getFlags('http://www.example.com --only-categories=performance,seo --skipAudits=unused-javascript,redirects --skipAudits=bootup-time');
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.
if reverting the change, would you want the code using multiple args (admittedly it's just test code) to look like this?
yes from me. Maybe it's just that I haven't been completely indoctrinated to rest parameters yet, but to me an optional manualArgv?: string
parameter is a lot clearer than ...manaulArgv: string[]
at informing that the argument is optional. It's not a huge deal since it's not a commonly used interface, but it's only test code that uses this, so it makes sense to me to make the real use case clear in the signature.
lighthouse-cli/cli-flags.js
Outdated
.version(() => pkg.version) | ||
.showHelpOnFail(false, 'Specify --help for available options') | ||
|
||
.usage('lighthouse <url> <options>') | ||
.example( | ||
'lighthouse <url> --view', 'Opens the HTML report in a browser after the run completes') | ||
.example( | ||
'lighthouse <url> --only-categories=performance,pwa', |
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.
kick somewhere below? I'd call --only-categories
less important than --config-path
, --chrome-flags
, etc
lighthouse-cli/cli-flags.js
Outdated
const y = manualArgv ? yargs(manualArgv) : yargs; | ||
return y.help('help') | ||
function getFlags(...manualArgv) { | ||
const y = manualArgv.length ? yargs(manualArgv) : yargs; |
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.
ha, actually, that test failure may be because our version of yargs doesn't take an array at all?
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 passes locally.
(EDIT: misread the build log. one sec)
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.
ok the issue is that if you pass in an array, you cannot have each item have multiple args. test just needs to 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.
also I guess they expect some preprocessing, b/c =
is required too. 6f58b90
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.
also I guess they expect some preprocessing, b/c = is required too.
You can only omit the =
when passing in as a single string? This seems like the real downside...we should be able to write tests using both styles since the real deal accepts both
@brendankenny updated |
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 good, just some last comment feedback
lighthouse-cli/cli-flags.js
Outdated
const result = []; | ||
return result.concat(...arr); | ||
} | ||
|
||
/** | ||
* @param {string=} manualArgv | ||
* @return {LH.CliFlags} | ||
*/ | ||
function getFlags(manualArgv) { | ||
// @ts-ignore yargs() is incorrectly typed as not returning itself |
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.
Maybe update this one as well? // @ts-ignore yargs() is incorrectly typed as not accepting a single 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.
honestly why are we even using @types/yargs
:)
lighthouse-cli/cli-flags.js
Outdated
// since assigning back to argv as string[] would be unsound for enums, | ||
// for example: output is LH.OutputMode[]. | ||
const input = argv[key]; | ||
// Existence check + convinces TS that this is an 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.
"Existence check + "...something else? Or no '+' needed
Co-Authored-By: Brendan Kenny <bckenny@gmail.com>
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. ℹ️ Googlers: Go here for more info. |