fix(core): task-orchestrator properly handles arguments (#3560)
The task-orchestrator was converting command line flags to "yargs-compatible" string using a custom logic. This commit makes sure that this happens through `yargs-unparser` to avoid issues with more complex options like arrays and objects. ISSUES CLOSED: #3450
This commit is contained in:
parent
08e4ee29fa
commit
2d1da6b4a7
@ -138,6 +138,7 @@
|
|||||||
"express": "4.17.1",
|
"express": "4.17.1",
|
||||||
"file-loader": "4.2.0",
|
"file-loader": "4.2.0",
|
||||||
"find-cache-dir": "3.0.0",
|
"find-cache-dir": "3.0.0",
|
||||||
|
"flat": "^5.0.2",
|
||||||
"fork-ts-checker-webpack-plugin": "^3.1.1",
|
"fork-ts-checker-webpack-plugin": "^3.1.1",
|
||||||
"fs-extra": "7.0.1",
|
"fs-extra": "7.0.1",
|
||||||
"glob": "7.1.4",
|
"glob": "7.1.4",
|
||||||
|
|||||||
@ -68,6 +68,7 @@
|
|||||||
"yargs": "^11.0.0",
|
"yargs": "^11.0.0",
|
||||||
"chalk": "2.4.2",
|
"chalk": "2.4.2",
|
||||||
"@nrwl/cli": "*",
|
"@nrwl/cli": "*",
|
||||||
"axios": "0.19.2"
|
"axios": "0.19.2",
|
||||||
|
"flat": "^5.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Cache, TaskWithCachedResult } from './cache';
|
|||||||
import { cliCommand } from '../core/file-utils';
|
import { cliCommand } from '../core/file-utils';
|
||||||
import { ProjectGraph } from '../core/project-graph';
|
import { ProjectGraph } from '../core/project-graph';
|
||||||
import { AffectedEventType, Task } from './tasks-runner';
|
import { AffectedEventType, Task } from './tasks-runner';
|
||||||
import { getOutputs } from './utils';
|
import { getOutputs, unparse } from './utils';
|
||||||
import { fork } from 'child_process';
|
import { fork } from 'child_process';
|
||||||
import { DefaultTasksRunnerOptions } from './default-tasks-runner';
|
import { DefaultTasksRunnerOptions } from './default-tasks-runner';
|
||||||
import { output } from '../utils/output';
|
import { output } from '../utils/output';
|
||||||
@ -318,13 +318,7 @@ export class TaskOrchestrator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getCommandArgs(task: Task) {
|
private getCommandArgs(task: Task) {
|
||||||
const args = Object.entries(task.overrides || {}).map(([prop, value]) =>
|
const args: string[] = unparse(task.overrides || {});
|
||||||
typeof value === 'boolean'
|
|
||||||
? value
|
|
||||||
? `--${prop}`
|
|
||||||
: `--no-${prop}`
|
|
||||||
: `--${prop}=${value}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const config = task.target.configuration
|
const config = task.target.configuration
|
||||||
? `:${task.target.configuration}`
|
? `:${task.target.configuration}`
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
import { getOutputsForTargetAndConfiguration } from '@nrwl/workspace/src/tasks-runner/utils';
|
import {
|
||||||
|
getOutputsForTargetAndConfiguration,
|
||||||
|
unparse,
|
||||||
|
} from '@nrwl/workspace/src/tasks-runner/utils';
|
||||||
|
|
||||||
describe('utils', () => {
|
describe('utils', () => {
|
||||||
describe('getOutputsForTargetAndConfiguration', () => {
|
describe('getOutputsForTargetAndConfiguration', () => {
|
||||||
@ -181,4 +184,59 @@ describe('utils', () => {
|
|||||||
).toEqual(['dist/root-myapp']);
|
).toEqual(['dist/root-myapp']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('unparse', () => {
|
||||||
|
it('should unparse options whose values are primitives', () => {
|
||||||
|
const options = {
|
||||||
|
boolean1: false,
|
||||||
|
boolean2: true,
|
||||||
|
number: 4,
|
||||||
|
string: 'foo',
|
||||||
|
'empty-string': '',
|
||||||
|
ignore: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(unparse(options)).toEqual([
|
||||||
|
'--no-boolean1',
|
||||||
|
'--boolean2',
|
||||||
|
'--number=4',
|
||||||
|
'--string=foo',
|
||||||
|
'--empty-string=',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should unparse options whose values are arrays', () => {
|
||||||
|
const options = {
|
||||||
|
array1: [1, 2],
|
||||||
|
array2: [3, 4],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(unparse(options)).toEqual([
|
||||||
|
'--array1=1',
|
||||||
|
'--array1=2',
|
||||||
|
'--array2=3',
|
||||||
|
'--array2=4',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should unparse options whose values are objects', () => {
|
||||||
|
const options = {
|
||||||
|
foo: {
|
||||||
|
x: 'x',
|
||||||
|
y: 'y',
|
||||||
|
w: [1, 2],
|
||||||
|
z: [3, 4],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(unparse(options)).toEqual([
|
||||||
|
'--foo.x=x',
|
||||||
|
'--foo.y=y',
|
||||||
|
'--foo.w=1',
|
||||||
|
'--foo.w=2',
|
||||||
|
'--foo.z=3',
|
||||||
|
'--foo.z=4',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Task } from './tasks-runner';
|
import { Task } from './tasks-runner';
|
||||||
import { ProjectGraphNode } from '../core/project-graph';
|
import { ProjectGraphNode } from '../core/project-graph';
|
||||||
|
import * as flatten from 'flat';
|
||||||
|
|
||||||
const commonCommands = ['build', 'test', 'lint', 'e2e', 'deploy'];
|
const commonCommands = ['build', 'test', 'lint', 'e2e', 'deploy'];
|
||||||
|
|
||||||
@ -75,3 +76,34 @@ export function getOutputsForTargetAndConfiguration(
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function unparse(options: Object): string[] {
|
||||||
|
const unparsed = [];
|
||||||
|
for (const key of Object.keys(options)) {
|
||||||
|
const value = options[key];
|
||||||
|
unparseOption(key, value, unparsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return unparsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unparseOption(key: string, value: any, unparsed: string[]) {
|
||||||
|
if (value === true) {
|
||||||
|
unparsed.push(`--${key}`);
|
||||||
|
} else if (value === false) {
|
||||||
|
unparsed.push(`--no-${key}`);
|
||||||
|
} else if (Array.isArray(value)) {
|
||||||
|
value.forEach((item) => unparseOption(key, item, unparsed));
|
||||||
|
} else if (Object.prototype.toString.call(value) === '[object Object]') {
|
||||||
|
const flattened = flatten(value, { safe: true });
|
||||||
|
for (const flattenedKey in flattened) {
|
||||||
|
unparseOption(
|
||||||
|
`${key}.${flattenedKey}`,
|
||||||
|
flattened[flattenedKey],
|
||||||
|
unparsed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (typeof value === 'string' || value != null) {
|
||||||
|
unparsed.push(`--${key}=${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -10094,6 +10094,11 @@ flat-cache@^2.0.1:
|
|||||||
rimraf "2.6.3"
|
rimraf "2.6.3"
|
||||||
write "1.0.3"
|
write "1.0.3"
|
||||||
|
|
||||||
|
flat@^5.0.2:
|
||||||
|
version "5.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
|
||||||
|
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
|
||||||
|
|
||||||
flatted@^2.0.0:
|
flatted@^2.0.0:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
|
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user