feat(core): properly passthrough flags unparsed to executors (#12890)
This commit is contained in:
parent
6baf78cce8
commit
145dda709b
@ -129,6 +129,12 @@ Default: `false`
|
|||||||
|
|
||||||
Rerun the tasks even when the results are available in the cache
|
Rerun the tasks even when the results are available in the cache
|
||||||
|
|
||||||
|
### target
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Task to run for affected projects
|
||||||
|
|
||||||
### type
|
### type
|
||||||
|
|
||||||
Type: `string`
|
Type: `string`
|
||||||
|
|||||||
@ -81,7 +81,7 @@
|
|||||||
"name": "print-affected",
|
"name": "print-affected",
|
||||||
"id": "print-affected",
|
"id": "print-affected",
|
||||||
"file": "generated/cli/print-affected",
|
"file": "generated/cli/print-affected",
|
||||||
"content": "---\ntitle: 'print-affected - CLI command'\ndescription: 'Prints information about the projects and targets affected by changes'\n---\n\n# print-affected\n\nPrints information about the projects and targets affected by changes\n\n## Usage\n\n```terminal\nnx print-affected\n```\n\nInstall `nx` globally to invoke the command directly using `nx`, or use `npx nx`, `yarn nx`, or `pnpm nx`.\n\n### Examples\n\nPrint information about affected projects and the project graph:\n\n```terminal\n nx print-affected\n```\n\nPrint information about the projects affected by the changes between main and HEAD (e.g,. PR):\n\n```terminal\n nx print-affected --base=main --head=HEAD\n```\n\nPrints information about the affected projects and a list of tasks to test them:\n\n```terminal\n nx print-affected --target=test\n```\n\nPrints the projects property from the print-affected output:\n\n```terminal\n nx print-affected --target=build --select=projects\n```\n\nPrints the tasks.target.project property from the print-affected output:\n\n```terminal\n nx print-affected --target=build --select=tasks.target.project\n```\n\n## Options\n\n### all\n\nType: `boolean`\n\nAll projects\n\n### base\n\nType: `string`\n\nBase of the current branch (usually main)\n\n### configuration\n\nType: `string`\n\nThis is the configuration to use when performing tasks on projects\n\n### exclude\n\nType: `array`\n\nDefault: `[]`\n\nExclude certain projects from being processed\n\n### files\n\nType: `array`\n\nChange the way Nx is calculating the affected command by providing directly changed files, list of files delimited by commas\n\n### head\n\nType: `string`\n\nLatest commit of the current branch (usually HEAD)\n\n### help\n\nType: `boolean`\n\nShow help\n\n### nx-bail\n\nType: `boolean`\n\nDefault: `false`\n\nStop command execution after the first failed task\n\n### nx-ignore-cycles\n\nType: `boolean`\n\nDefault: `false`\n\nIgnore cycles in the task graph\n\n### runner\n\nType: `string`\n\nThis is the name of the tasks runner configured in nx.json\n\n### select\n\nType: `string`\n\nSelect the subset of the returned json document (e.g., --select=projects)\n\n### skip-nx-cache\n\nType: `boolean`\n\nDefault: `false`\n\nRerun the tasks even when the results are available in the cache\n\n### type\n\nType: `string`\n\nChoices: [app, lib]\n\nSelect the type of projects to be returned (e.g., --type=app)\n\n### uncommitted\n\nType: `boolean`\n\nUncommitted changes\n\n### untracked\n\nType: `boolean`\n\nUntracked changes\n\n### verbose\n\nType: `boolean`\n\nDefault: `false`\n\nPrints additional information about the commands (e.g., stack traces)\n\n### version\n\nType: `boolean`\n\nShow version number\n"
|
"content": "---\ntitle: 'print-affected - CLI command'\ndescription: 'Prints information about the projects and targets affected by changes'\n---\n\n# print-affected\n\nPrints information about the projects and targets affected by changes\n\n## Usage\n\n```terminal\nnx print-affected\n```\n\nInstall `nx` globally to invoke the command directly using `nx`, or use `npx nx`, `yarn nx`, or `pnpm nx`.\n\n### Examples\n\nPrint information about affected projects and the project graph:\n\n```terminal\n nx print-affected\n```\n\nPrint information about the projects affected by the changes between main and HEAD (e.g,. PR):\n\n```terminal\n nx print-affected --base=main --head=HEAD\n```\n\nPrints information about the affected projects and a list of tasks to test them:\n\n```terminal\n nx print-affected --target=test\n```\n\nPrints the projects property from the print-affected output:\n\n```terminal\n nx print-affected --target=build --select=projects\n```\n\nPrints the tasks.target.project property from the print-affected output:\n\n```terminal\n nx print-affected --target=build --select=tasks.target.project\n```\n\n## Options\n\n### all\n\nType: `boolean`\n\nAll projects\n\n### base\n\nType: `string`\n\nBase of the current branch (usually main)\n\n### configuration\n\nType: `string`\n\nThis is the configuration to use when performing tasks on projects\n\n### exclude\n\nType: `array`\n\nDefault: `[]`\n\nExclude certain projects from being processed\n\n### files\n\nType: `array`\n\nChange the way Nx is calculating the affected command by providing directly changed files, list of files delimited by commas\n\n### head\n\nType: `string`\n\nLatest commit of the current branch (usually HEAD)\n\n### help\n\nType: `boolean`\n\nShow help\n\n### nx-bail\n\nType: `boolean`\n\nDefault: `false`\n\nStop command execution after the first failed task\n\n### nx-ignore-cycles\n\nType: `boolean`\n\nDefault: `false`\n\nIgnore cycles in the task graph\n\n### runner\n\nType: `string`\n\nThis is the name of the tasks runner configured in nx.json\n\n### select\n\nType: `string`\n\nSelect the subset of the returned json document (e.g., --select=projects)\n\n### skip-nx-cache\n\nType: `boolean`\n\nDefault: `false`\n\nRerun the tasks even when the results are available in the cache\n\n### target\n\nType: `string`\n\nTask to run for affected projects\n\n### type\n\nType: `string`\n\nChoices: [app, lib]\n\nSelect the type of projects to be returned (e.g., --type=app)\n\n### uncommitted\n\nType: `boolean`\n\nUncommitted changes\n\n### untracked\n\nType: `boolean`\n\nUntracked changes\n\n### verbose\n\nType: `boolean`\n\nDefault: `false`\n\nPrints additional information about the commands (e.g., stack traces)\n\n### version\n\nType: `boolean`\n\nShow version number\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "format:check",
|
"name": "format:check",
|
||||||
|
|||||||
@ -581,7 +581,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
|||||||
// check building project
|
// check building project
|
||||||
let output = runCLI(`build ${project} --outputHashing none`);
|
let output = runCLI(`build ${project} --outputHashing none`);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`> nx run ${project}:build:production --outputHashing=none`
|
`> nx run ${project}:build:production --outputHashing none`
|
||||||
);
|
);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`Successfully ran target build for project ${project}`
|
`Successfully ran target build for project ${project}`
|
||||||
@ -590,7 +590,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
|||||||
|
|
||||||
output = runCLI(`build ${project} --outputHashing none`);
|
output = runCLI(`build ${project} --outputHashing none`);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`> nx run ${project}:build:production --outputHashing=none [local cache]`
|
`> nx run ${project}:build:production --outputHashing none [local cache]`
|
||||||
);
|
);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`Successfully ran target build for project ${project}`
|
`Successfully ran target build for project ${project}`
|
||||||
@ -599,7 +599,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
|||||||
// check building app1
|
// check building app1
|
||||||
output = runCLI(`build ${app1} --outputHashing none`);
|
output = runCLI(`build ${app1} --outputHashing none`);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`> nx run ${app1}:build:production --outputHashing=none`
|
`> nx run ${app1}:build:production --outputHashing none`
|
||||||
);
|
);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`Successfully ran target build for project ${app1}`
|
`Successfully ran target build for project ${app1}`
|
||||||
@ -608,7 +608,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
|||||||
|
|
||||||
output = runCLI(`build ${app1} --outputHashing none`);
|
output = runCLI(`build ${app1} --outputHashing none`);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`> nx run ${app1}:build:production --outputHashing=none [local cache]`
|
`> nx run ${app1}:build:production --outputHashing none [local cache]`
|
||||||
);
|
);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`Successfully ran target build for project ${app1}`
|
`Successfully ran target build for project ${app1}`
|
||||||
@ -638,7 +638,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
|||||||
// check building an app
|
// check building an app
|
||||||
let output = runCLI(`build ${project} --outputHashing none`);
|
let output = runCLI(`build ${project} --outputHashing none`);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`> nx run ${project}:build:production --outputHashing=none`
|
`> nx run ${project}:build:production --outputHashing none`
|
||||||
);
|
);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`Successfully ran target build for project ${project}`
|
`Successfully ran target build for project ${project}`
|
||||||
@ -647,7 +647,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
|||||||
|
|
||||||
output = runCLI(`build ${project} --outputHashing none`);
|
output = runCLI(`build ${project} --outputHashing none`);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`> nx run ${project}:build:production --outputHashing=none [local cache]`
|
`> nx run ${project}:build:production --outputHashing none [local cache]`
|
||||||
);
|
);
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
`Successfully ran target build for project ${project}`
|
`Successfully ran target build for project ${project}`
|
||||||
|
|||||||
@ -21,6 +21,37 @@ describe('Nx Running Tests', () => {
|
|||||||
afterAll(() => cleanupProject());
|
afterAll(() => cleanupProject());
|
||||||
|
|
||||||
describe('running targets', () => {
|
describe('running targets', () => {
|
||||||
|
describe('(forwarding params)', () => {
|
||||||
|
let proj = uniq('proj');
|
||||||
|
beforeAll(() => {
|
||||||
|
runCLI(`generate @nrwl/workspace:lib ${proj}`);
|
||||||
|
updateProjectConfig(proj, (c) => {
|
||||||
|
c.targets['echo'] = {
|
||||||
|
executor: 'nx:run-commands',
|
||||||
|
options: {
|
||||||
|
command: 'echo ECHO:',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return c;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
'--watch false',
|
||||||
|
'--watch=false',
|
||||||
|
'--arr=a,b,c',
|
||||||
|
'--arr=a --arr=b --arr=c',
|
||||||
|
'a',
|
||||||
|
'--a.b=1',
|
||||||
|
'--a.b 1',
|
||||||
|
'-- a b c --a --a.b=1',
|
||||||
|
'--ignored -- a b c --a --a.b=1',
|
||||||
|
])('should forward %s properly', (args) => {
|
||||||
|
const output = runCLI(`echo ${proj} ${args}`);
|
||||||
|
expect(output).toContain(`ECHO: ${args.replace(/^.*-- /, '')}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should execute long running tasks', async () => {
|
it('should execute long running tasks', async () => {
|
||||||
const myapp = uniq('myapp');
|
const myapp = uniq('myapp');
|
||||||
runCLI(`generate @nrwl/web:app ${myapp}`);
|
runCLI(`generate @nrwl/web:app ${myapp}`);
|
||||||
|
|||||||
@ -191,7 +191,9 @@ export const commandsObject = yargs
|
|||||||
'Prints information about the projects and targets affected by changes',
|
'Prints information about the projects and targets affected by changes',
|
||||||
builder: (yargs) =>
|
builder: (yargs) =>
|
||||||
linkToNxDevAndExamples(
|
linkToNxDevAndExamples(
|
||||||
withAffectedOptions(withPrintAffectedOptions(yargs)),
|
withAffectedOptions(
|
||||||
|
withTargetOption(withPrintAffectedOptions(yargs), false)
|
||||||
|
),
|
||||||
'print-affected'
|
'print-affected'
|
||||||
),
|
),
|
||||||
handler: async (args) => {
|
handler: async (args) => {
|
||||||
@ -406,9 +408,9 @@ function withPlainOption(yargs: yargs.Argv): yargs.Argv {
|
|||||||
function withAffectedOptions(yargs: yargs.Argv): yargs.Argv {
|
function withAffectedOptions(yargs: yargs.Argv): yargs.Argv {
|
||||||
return yargs
|
return yargs
|
||||||
.parserConfiguration({
|
.parserConfiguration({
|
||||||
'camel-case-expansion': false,
|
'strip-dashed': true,
|
||||||
// allow parsing --env.SOME_ARG for cypress cli env args
|
'unknown-options-as-args': true,
|
||||||
'dot-notation': true,
|
'populate--': true,
|
||||||
})
|
})
|
||||||
.option('files', {
|
.option('files', {
|
||||||
describe:
|
describe:
|
||||||
@ -473,6 +475,12 @@ function withAffectedOptions(yargs: yargs.Argv): yargs.Argv {
|
|||||||
'This is the configuration to use when performing tasks on projects',
|
'This is the configuration to use when performing tasks on projects',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
})
|
})
|
||||||
|
.option('prod', {
|
||||||
|
describe: 'Use the production configuration',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
hidden: true,
|
||||||
|
})
|
||||||
.option('verbose', {
|
.option('verbose', {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
describe:
|
describe:
|
||||||
@ -494,15 +502,32 @@ function withAffectedOptions(yargs: yargs.Argv): yargs.Argv {
|
|||||||
untracked: ['uncommitted', 'files', 'base', 'head', 'all'],
|
untracked: ['uncommitted', 'files', 'base', 'head', 'all'],
|
||||||
uncommitted: ['files', 'untracked', 'base', 'head', 'all'],
|
uncommitted: ['files', 'untracked', 'base', 'head', 'all'],
|
||||||
all: ['files', 'untracked', 'uncommitted', 'base', 'head'],
|
all: ['files', 'untracked', 'uncommitted', 'base', 'head'],
|
||||||
|
})
|
||||||
|
.check((nxArgs) => {
|
||||||
|
if (
|
||||||
|
!nxArgs.files &&
|
||||||
|
!nxArgs.uncommitted &&
|
||||||
|
!nxArgs.untracked &&
|
||||||
|
!nxArgs.base &&
|
||||||
|
!nxArgs.head &&
|
||||||
|
!nxArgs.all &&
|
||||||
|
nxArgs._ &&
|
||||||
|
nxArgs._.length >= 3
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`Nx no longer supports using positional arguments for base and head. Please use --base and --head instead.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function withRunManyOptions(yargs: yargs.Argv): yargs.Argv {
|
function withRunManyOptions(yargs: yargs.Argv): yargs.Argv {
|
||||||
return yargs
|
return yargs
|
||||||
.parserConfiguration({
|
.parserConfiguration({
|
||||||
'camel-case-expansion': false,
|
'strip-dashed': true,
|
||||||
// allow parsing --env.SOME_ARG for cypress cli env args
|
'unknown-options-as-args': true,
|
||||||
'dot-notation': true,
|
'populate--': true,
|
||||||
})
|
})
|
||||||
.option('projects', {
|
.option('projects', {
|
||||||
describe: 'Projects to run (comma delimited)',
|
describe: 'Projects to run (comma delimited)',
|
||||||
@ -513,6 +538,12 @@ function withRunManyOptions(yargs: yargs.Argv): yargs.Argv {
|
|||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
|
.option('prod', {
|
||||||
|
describe: 'Use the production configuration',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
hidden: true,
|
||||||
|
})
|
||||||
.options('runner', {
|
.options('runner', {
|
||||||
describe: 'Override the tasks runner in `nx.json`',
|
describe: 'Override the tasks runner in `nx.json`',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
@ -596,16 +627,12 @@ function withDepGraphOptions(yargs: yargs.Argv): yargs.Argv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function withOverrides(args: any): any {
|
function withOverrides(args: any): any {
|
||||||
const split = process.argv.indexOf('--');
|
args.__overrides_unparsed__ = (args['--'] ?? args._.slice(1)).map((v) =>
|
||||||
if (split > -1) {
|
v.toString()
|
||||||
const overrides = process.argv.slice(split + 1);
|
);
|
||||||
delete args._;
|
delete args['--'];
|
||||||
return { ...args, __overrides__: overrides };
|
delete args._;
|
||||||
} else {
|
return args;
|
||||||
args['__positional_overrides__'] = args._.slice(1);
|
|
||||||
delete args._;
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function withParallelOption(yargs: yargs.Argv): yargs.Argv {
|
function withParallelOption(yargs: yargs.Argv): yargs.Argv {
|
||||||
@ -623,12 +650,12 @@ function withOutputStyleOption(yargs: yargs.Argv): yargs.Argv {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function withTargetOption(yargs: yargs.Argv): yargs.Argv {
|
function withTargetOption(yargs: yargs.Argv, demandOption = true): yargs.Argv {
|
||||||
return yargs.option('target', {
|
return yargs.option('target', {
|
||||||
describe: 'Task to run for affected projects',
|
describe: 'Task to run for affected projects',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
requiresArg: true,
|
requiresArg: true,
|
||||||
demandOption: true,
|
demandOption,
|
||||||
global: false,
|
global: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -687,11 +714,11 @@ function withRunOneOptions(yargs: yargs.Argv) {
|
|||||||
const executorShouldShowHelp = !(
|
const executorShouldShowHelp = !(
|
||||||
process.argv[2] === 'run' && process.argv[3] === '--help'
|
process.argv[2] === 'run' && process.argv[3] === '--help'
|
||||||
);
|
);
|
||||||
const res = yargs
|
const res = withOutputStyleOption(yargs)
|
||||||
.parserConfiguration({
|
.parserConfiguration({
|
||||||
'camel-case-expansion': false,
|
'strip-dashed': true,
|
||||||
// allow parsing --env.SOME_ARG for cypress cli env args
|
'unknown-options-as-args': true,
|
||||||
'dot-notation': true,
|
'populate--': true,
|
||||||
})
|
})
|
||||||
.option('prod', {
|
.option('prod', {
|
||||||
describe: 'Use the production configuration',
|
describe: 'Use the production configuration',
|
||||||
|
|||||||
@ -9,8 +9,7 @@ describe('splitArgs', () => {
|
|||||||
{
|
{
|
||||||
base: 'sha1',
|
base: 'sha1',
|
||||||
head: 'sha2',
|
head: 'sha2',
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['--notNxArg', '--override'],
|
||||||
override: true,
|
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -27,24 +26,22 @@ describe('splitArgs', () => {
|
|||||||
it('should put every command start with nx to nxArgs', () => {
|
it('should put every command start with nx to nxArgs', () => {
|
||||||
const nxArgs = splitArgsIntoNxArgsAndOverrides(
|
const nxArgs = splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
'nx-key': 'some-value',
|
nxBail: 'some-value',
|
||||||
nxKey: 'some-value',
|
__overrides_unparsed__: ['--override'],
|
||||||
_: ['--override'],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
{} as any,
|
{} as any,
|
||||||
{} as any
|
{} as any
|
||||||
).nxArgs;
|
).nxArgs;
|
||||||
expect(nxArgs['nxKey']).toEqual('some-value');
|
expect(nxArgs['nxBail']).toEqual('some-value');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should default to having a base of main', () => {
|
it('should default to having a base of main', () => {
|
||||||
expect(
|
expect(
|
||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['--notNxArg', '--override'],
|
||||||
_: ['--override'],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -61,8 +58,7 @@ describe('splitArgs', () => {
|
|||||||
expect(
|
expect(
|
||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['--notNxArg', '--override'],
|
||||||
_: ['--override'],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -79,8 +75,7 @@ describe('splitArgs', () => {
|
|||||||
expect(
|
expect(
|
||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['--notNxArg', 'affecteda', '--override'],
|
||||||
_: ['affecteda', '--override'],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -98,8 +93,7 @@ describe('splitArgs', () => {
|
|||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
files: [''],
|
files: [''],
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['--notNxArg'],
|
||||||
__positional_overrides__: [],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -117,8 +111,7 @@ describe('splitArgs', () => {
|
|||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
files: [''],
|
files: [''],
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['positional', '--notNxArg'],
|
||||||
__positional_overrides__: ['positional'],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -137,8 +130,7 @@ describe('splitArgs', () => {
|
|||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
files: [''],
|
files: [''],
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['explicit'],
|
||||||
_: ['explicit'],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -151,19 +143,22 @@ describe('splitArgs', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when base and head are set as positional args', () => {
|
it('should be able to parse arguments in __overrides__', () => {
|
||||||
expect(() =>
|
expect(
|
||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
notNxArg: true,
|
files: [''],
|
||||||
__positional_overrides__: ['sha1', 'sha2'],
|
__overrides__: ['explicit'],
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
{} as any,
|
{} as any,
|
||||||
{} as any
|
{} as any
|
||||||
)
|
).overrides
|
||||||
).toThrow();
|
).toEqual({
|
||||||
|
__overrides_unparsed__: ['explicit'],
|
||||||
|
_: ['explicit'],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set base and head based on environment variables in affected mode, if they are not provided directly on the command', () => {
|
it('should set base and head based on environment variables in affected mode, if they are not provided directly on the command', () => {
|
||||||
@ -175,8 +170,7 @@ describe('splitArgs', () => {
|
|||||||
expect(
|
expect(
|
||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['--notNxArg', 'true', '--override'],
|
||||||
_: ['--override'],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -192,8 +186,7 @@ describe('splitArgs', () => {
|
|||||||
expect(
|
expect(
|
||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['--notNxArg', 'true', '--override'],
|
||||||
_: ['--override'],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
head: 'directlyOnCommandSha1', // higher priority than $NX_HEAD
|
head: 'directlyOnCommandSha1', // higher priority than $NX_HEAD
|
||||||
},
|
},
|
||||||
@ -210,8 +203,7 @@ describe('splitArgs', () => {
|
|||||||
expect(
|
expect(
|
||||||
splitArgsIntoNxArgsAndOverrides(
|
splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
notNxArg: true,
|
__overrides_unparsed__: ['--notNxArg', 'true', '--override'],
|
||||||
_: ['--override'],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
base: 'directlyOnCommandSha2', // higher priority than $NX_BASE
|
base: 'directlyOnCommandSha2', // higher priority than $NX_BASE
|
||||||
},
|
},
|
||||||
@ -234,8 +226,8 @@ describe('splitArgs', () => {
|
|||||||
it('should be a number', () => {
|
it('should be a number', () => {
|
||||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
_: [],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
|
__overrides_unparsed__: [],
|
||||||
parallel: '5',
|
parallel: '5',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -249,8 +241,8 @@ describe('splitArgs', () => {
|
|||||||
it('should default to 3', () => {
|
it('should default to 3', () => {
|
||||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
_: [],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
|
__overrides_unparsed__: [],
|
||||||
parallel: '',
|
parallel: '',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -264,8 +256,8 @@ describe('splitArgs', () => {
|
|||||||
it('should be 3 when set to true', () => {
|
it('should be 3 when set to true', () => {
|
||||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
_: [],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
|
__overrides_unparsed__: [],
|
||||||
parallel: 'true',
|
parallel: 'true',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -279,8 +271,8 @@ describe('splitArgs', () => {
|
|||||||
it('should be 1 when set to false', () => {
|
it('should be 1 when set to false', () => {
|
||||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
_: [],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
|
__overrides_unparsed__: [],
|
||||||
parallel: 'false',
|
parallel: 'false',
|
||||||
},
|
},
|
||||||
'affected',
|
'affected',
|
||||||
@ -294,8 +286,8 @@ describe('splitArgs', () => {
|
|||||||
it('should use the maxParallel option when given', () => {
|
it('should use the maxParallel option when given', () => {
|
||||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
_: [],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
|
__overrides_unparsed__: [],
|
||||||
parallel: '',
|
parallel: '',
|
||||||
maxParallel: 5,
|
maxParallel: 5,
|
||||||
},
|
},
|
||||||
@ -310,8 +302,8 @@ describe('splitArgs', () => {
|
|||||||
it('should use the maxParallel option when given', () => {
|
it('should use the maxParallel option when given', () => {
|
||||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||||
{
|
{
|
||||||
_: [],
|
|
||||||
$0: '',
|
$0: '',
|
||||||
|
__overrides_unparsed__: [],
|
||||||
parallel: '',
|
parallel: '',
|
||||||
maxParallel: 5,
|
maxParallel: 5,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,104 +1,11 @@
|
|||||||
import * as yargsParser from 'yargs-parser';
|
import * as yargsParser from 'yargs-parser';
|
||||||
import * as yargs from 'yargs';
|
import type { Arguments } from 'yargs';
|
||||||
import { TEN_MEGABYTES } from '../project-graph/file-utils';
|
import { TEN_MEGABYTES } from '../project-graph/file-utils';
|
||||||
import { output } from './output';
|
import { output } from './output';
|
||||||
import { NxJsonConfiguration } from '../config/nx-json';
|
import { NxJsonConfiguration } from '../config/nx-json';
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
import { serializeOverridesIntoCommandLine } from './serialize-overrides-into-command-line';
|
|
||||||
import { ProjectGraph } from '../config/project-graph';
|
import { ProjectGraph } from '../config/project-graph';
|
||||||
|
|
||||||
export function names(name: string): {
|
|
||||||
name: string;
|
|
||||||
className: string;
|
|
||||||
propertyName: string;
|
|
||||||
constantName: string;
|
|
||||||
fileName: string;
|
|
||||||
} {
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
className: toClassName(name),
|
|
||||||
propertyName: toPropertyName(name),
|
|
||||||
constantName: toConstantName(name),
|
|
||||||
fileName: toFileName(name),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hyphenated to UpperCamelCase
|
|
||||||
*/
|
|
||||||
function toClassName(str: string): string {
|
|
||||||
return toCapitalCase(toPropertyName(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hyphenated to lowerCamelCase
|
|
||||||
*/
|
|
||||||
function toPropertyName(s: string): string {
|
|
||||||
return s
|
|
||||||
.replace(/([^a-zA-Z0-9])+(.)?/g, (_, __, chr) =>
|
|
||||||
chr ? chr.toUpperCase() : ''
|
|
||||||
)
|
|
||||||
.replace(/[^a-zA-Z\d]/g, '')
|
|
||||||
.replace(/^([A-Z])/, (m) => m.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hyphenated to CONSTANT_CASE
|
|
||||||
*/
|
|
||||||
function toConstantName(s: string): string {
|
|
||||||
return s.replace(/([^a-zA-Z0-9])/g, '_').toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upper camelCase to lowercase, hyphenated
|
|
||||||
*/
|
|
||||||
function toFileName(s: string): string {
|
|
||||||
return s
|
|
||||||
.replace(/([a-z\d])([A-Z])/g, '$1_$2')
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(/[ _]/g, '-');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Capitalizes the first letter of a string
|
|
||||||
*/
|
|
||||||
function toCapitalCase(s: string): string {
|
|
||||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const runOne: string[] = [
|
|
||||||
'target',
|
|
||||||
'configuration',
|
|
||||||
'prod',
|
|
||||||
'runner',
|
|
||||||
'parallel',
|
|
||||||
'maxParallel',
|
|
||||||
'exclude',
|
|
||||||
'help',
|
|
||||||
'skipNxCache',
|
|
||||||
'outputStyle',
|
|
||||||
'nxBail',
|
|
||||||
'nxIgnoreCycles',
|
|
||||||
'verbose',
|
|
||||||
'cloud',
|
|
||||||
'dte',
|
|
||||||
];
|
|
||||||
|
|
||||||
const runMany: string[] = [...runOne, 'projects', 'all'];
|
|
||||||
|
|
||||||
const runAffected: string[] = [
|
|
||||||
...runOne,
|
|
||||||
'untracked',
|
|
||||||
'uncommitted',
|
|
||||||
'all',
|
|
||||||
'base',
|
|
||||||
'head',
|
|
||||||
'files',
|
|
||||||
'plain',
|
|
||||||
'select',
|
|
||||||
'type',
|
|
||||||
];
|
|
||||||
|
|
||||||
export interface RawNxArgs extends NxArgs {
|
export interface RawNxArgs extends NxArgs {
|
||||||
prod?: boolean;
|
prod?: boolean;
|
||||||
}
|
}
|
||||||
@ -128,79 +35,40 @@ export interface NxArgs {
|
|||||||
type?: string;
|
type?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ignoreArgs = ['$0', '_'];
|
|
||||||
|
|
||||||
export function splitArgsIntoNxArgsAndOverrides(
|
export function splitArgsIntoNxArgsAndOverrides(
|
||||||
args: { [k: string]: any },
|
args: { [k: string]: any },
|
||||||
mode: 'run-one' | 'run-many' | 'affected' | 'print-affected',
|
mode: 'run-one' | 'run-many' | 'affected' | 'print-affected',
|
||||||
options = { printWarnings: true },
|
options = { printWarnings: true },
|
||||||
nxJson: NxJsonConfiguration
|
nxJson: NxJsonConfiguration
|
||||||
): { nxArgs: NxArgs; overrides: yargs.Arguments } {
|
): { nxArgs: NxArgs; overrides: Arguments } {
|
||||||
if (!args.__overrides__ && args._) {
|
if (!args.__overrides_unparsed__ && args._) {
|
||||||
// required for backwards compatibility
|
// required for backwards compatibility
|
||||||
args.__overrides__ = args._;
|
args.__overrides_unparsed__ = args._;
|
||||||
|
delete args._;
|
||||||
|
}
|
||||||
|
// This handles the way Lerna passes in overrides
|
||||||
|
if (!args.__overrides_unparsed__ && args.__overrides__) {
|
||||||
|
// required for backwards compatibility
|
||||||
|
args.__overrides_unparsed__ = args.__overrides__;
|
||||||
delete args._;
|
delete args._;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nxSpecific =
|
const nxArgs: RawNxArgs = args;
|
||||||
mode === 'run-one' ? runOne : mode === 'run-many' ? runMany : runAffected;
|
let overrides = yargsParser(args.__overrides_unparsed__ as string[], {
|
||||||
|
configuration: {
|
||||||
let explicitOverrides;
|
'camel-case-expansion': false,
|
||||||
if (args.__overrides__) {
|
'dot-notation': true,
|
||||||
explicitOverrides = yargsParser(args.__overrides__ as string[], {
|
},
|
||||||
configuration: {
|
|
||||||
'camel-case-expansion': false,
|
|
||||||
'dot-notation': false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!explicitOverrides._ || explicitOverrides._.length === 0) {
|
|
||||||
delete explicitOverrides._;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const overridesFromMainArgs = {} as any;
|
|
||||||
if (
|
|
||||||
args['__positional_overrides__'] &&
|
|
||||||
args['__positional_overrides__'].length > 0
|
|
||||||
) {
|
|
||||||
overridesFromMainArgs['_'] = args['__positional_overrides__'];
|
|
||||||
}
|
|
||||||
const nxArgs: RawNxArgs = {};
|
|
||||||
Object.entries(args).forEach(([key, value]) => {
|
|
||||||
const camelCased = names(key).propertyName;
|
|
||||||
if (nxSpecific.includes(camelCased) || camelCased.startsWith('nx')) {
|
|
||||||
if (value !== undefined) nxArgs[camelCased] = value;
|
|
||||||
} else if (
|
|
||||||
!ignoreArgs.includes(key) &&
|
|
||||||
key !== '__positional_overrides__' &&
|
|
||||||
key !== '__overrides__'
|
|
||||||
) {
|
|
||||||
overridesFromMainArgs[key] = value;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let overrides;
|
if (!overrides._ || overrides._.length === 0) {
|
||||||
if (explicitOverrides) {
|
delete overrides._;
|
||||||
overrides = explicitOverrides;
|
|
||||||
overrides['__overrides_unparsed__'] = args.__overrides__;
|
|
||||||
if (
|
|
||||||
Object.keys(overridesFromMainArgs).length > 0 &&
|
|
||||||
options.printWarnings
|
|
||||||
) {
|
|
||||||
const s = Object.keys(overridesFromMainArgs).join(', ');
|
|
||||||
output.warn({
|
|
||||||
title: `Nx didn't recognize the following args: ${s}`,
|
|
||||||
bodyLines: [
|
|
||||||
"When using '--' all executor args have to be defined after '--'.",
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
overrides = overridesFromMainArgs;
|
|
||||||
overrides['__overrides_unparsed__'] = serializeOverridesIntoCommandLine(
|
|
||||||
overridesFromMainArgs
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
overrides.__overrides_unparsed__ = args.__overrides_unparsed__;
|
||||||
|
delete (nxArgs as any).$0;
|
||||||
|
delete (nxArgs as any).__overrides_unparsed__;
|
||||||
|
|
||||||
if (mode === 'run-many') {
|
if (mode === 'run-many') {
|
||||||
if (!nxArgs.projects) {
|
if (!nxArgs.projects) {
|
||||||
nxArgs.projects = [];
|
nxArgs.projects = [];
|
||||||
@ -232,21 +100,6 @@ export function splitArgsIntoNxArgsAndOverrides(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
!nxArgs.files &&
|
|
||||||
!nxArgs.uncommitted &&
|
|
||||||
!nxArgs.untracked &&
|
|
||||||
!nxArgs.base &&
|
|
||||||
!nxArgs.head &&
|
|
||||||
!nxArgs.all &&
|
|
||||||
overridesFromMainArgs._ &&
|
|
||||||
overridesFromMainArgs._.length >= 2
|
|
||||||
) {
|
|
||||||
throw new Error(
|
|
||||||
`Nx no longer supports using positional arguments for base and head. Please use --base and --head instead.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow setting base and head via environment variables (lower priority then direct command arguments)
|
// Allow setting base and head via environment variables (lower priority then direct command arguments)
|
||||||
if (!nxArgs.base && process.env.NX_BASE) {
|
if (!nxArgs.base && process.env.NX_BASE) {
|
||||||
nxArgs.base = process.env.NX_BASE;
|
nxArgs.base = process.env.NX_BASE;
|
||||||
|
|||||||
@ -183,6 +183,7 @@ export async function parseCommand(
|
|||||||
type: builderOptionTypes[key],
|
type: builderOptionTypes[key],
|
||||||
choices: builderOptionsChoices[key],
|
choices: builderOptionsChoices[key],
|
||||||
deprecated: builderDeprecatedOptions[key],
|
deprecated: builderDeprecatedOptions[key],
|
||||||
|
hidden: builderOptions.hiddenOptions.includes(key),
|
||||||
})) || null,
|
})) || null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -194,6 +195,7 @@ export function generateOptionsMarkdown(command): string {
|
|||||||
|
|
||||||
command.options
|
command.options
|
||||||
.sort((a, b) => sortAlphabeticallyFunction(a.name, b.name))
|
.sort((a, b) => sortAlphabeticallyFunction(a.name, b.name))
|
||||||
|
.filter(({ hidden }) => !hidden)
|
||||||
.forEach((option) => {
|
.forEach((option) => {
|
||||||
response += `\n### ${
|
response += `\n### ${
|
||||||
option.deprecated ? `~~${option.name}~~` : option.name
|
option.deprecated ? `~~${option.name}~~` : option.name
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user