Skip to content

Commit

Permalink
feat(nx): support passing args to run-commands builder
Browse files Browse the repository at this point in the history
  • Loading branch information
vsavkin committed May 7, 2019
1 parent aef9170 commit fba08a5
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 2 deletions.
6 changes: 6 additions & 0 deletions docs/api-builders/run-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ Run commands

## Properties

### args

Type: `string`

Extra arguments. You can pass them as follows: ng run project:target --args='--wait=100'. You can them use {args.wait} syntax to interpolate them in angular.json

### parallel

Default: `true`
Expand Down
48 changes: 48 additions & 0 deletions packages/builders/src/run-commands/run-commands.builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,52 @@ describe('Command Runner Builder', () => {
expect(result).toEqual({ success: false });
expect(readFile(f)).toEqual('1');
});

it('should throw when invalid args', async () => {
const root = normalize('/root');
const f = fileSync().name;

try {
await builder
.run({
root,
builder: '@nrwl/run-commands',
projectType: 'application',
options: {
commands: [
{
command: `echo {args.key} >> ${f}`
}
],
args: 'key=value'
}
})
.toPromise();
} catch (e) {
expect(e.message).toEqual('Invalid args: key=value');
}
});

it('should enable parameter substitution', async () => {
const root = normalize('/root');
const f = fileSync().name;
const result = await builder
.run({
root,
builder: '@nrwl/run-commands',
projectType: 'application',
options: {
commands: [
{
command: `echo {args.key} >> ${f}`
}
],
args: '--key=value'
}
})
.toPromise();

expect(result).toEqual({ success: true });
expect(readFile(f)).toEqual('value');
});
});
38 changes: 36 additions & 2 deletions packages/builders/src/run-commands/run-commands.builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ export interface RunCommandsBuilderOptions {
commands: { command: string }[];
parallel?: boolean;
readyWhen?: string;
args?: string;
parsedArgs?: { [k: string]: string };
}

export default class RunCommandsBuilder
implements Builder<RunCommandsBuilderOptions> {
run(
config: BuilderConfiguration<RunCommandsBuilderOptions>
): Observable<BuildEvent> {
config.options.parsedArgs = {
...(config.options as any),
...this.parseArgs(config.options.args)
};
return Observable.create(async observer => {
if (!config || !config.options || !config.options.commands) {
observer.error(
Expand Down Expand Up @@ -62,7 +68,10 @@ export default class RunCommandsBuilder
config: BuilderConfiguration<RunCommandsBuilderOptions>
) {
const procs = config.options.commands.map(c =>
this.createProcess(c.command, config.options.readyWhen).then(result => ({
this.createProcess(
this.transformCommand(c.command, config.options.parsedArgs),
config.options.readyWhen
).then(result => ({
result,
command: c.command
}))
Expand Down Expand Up @@ -106,7 +115,7 @@ export default class RunCommandsBuilder
>(async (m, c) => {
if ((await m) === null) {
const success = await this.createProcess(
c.command,
this.transformCommand(c.command, config.options.parsedArgs),
config.options.readyWhen
);
return !success ? c.command : null;
Expand Down Expand Up @@ -151,4 +160,29 @@ export default class RunCommandsBuilder
});
});
}

private transformCommand(command: string, args: any) {
const regex = /{args\.([^}]+)}/g;
return command.replace(regex, (_, group: string) => args[group]);
}

private parseArgs(args: string) {
if (!args) {
return {};
}
return args
.split(' ')
.map(t => t.trim())
.reduce((m, c) => {
if (!c.startsWith('--')) {
throw new Error(`Invalid args: ${args}`);
}
const [key, value] = c.substring(2).split('=');
if (!key || !value) {
throw new Error(`Invalid args: ${args}`);
}
m[key] = value;
return m;
}, {});
}
}
4 changes: 4 additions & 0 deletions packages/builders/src/run-commands/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
"readyWhen": {
"type": "string",
"description": "String to appear in stdout or stderr that indicates that the task is done. This option can only be used when parallel is set to true. If not specified, the task is done when all the child processes complete."
},
"args": {
"type": "string",
"description": "Extra arguments. You can pass them as follows: ng run project:target --args='--wait=100'. You can them use {args.wait} syntax to interpolate them in angular.json"
}
},
"required": ["commands"]
Expand Down

0 comments on commit fba08a5

Please sign in to comment.