feat(core): add shorthand for nx run-commands (#13139)
This commit is contained in:
parent
76c237bd2c
commit
61c3b0ef31
@ -302,7 +302,7 @@
|
||||
},
|
||||
"additionalProperties": true,
|
||||
"required": [],
|
||||
"examplesFile": "`project.json`:\n\n```json\n{\n // ...\n \"targets\": {\n //...\n \"ls-project-root\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"command\": \"ls apps/frontend/src\"\n }\n }\n }\n}\n```\n\n```bash\nnx run frontend:ls-project-root\n```\n\n## Examples\n\n{% tabs %}\n{% tab label=\"Chaining commands\" %}\n\nThe `commands` option accepts as many commands as you want. By default, they all run in parallel.\nYou can run them sequentially by setting `parallel: false`:\n\n```json\n\"create-script\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"commands\": [\n \"mkdir -p apps/frontend/scripts\",\n \"touch apps/frontend/scripts/my-script.sh\",\n \"chmod +x apps/frontend/scripts/my-script.sh\"\n ],\n \"parallel\": false\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Setting the cwd\" %}\n\nBy setting the `cwd` option, each command will run in the `apps/frontend` folder.\n\n```json\n\"create-script\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"cwd\": \"apps/frontend\",\n \"commands\": [\n \"mkdir -p scripts\",\n \"touch scripts/my-script.sh\",\n \"chmod +x scripts/my-script.sh\"\n ],\n \"parallel\": false\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Interpolating Args\" %}\n\nYou can use custom arguments in your scripts with `{args.[someFlag]}`:\n\n```json\n\"create-script\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"cwd\": \"apps/frontend\",\n \"commands\": [\n \"mkdir -p scripts\",\n \"touch scripts/{args.name}.sh\",\n \"chmod +x scripts/{args.name}.sh\"\n ],\n \"parallel\": false\n }\n}\n```\n\nWe run the above with:\n\n```bash\nnx run frontend:create-script --args=\"--name=example\"\n```\n\nor simply with:\n\n```bash\nnx run frontend:create-script --name=example\n```\n\n{% /tab %}\n{% tab label=\"Arguments forwarding\" %}\nWhen interpolation is not present in the command, all arguments are forwarded to the command by default.\n\nThis is useful when you need to pass raw argument strings to your command.\n\nFor example, when you run:\n\n```bash\nnx run frontend:webpack --args=\"--config=example.config.js\"\n```\n\n```json\n\"webpack\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"command\": \"webpack\"\n }\n}\n```\n\nThe above command will execute: `webpack --config=example.config.js`\n\nThis functionality can be disabled by using `commands` and expanding each `command` into an object\nthat sets the `forwardAllArgs` option to `false` as shown below:\n\n```json\n\"webpack\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"commands\": [\n {\n \"command\": \"webpack\",\n \"forwardAllArgs\": false\n }\n ]\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Custom done conditions\" %}\n\nNormally, `run-commands` considers the commands done when all of them have finished running. If you don't need to wait until they're all done, you can set a special string that considers the commands finished the moment the string appears in `stdout` or `stderr`:\n\n```json\n\"finish-when-ready\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"commands\": [\n \"sleep 5 && echo 'FINISHED'\",\n \"echo 'READY'\"\n ],\n \"readyWhen\": \"READY\",\n \"parallel\": true\n }\n}\n```\n\n```bash\nnx run frontend:finish-when-ready\n```\n\nThe above commands will finish immediately, instead of waiting for 5 seconds.\n{% /tab %}\n{% tab label=\"Nx Affected\" %}\n\nThe true power of `run-commands` comes from the fact that it runs through `nx`, which knows about your project graph. So you can run **custom commands** only for the projects that have been affected by a change.\n\nWe can create some configurations to generate docs, and if run using `nx affected`, it will only generate documentation for the projects that have been changed:\n\n```bash\nnx affected --target=generate-docs\n```\n\n```json\n//...\n\"frontend\": {\n \"targets\": {\n //...\n \"generate-docs\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"command\": \"npx compodoc -p apps/frontend/tsconfig.app.json\"\n }\n }\n }\n},\n\"api\": {\n \"targets\": {\n //...\n \"generate-docs\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"command\": \"npx compodoc -p apps/api/tsconfig.app.json\"\n }\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n\n---\n"
|
||||
"examplesFile": "`project.json`:\n\n```json\n{\n // ...\n \"targets\": {\n //...\n \"ls-project-root\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"command\": \"ls apps/frontend/src\"\n }\n }\n }\n}\n```\n\n```bash\nnx run frontend:ls-project-root\n```\n\n## Examples\n\n{% tabs %}\n{% tab label=\"Chaining commands\" %}\n\nThe `commands` option accepts as many commands as you want. By default, they all run in parallel.\nYou can run them sequentially by setting `parallel: false`:\n\n```json\n\"create-script\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"commands\": [\n \"mkdir -p apps/frontend/scripts\",\n \"touch apps/frontend/scripts/my-script.sh\",\n \"chmod +x apps/frontend/scripts/my-script.sh\"\n ],\n \"parallel\": false\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Setting the cwd\" %}\n\nBy setting the `cwd` option, each command will run in the `apps/frontend` folder.\n\n```json\n\"create-script\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"cwd\": \"apps/frontend\",\n \"commands\": [\n \"mkdir -p scripts\",\n \"touch scripts/my-script.sh\",\n \"chmod +x scripts/my-script.sh\"\n ],\n \"parallel\": false\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Interpolating Args\" %}\n\nYou can use custom arguments in your scripts with `{args.[someFlag]}`:\n\n```json\n\"create-script\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"cwd\": \"apps/frontend\",\n \"commands\": [\n \"mkdir -p scripts\",\n \"touch scripts/{args.name}.sh\",\n \"chmod +x scripts/{args.name}.sh\"\n ],\n \"parallel\": false\n }\n}\n```\n\nWe run the above with:\n\n```bash\nnx run frontend:create-script --args=\"--name=example\"\n```\n\nor simply with:\n\n```bash\nnx run frontend:create-script --name=example\n```\n\n{% /tab %}\n{% tab label=\"Arguments forwarding\" %}\nWhen interpolation is not present in the command, all arguments are forwarded to the command by default.\n\nThis is useful when you need to pass raw argument strings to your command.\n\nFor example, when you run:\n\n```bash\nnx run frontend:webpack --args=\"--config=example.config.js\"\n```\n\n```json\n\"webpack\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"command\": \"webpack\"\n }\n}\n```\n\nThe above command will execute: `webpack --config=example.config.js`\n\nThis functionality can be disabled by using `commands` and expanding each `command` into an object\nthat sets the `forwardAllArgs` option to `false` as shown below:\n\n```json\n\"webpack\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"commands\": [\n {\n \"command\": \"webpack\",\n \"forwardAllArgs\": false\n }\n ]\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Shorthand\" %}\nWhen you only need to run a single command, you can use a shorthand for nx:run-commands:\n\n```json\n\"webpack\": {\n \"command\": \"webpack\"\n}\n```\n\n{% /tab %}\n{% tab label=\"Custom done conditions\" %}\n\nNormally, `run-commands` considers the commands done when all of them have finished running. If you don't need to wait until they're all done, you can set a special string that considers the commands finished the moment the string appears in `stdout` or `stderr`:\n\n```json\n\"finish-when-ready\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"commands\": [\n \"sleep 5 && echo 'FINISHED'\",\n \"echo 'READY'\"\n ],\n \"readyWhen\": \"READY\",\n \"parallel\": true\n }\n}\n```\n\n```bash\nnx run frontend:finish-when-ready\n```\n\nThe above commands will finish immediately, instead of waiting for 5 seconds.\n{% /tab %}\n{% tab label=\"Nx Affected\" %}\n\nThe true power of `run-commands` comes from the fact that it runs through `nx`, which knows about your project graph. So you can run **custom commands** only for the projects that have been affected by a change.\n\nWe can create some configurations to generate docs, and if run using `nx affected`, it will only generate documentation for the projects that have been changed:\n\n```bash\nnx affected --target=generate-docs\n```\n\n```json\n//...\n\"frontend\": {\n \"targets\": {\n //...\n \"generate-docs\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"command\": \"npx compodoc -p apps/frontend/tsconfig.app.json\"\n }\n }\n }\n},\n\"api\": {\n \"targets\": {\n //...\n \"generate-docs\": {\n \"executor\": \"nx:run-commands\",\n \"options\": {\n \"command\": \"npx compodoc -p apps/api/tsconfig.app.json\"\n }\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n\n---\n"
|
||||
},
|
||||
"description": "Run any custom commands with Nx.",
|
||||
"aliases": [],
|
||||
|
||||
@ -83,3 +83,23 @@ Or you can overwrite individual executor options like this:
|
||||
nx [command] [project] --[optionNameInCamelCase]=[value]
|
||||
nx build cart --outputPath=some/other/path
|
||||
```
|
||||
|
||||
## Running a single command
|
||||
|
||||
If defining a new target that needs to run a single shell command, there is a shorthand for the `nx:run-commands` executor that can be used.
|
||||
|
||||
```jsonc {% fileName="project.json" %}
|
||||
{
|
||||
"root": "apps/cart",
|
||||
"sourceRoot": "apps/cart/src",
|
||||
"projectType": "application",
|
||||
"generators": {},
|
||||
"targets": {
|
||||
"echo": {
|
||||
"command": "echo 'hello world'"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For more info, see the [run-commands documentation](/packages/nx/executors/run-commands)
|
||||
|
||||
@ -20,10 +20,7 @@ describe('Extra Nx Misc Tests', () => {
|
||||
runCLI(`generate @nrwl/web:app ${myapp}`);
|
||||
updateProjectConfig(myapp, (c) => {
|
||||
c.targets['inner'] = {
|
||||
executor: 'nx:run-commands',
|
||||
options: {
|
||||
command: 'echo inner',
|
||||
},
|
||||
command: 'echo inner',
|
||||
};
|
||||
c.targets['echo'] = {
|
||||
executor: 'nx:run-commands',
|
||||
@ -140,9 +137,8 @@ describe('Extra Nx Misc Tests', () => {
|
||||
it('should pass options', async () => {
|
||||
updateProjectConfig(mylib, (config) => {
|
||||
config.targets.echo = {
|
||||
executor: 'nx:run-commands',
|
||||
command: 'echo --var1={args.var1}',
|
||||
options: {
|
||||
command: 'echo --var1={args.var1}',
|
||||
var1: 'a',
|
||||
},
|
||||
};
|
||||
|
||||
@ -33,10 +33,7 @@ describe('Nx Running Tests', () => {
|
||||
runCLI(`generate @nrwl/workspace:lib ${proj}`);
|
||||
updateProjectConfig(proj, (c) => {
|
||||
c.targets['echo'] = {
|
||||
executor: 'nx:run-commands',
|
||||
options: {
|
||||
command: 'echo ECHO:',
|
||||
},
|
||||
command: 'echo ECHO:',
|
||||
};
|
||||
return c;
|
||||
});
|
||||
@ -129,10 +126,7 @@ describe('Nx Running Tests', () => {
|
||||
runCLI(`generate @nrwl/web:app ${myapp2}`);
|
||||
updateProjectConfig(myapp1, (c) => {
|
||||
c.targets['error'] = {
|
||||
executor: 'nx:run-commands',
|
||||
options: {
|
||||
command: 'echo boom1 && exit 1',
|
||||
},
|
||||
command: 'echo boom1 && exit 1',
|
||||
};
|
||||
return c;
|
||||
});
|
||||
@ -325,16 +319,10 @@ describe('Nx Running Tests', () => {
|
||||
const nxJson = readJson('nx.json');
|
||||
updateProjectConfig(myapp, (config) => {
|
||||
config.targets.prep = {
|
||||
executor: 'nx:run-commands',
|
||||
options: {
|
||||
command: 'echo PREP > one.txt',
|
||||
},
|
||||
command: 'echo PREP > one.txt',
|
||||
};
|
||||
config.targets.outside = {
|
||||
executor: 'nx:run-commands',
|
||||
options: {
|
||||
command: 'echo OUTSIDE',
|
||||
},
|
||||
command: 'echo OUTSIDE',
|
||||
};
|
||||
return config;
|
||||
});
|
||||
|
||||
@ -133,6 +133,16 @@ that sets the `forwardAllArgs` option to `false` as shown below:
|
||||
}
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% tab label="Shorthand" %}
|
||||
When you only need to run a single command, you can use a shorthand for nx:run-commands:
|
||||
|
||||
```json
|
||||
"webpack": {
|
||||
"command": "webpack"
|
||||
}
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{% tab label="Custom done conditions" %}
|
||||
|
||||
|
||||
@ -71,8 +71,22 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "A shorthand for using the nx:run-commands executor"
|
||||
}
|
||||
}
|
||||
},
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["executor"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["command"]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"tags": {
|
||||
|
||||
@ -85,8 +85,22 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "A shorthand for using the nx:run-commands executor"
|
||||
}
|
||||
}
|
||||
},
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["executor"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["command"]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"tags": {
|
||||
|
||||
@ -137,7 +137,12 @@ export interface TargetConfiguration<T = any> {
|
||||
*
|
||||
* Example: '@nrwl/web:rollup'
|
||||
*/
|
||||
executor: string;
|
||||
executor?: string;
|
||||
|
||||
/**
|
||||
* Used as a shorthand for nx:run-commands, a command to run.
|
||||
*/
|
||||
command?: string;
|
||||
|
||||
/**
|
||||
* List of the target's outputs. The outputs will be cached by the Nx computation
|
||||
|
||||
@ -12,6 +12,7 @@ import { PackageJson } from 'nx/src/utils/package-json';
|
||||
import { readJsonFile } from 'nx/src/utils/fileutils';
|
||||
import { NxJsonConfiguration } from 'nx/src/config/nx-json';
|
||||
import { TargetConfiguration } from 'nx/src/config/workspace-json-project-json';
|
||||
import { NX_PREFIX } from 'nx/src/utils/logger';
|
||||
|
||||
export function buildWorkspaceProjectNodes(
|
||||
ctx: ProjectGraphProcessorContext,
|
||||
@ -42,10 +43,7 @@ export function buildWorkspaceProjectNodes(
|
||||
}
|
||||
}
|
||||
|
||||
p.targets = mergeNxDefaultTargetsWithNxTargets(
|
||||
p.targets,
|
||||
nxJson.targetDefaults
|
||||
);
|
||||
p.targets = normalizeProjectTargets(p.targets, nxJson.targetDefaults, key);
|
||||
|
||||
p.targets = mergePluginTargetsWithNxTargets(
|
||||
p.root,
|
||||
@ -91,9 +89,13 @@ export function buildWorkspaceProjectNodes(
|
||||
});
|
||||
}
|
||||
|
||||
function mergeNxDefaultTargetsWithNxTargets(
|
||||
/**
|
||||
* Apply target defaults and normalization
|
||||
*/
|
||||
function normalizeProjectTargets(
|
||||
targets: Record<string, TargetConfiguration>,
|
||||
defaultTargets: NxJsonConfiguration['targetDefaults']
|
||||
defaultTargets: NxJsonConfiguration['targetDefaults'],
|
||||
projectName: string
|
||||
) {
|
||||
for (const targetName in defaultTargets) {
|
||||
const target = targets?.[targetName];
|
||||
@ -110,5 +112,24 @@ function mergeNxDefaultTargetsWithNxTargets(
|
||||
target.outputs = defaultTargets[targetName].outputs;
|
||||
}
|
||||
}
|
||||
for (const target in targets) {
|
||||
const config = targets[target];
|
||||
if (config.command) {
|
||||
if (config.executor) {
|
||||
throw new Error(
|
||||
`${NX_PREFIX} ${projectName}: ${target} should not have executor and command both configured.`
|
||||
);
|
||||
} else {
|
||||
targets[target] = {
|
||||
...targets[target],
|
||||
executor: 'nx:run-commands',
|
||||
options: {
|
||||
...config.options,
|
||||
command: config.command,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user