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
|
||||
|
||||
### target
|
||||
|
||||
Type: `string`
|
||||
|
||||
Task to run for affected projects
|
||||
|
||||
### type
|
||||
|
||||
Type: `string`
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
"name": "print-affected",
|
||||
"id": "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",
|
||||
|
||||
@ -581,7 +581,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
// check building project
|
||||
let output = runCLI(`build ${project} --outputHashing none`);
|
||||
expect(output).toContain(
|
||||
`> nx run ${project}:build:production --outputHashing=none`
|
||||
`> nx run ${project}:build:production --outputHashing none`
|
||||
);
|
||||
expect(output).toContain(
|
||||
`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`);
|
||||
expect(output).toContain(
|
||||
`> nx run ${project}:build:production --outputHashing=none [local cache]`
|
||||
`> nx run ${project}:build:production --outputHashing none [local cache]`
|
||||
);
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${project}`
|
||||
@ -599,7 +599,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
// check building app1
|
||||
output = runCLI(`build ${app1} --outputHashing none`);
|
||||
expect(output).toContain(
|
||||
`> nx run ${app1}:build:production --outputHashing=none`
|
||||
`> nx run ${app1}:build:production --outputHashing none`
|
||||
);
|
||||
expect(output).toContain(
|
||||
`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`);
|
||||
expect(output).toContain(
|
||||
`> nx run ${app1}:build:production --outputHashing=none [local cache]`
|
||||
`> nx run ${app1}:build:production --outputHashing none [local cache]`
|
||||
);
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${app1}`
|
||||
@ -638,7 +638,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
// check building an app
|
||||
let output = runCLI(`build ${project} --outputHashing none`);
|
||||
expect(output).toContain(
|
||||
`> nx run ${project}:build:production --outputHashing=none`
|
||||
`> nx run ${project}:build:production --outputHashing none`
|
||||
);
|
||||
expect(output).toContain(
|
||||
`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`);
|
||||
expect(output).toContain(
|
||||
`> nx run ${project}:build:production --outputHashing=none [local cache]`
|
||||
`> nx run ${project}:build:production --outputHashing none [local cache]`
|
||||
);
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${project}`
|
||||
|
||||
@ -21,6 +21,37 @@ describe('Nx Running Tests', () => {
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
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 () => {
|
||||
const myapp = uniq('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',
|
||||
builder: (yargs) =>
|
||||
linkToNxDevAndExamples(
|
||||
withAffectedOptions(withPrintAffectedOptions(yargs)),
|
||||
withAffectedOptions(
|
||||
withTargetOption(withPrintAffectedOptions(yargs), false)
|
||||
),
|
||||
'print-affected'
|
||||
),
|
||||
handler: async (args) => {
|
||||
@ -406,9 +408,9 @@ function withPlainOption(yargs: yargs.Argv): yargs.Argv {
|
||||
function withAffectedOptions(yargs: yargs.Argv): yargs.Argv {
|
||||
return yargs
|
||||
.parserConfiguration({
|
||||
'camel-case-expansion': false,
|
||||
// allow parsing --env.SOME_ARG for cypress cli env args
|
||||
'dot-notation': true,
|
||||
'strip-dashed': true,
|
||||
'unknown-options-as-args': true,
|
||||
'populate--': true,
|
||||
})
|
||||
.option('files', {
|
||||
describe:
|
||||
@ -473,6 +475,12 @@ function withAffectedOptions(yargs: yargs.Argv): yargs.Argv {
|
||||
'This is the configuration to use when performing tasks on projects',
|
||||
type: 'string',
|
||||
})
|
||||
.option('prod', {
|
||||
describe: 'Use the production configuration',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
hidden: true,
|
||||
})
|
||||
.option('verbose', {
|
||||
type: 'boolean',
|
||||
describe:
|
||||
@ -494,15 +502,32 @@ function withAffectedOptions(yargs: yargs.Argv): yargs.Argv {
|
||||
untracked: ['uncommitted', 'files', 'base', 'head', 'all'],
|
||||
uncommitted: ['files', 'untracked', 'base', 'head', 'all'],
|
||||
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 {
|
||||
return yargs
|
||||
.parserConfiguration({
|
||||
'camel-case-expansion': false,
|
||||
// allow parsing --env.SOME_ARG for cypress cli env args
|
||||
'dot-notation': true,
|
||||
'strip-dashed': true,
|
||||
'unknown-options-as-args': true,
|
||||
'populate--': true,
|
||||
})
|
||||
.option('projects', {
|
||||
describe: 'Projects to run (comma delimited)',
|
||||
@ -513,6 +538,12 @@ function withRunManyOptions(yargs: yargs.Argv): yargs.Argv {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
})
|
||||
.option('prod', {
|
||||
describe: 'Use the production configuration',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
hidden: true,
|
||||
})
|
||||
.options('runner', {
|
||||
describe: 'Override the tasks runner in `nx.json`',
|
||||
type: 'string',
|
||||
@ -596,16 +627,12 @@ function withDepGraphOptions(yargs: yargs.Argv): yargs.Argv {
|
||||
}
|
||||
|
||||
function withOverrides(args: any): any {
|
||||
const split = process.argv.indexOf('--');
|
||||
if (split > -1) {
|
||||
const overrides = process.argv.slice(split + 1);
|
||||
delete args._;
|
||||
return { ...args, __overrides__: overrides };
|
||||
} else {
|
||||
args['__positional_overrides__'] = args._.slice(1);
|
||||
args.__overrides_unparsed__ = (args['--'] ?? args._.slice(1)).map((v) =>
|
||||
v.toString()
|
||||
);
|
||||
delete args['--'];
|
||||
delete args._;
|
||||
return args;
|
||||
}
|
||||
}
|
||||
|
||||
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', {
|
||||
describe: 'Task to run for affected projects',
|
||||
type: 'string',
|
||||
requiresArg: true,
|
||||
demandOption: true,
|
||||
demandOption,
|
||||
global: false,
|
||||
});
|
||||
}
|
||||
@ -687,11 +714,11 @@ function withRunOneOptions(yargs: yargs.Argv) {
|
||||
const executorShouldShowHelp = !(
|
||||
process.argv[2] === 'run' && process.argv[3] === '--help'
|
||||
);
|
||||
const res = yargs
|
||||
const res = withOutputStyleOption(yargs)
|
||||
.parserConfiguration({
|
||||
'camel-case-expansion': false,
|
||||
// allow parsing --env.SOME_ARG for cypress cli env args
|
||||
'dot-notation': true,
|
||||
'strip-dashed': true,
|
||||
'unknown-options-as-args': true,
|
||||
'populate--': true,
|
||||
})
|
||||
.option('prod', {
|
||||
describe: 'Use the production configuration',
|
||||
|
||||
@ -9,8 +9,7 @@ describe('splitArgs', () => {
|
||||
{
|
||||
base: 'sha1',
|
||||
head: 'sha2',
|
||||
notNxArg: true,
|
||||
override: true,
|
||||
__overrides_unparsed__: ['--notNxArg', '--override'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
@ -27,24 +26,22 @@ describe('splitArgs', () => {
|
||||
it('should put every command start with nx to nxArgs', () => {
|
||||
const nxArgs = splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
'nx-key': 'some-value',
|
||||
nxKey: 'some-value',
|
||||
_: ['--override'],
|
||||
nxBail: 'some-value',
|
||||
__overrides_unparsed__: ['--override'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
{} as any,
|
||||
{} as any
|
||||
).nxArgs;
|
||||
expect(nxArgs['nxKey']).toEqual('some-value');
|
||||
expect(nxArgs['nxBail']).toEqual('some-value');
|
||||
});
|
||||
|
||||
it('should default to having a base of main', () => {
|
||||
expect(
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
notNxArg: true,
|
||||
_: ['--override'],
|
||||
__overrides_unparsed__: ['--notNxArg', '--override'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
@ -61,8 +58,7 @@ describe('splitArgs', () => {
|
||||
expect(
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
notNxArg: true,
|
||||
_: ['--override'],
|
||||
__overrides_unparsed__: ['--notNxArg', '--override'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
@ -79,8 +75,7 @@ describe('splitArgs', () => {
|
||||
expect(
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
notNxArg: true,
|
||||
_: ['affecteda', '--override'],
|
||||
__overrides_unparsed__: ['--notNxArg', 'affecteda', '--override'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
@ -98,8 +93,7 @@ describe('splitArgs', () => {
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
files: [''],
|
||||
notNxArg: true,
|
||||
__positional_overrides__: [],
|
||||
__overrides_unparsed__: ['--notNxArg'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
@ -117,8 +111,7 @@ describe('splitArgs', () => {
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
files: [''],
|
||||
notNxArg: true,
|
||||
__positional_overrides__: ['positional'],
|
||||
__overrides_unparsed__: ['positional', '--notNxArg'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
@ -137,8 +130,7 @@ describe('splitArgs', () => {
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
files: [''],
|
||||
notNxArg: true,
|
||||
_: ['explicit'],
|
||||
__overrides_unparsed__: ['explicit'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
@ -151,19 +143,22 @@ describe('splitArgs', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw when base and head are set as positional args', () => {
|
||||
expect(() =>
|
||||
it('should be able to parse arguments in __overrides__', () => {
|
||||
expect(
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
notNxArg: true,
|
||||
__positional_overrides__: ['sha1', 'sha2'],
|
||||
files: [''],
|
||||
__overrides__: ['explicit'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
{} as any,
|
||||
{} as any
|
||||
)
|
||||
).toThrow();
|
||||
).overrides
|
||||
).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', () => {
|
||||
@ -175,8 +170,7 @@ describe('splitArgs', () => {
|
||||
expect(
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
notNxArg: true,
|
||||
_: ['--override'],
|
||||
__overrides_unparsed__: ['--notNxArg', 'true', '--override'],
|
||||
$0: '',
|
||||
},
|
||||
'affected',
|
||||
@ -192,8 +186,7 @@ describe('splitArgs', () => {
|
||||
expect(
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
notNxArg: true,
|
||||
_: ['--override'],
|
||||
__overrides_unparsed__: ['--notNxArg', 'true', '--override'],
|
||||
$0: '',
|
||||
head: 'directlyOnCommandSha1', // higher priority than $NX_HEAD
|
||||
},
|
||||
@ -210,8 +203,7 @@ describe('splitArgs', () => {
|
||||
expect(
|
||||
splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
notNxArg: true,
|
||||
_: ['--override'],
|
||||
__overrides_unparsed__: ['--notNxArg', 'true', '--override'],
|
||||
$0: '',
|
||||
base: 'directlyOnCommandSha2', // higher priority than $NX_BASE
|
||||
},
|
||||
@ -234,8 +226,8 @@ describe('splitArgs', () => {
|
||||
it('should be a number', () => {
|
||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
_: [],
|
||||
$0: '',
|
||||
__overrides_unparsed__: [],
|
||||
parallel: '5',
|
||||
},
|
||||
'affected',
|
||||
@ -249,8 +241,8 @@ describe('splitArgs', () => {
|
||||
it('should default to 3', () => {
|
||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
_: [],
|
||||
$0: '',
|
||||
__overrides_unparsed__: [],
|
||||
parallel: '',
|
||||
},
|
||||
'affected',
|
||||
@ -264,8 +256,8 @@ describe('splitArgs', () => {
|
||||
it('should be 3 when set to true', () => {
|
||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
_: [],
|
||||
$0: '',
|
||||
__overrides_unparsed__: [],
|
||||
parallel: 'true',
|
||||
},
|
||||
'affected',
|
||||
@ -279,8 +271,8 @@ describe('splitArgs', () => {
|
||||
it('should be 1 when set to false', () => {
|
||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
_: [],
|
||||
$0: '',
|
||||
__overrides_unparsed__: [],
|
||||
parallel: 'false',
|
||||
},
|
||||
'affected',
|
||||
@ -294,8 +286,8 @@ describe('splitArgs', () => {
|
||||
it('should use the maxParallel option when given', () => {
|
||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
_: [],
|
||||
$0: '',
|
||||
__overrides_unparsed__: [],
|
||||
parallel: '',
|
||||
maxParallel: 5,
|
||||
},
|
||||
@ -310,8 +302,8 @@ describe('splitArgs', () => {
|
||||
it('should use the maxParallel option when given', () => {
|
||||
const parallel = splitArgsIntoNxArgsAndOverrides(
|
||||
{
|
||||
_: [],
|
||||
$0: '',
|
||||
__overrides_unparsed__: [],
|
||||
parallel: '',
|
||||
maxParallel: 5,
|
||||
},
|
||||
|
||||
@ -1,104 +1,11 @@
|
||||
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 { output } from './output';
|
||||
import { NxJsonConfiguration } from '../config/nx-json';
|
||||
import { execSync } from 'child_process';
|
||||
import { serializeOverridesIntoCommandLine } from './serialize-overrides-into-command-line';
|
||||
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 {
|
||||
prod?: boolean;
|
||||
}
|
||||
@ -128,79 +35,40 @@ export interface NxArgs {
|
||||
type?: string;
|
||||
}
|
||||
|
||||
const ignoreArgs = ['$0', '_'];
|
||||
|
||||
export function splitArgsIntoNxArgsAndOverrides(
|
||||
args: { [k: string]: any },
|
||||
mode: 'run-one' | 'run-many' | 'affected' | 'print-affected',
|
||||
options = { printWarnings: true },
|
||||
nxJson: NxJsonConfiguration
|
||||
): { nxArgs: NxArgs; overrides: yargs.Arguments } {
|
||||
if (!args.__overrides__ && args._) {
|
||||
): { nxArgs: NxArgs; overrides: Arguments } {
|
||||
if (!args.__overrides_unparsed__ && args._) {
|
||||
// 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._;
|
||||
}
|
||||
|
||||
const nxSpecific =
|
||||
mode === 'run-one' ? runOne : mode === 'run-many' ? runMany : runAffected;
|
||||
|
||||
let explicitOverrides;
|
||||
if (args.__overrides__) {
|
||||
explicitOverrides = yargsParser(args.__overrides__ as string[], {
|
||||
const nxArgs: RawNxArgs = args;
|
||||
let overrides = yargsParser(args.__overrides_unparsed__ as string[], {
|
||||
configuration: {
|
||||
'camel-case-expansion': false,
|
||||
'dot-notation': false,
|
||||
'dot-notation': true,
|
||||
},
|
||||
});
|
||||
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 (explicitOverrides) {
|
||||
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
|
||||
);
|
||||
if (!overrides._ || overrides._.length === 0) {
|
||||
delete overrides._;
|
||||
}
|
||||
|
||||
overrides.__overrides_unparsed__ = args.__overrides_unparsed__;
|
||||
delete (nxArgs as any).$0;
|
||||
delete (nxArgs as any).__overrides_unparsed__;
|
||||
|
||||
if (mode === 'run-many') {
|
||||
if (!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)
|
||||
if (!nxArgs.base && process.env.NX_BASE) {
|
||||
nxArgs.base = process.env.NX_BASE;
|
||||
|
||||
@ -183,6 +183,7 @@ export async function parseCommand(
|
||||
type: builderOptionTypes[key],
|
||||
choices: builderOptionsChoices[key],
|
||||
deprecated: builderDeprecatedOptions[key],
|
||||
hidden: builderOptions.hiddenOptions.includes(key),
|
||||
})) || null,
|
||||
};
|
||||
}
|
||||
@ -194,6 +195,7 @@ export function generateOptionsMarkdown(command): string {
|
||||
|
||||
command.options
|
||||
.sort((a, b) => sortAlphabeticallyFunction(a.name, b.name))
|
||||
.filter(({ hidden }) => !hidden)
|
||||
.forEach((option) => {
|
||||
response += `\n### ${
|
||||
option.deprecated ? `~~${option.name}~~` : option.name
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user