run-z
is a command line utility able to run multiple npm-scripts at once.
- Each NPM script considered a task to execute.
- Each task may have prerequisites. I.e. other tasks to execute before it.
- Each task executes at most once, even though it is a prerequisite of many tasks.
- Additional parameters can be passed to any task.
- Tasks can be executed in parallel or sequentially.
- Tasks may belong to different packages. This is especially helpful with Yarn Workspaces or Lerna.
- Tasks can be batched - the same-named tasks can be executed in each of the selected packages.
- The dependencies between packages respected when batching - the tasks executed in dependencies-first order.
- Only one instance of
run-z
process started despite the number of tasks to execute.
See also:
-
Add
run-z
as development dependency of your package:-
Using npm:
npm install run-z --save-dev
-
Using pnpm:
pnpm add run-z -D
-
Using Yarn:
yarn add run-z --dev
-
-
Add script(s) to
package.json
executingrun-z
:{ "scripts": { "all": "run-z build lint,test", "build": "run-z --then tsc -p .", "clean": "run-z --then shx rm -rf ./dist", "lint": "run-z --then eslint .", "test": "run-z --then jest", "z": "run-z" } }
-
Execute tasks:
-
Using npm:
# Run single task npm run all # Run multiple tasks npm run clean -- build # Use a no-op `z` task for convenience npm run z -- clean build
-
Using pnpm:
# Run single task pnpm all # Run multiple tasks pnpm clean build
-
Using Yarn:
# Run single task yarn all # Run multiple tasks yarn clean build
-
Or just use npx
for your existing project. No need to install run-z
or modify package.json
:
npx run-z clean build
Each record in scripts section of package.json is a script executable by a package manager (NPM or Yarn). If
executed script is a run-z
command, the latter treats every script as task. Such a task can be used as a prerequisite
of another one. run-z
executes prerequisites prior to the task itself.
To specify a task prerequisite just add its name to run-z
command line:
run-z prerequisite1 prerequisite2 --then node ./my-script.js --arg
This task would execute prerequsite1
, then prerequisite2
, and finally the node ./my-script.js --arg
command.
The following types of tasks supported:
-
Command.
--then
option treats the rest of the command line as command to execute after prerequisites. -
NPM script.
A
package.json
script not containing arun-z
command. It still can be used as prerequisite of another task. -
Group.
A
run-z
command containing zero or more prerequisites and not containing a command to execute. -
Unknown.
A task prerequisite not matching any of the
package.json
scripts. Attempting to execute such a task would cause an error. However, it is possible to skip such task execution without causing an error.
To pass additional command line arguments to the task a special syntax can be used:
run-z test/--ci/--runInBand # Pass `--ci` and `--runInBand` command line argument
# to command or NPM script executed by `test` task.
run-z test //--ci --runInBand// # Pass multiple command line options at once.
Single arguments can be passed by prefixing them with /
sign. Any number of spaces may precede the /
sign, but
should not follow it.
Multiple arguments can be passed by enclosing them with two or more /
signs. The number of opening and closing signs
should be the same. Any number of spaces may precede or follow opening and closing signs.
Task attributes are name/value pairs accepted by tasks. They can be passed to the tasks similarly to command line arguments:
run-z test/attribute=value # Pass `attribute` with `value` to `test` prerequisite.
run-z build test attribute=value # Pass `attribute` with `value` to the task itself and all of its prerequisites.
run-z test/=if-present # The shorthand for `if-present=on`.
Some attributes are flags. I.e. their values treated as booleans with 0
, false
, and off
(case-insensitive) meaning
false
, and everything else meaning true
. A shorthand syntax (=flag
) can be used to set it to on
meaning true
.
If attribute value set multiple times, the last value takes precedence. If set both by a task and its prerequisite, the value set prerequisite has lower precedence. The attribute value passed from command line always has the highest precedence.
The following attributes supported:
-
env:NAME
- Sets environment variableNAME
.Multiple values for the same environment variable are joined:
env:NODE_OPTIONS=--experimental-vm-modules env:NODE_OPTIONS=--no-warnings
setsNODE_OPTIONS='--experimental-vm-modules --no-warnings'
To override the value a
:=
sign can be used instead of=
:
env:NODE_OPTIONS=--no-warnings env:NODE_OPTIONS:=--no-deprecation
setsNODE_OPTIONS='--no-deprecation'
-
if-present
- A flag indicating that the task should be executed only if corresponding script defined.This can be useful for batched tasks.
-
skip
- When this flag set the task won't be executed.
Other attributes aren't currently used, but still can be set.
See also:
Tasks executed sequentially unless parallel execution allowed for them. To allow two or more tasks to be executed in parallel to each other, separate their names with commas:
run-z clean build lint,test # Arbitrary number of spaces allowed around comma.
This would execute lint
and test
tasks in parallel to each other, but only when build
one completed. While the
build
task would be executed only when clean
one completed.
It is also possible to execute a command in parallel to its prerequisite. For that an --and
option could be used
instead of --then
:
run-z copy-assets --and tsc -p . # Copies assets and compiles TypeScript simultaneously.
By default, the maximum number of tasks that can be executed simultaneously is limited to the number of CPUs. The
--max-jobs
(-j
) option can be used to change the limit:
run-z build,lint,test -j2 # Only two jobs can run simultaneously. The third one would pend.
run-z build,lint,test -max-jobs 1 # Effectively disables parallel execution.
run-z build,lint,test -j0 # Remove the limit completely.
It is possible to execute tasks from other packages:
run-z ../package1 build test . build test
this executes build
and test
tasks in the package located in ../package1
directory, then runs build
and test
tasks in current one.
run-z
command line options .
, ..
, and the ones started with ./
or ../
are relative URLs to package
directories. The following tasks searched for and executed in target packages.
The package selector may select multiple packages. The task following it would be executed in each of the selected packages in a batch:
run-z ./packages// build # Executes `build` in each package
# inside `./packages` directory.
run-z ./packages/// build # Executes `build` in `./packages` directory
# and in each package deeply nested within it.
The //
syntax selects all directly nested directories. The ///
syntax selects the directory and all directories
deeply nested within it. The hidden directories and directories without package.json
file ignored.
It is also possible to specify multiple package selectors. All selected packages would be united:
run-z ./3rd-party// ./packages// build # Executes `build` in each package
# inside `./3rd-party` and `./packages` directories.
The tasks within a batch executed in a dependency-first order. I.e. if one of the target packages depends on another, the task would be executed in dependency first, and in dependent package after that.
The tasks in independent packages executed in parallel to each other.
It is also possible to forcibly execute all batched tasks in parallel to each other with --batch-parallel
(--bap
)
option:
run-z --batch-parallel ./packages// lint # Executes `lint` in each package
# inside `./packages` directory
# in parallel to each other.
See also:
The group tasks accept parameters. The first parameter considered a name of the task in the same package to execute. The rest are parameters to this task. This can be used to batch tasks without specifying the package directories every time.
So, with the following package.json
:
{
"scripts": {
"each": "run-z ./3rd-party// ./packages//"
}
}
it is possible to batch tasks across packages in ./3rd-party
and ./packages
directories:
-
Using npm:
npm run each -- /build each /test # Batch `build`, then `test` across all packages.
-
Using pnpm:
pnpm each /build each /test # Batch `build`, then `test` across all packages.
-
Using Yarn:
yarn each /build each /test # Batch `build`, then `test` across all packages.
When working with Yarn Workspaces or Lerna it is often necessary to run the task across multiple packages. It is quite doable via specifying package selectors. Still, there is a better solution utilizing named batches.
Let's say we have a root package (worktree root) and several packages within a packages/
directory.
Let's place the following scripts to the root package.json
:
{
"scripts": {
"all/*": "run-z ./packages//",
"z": "run-z"
}
}
The all/*
script is a named batch specifier. The z
task is a handy NPM script, that just runs run-z
.
With these present it becomes possible to batch tasks by executing run-z
in either root package directory, or in any
of the nested packages:
-
Using npm:
npm run z -- build --all # Batch `build` task across all packages.
-
Using pnpm:
pnpm z build --all # Batch `build` task across all packages.
-
Using Yarn:
yarn z build --all # Batch `build` task across all packages.
With --all
option specified the run-z
searches for topmost package containing named batch(-es) specifier, and
batches the task across selected packages.
The z
task used for convenience here. It is expected to present in all packages. Any task can be executed instead. For
example, when running inside one of the nested packages, the following command can do the same as above:
-
Using npm:
npm run build -- --all
-
Using pnpm:
pnpm build --all
-
Using Yarn:
yarn build --all
The named batch can have a syntax like all/test
. When present, such named batch will be used instead of the all/*
one when batching a test
task. This can be useful, e.g. when it is necessary to pass additional parameters to specific
tasks:
{
"scripts": {
"all/*": "run-z ./packages//",
"all/test": "run-z ./packages// +test/--runInBand",
"z": "run-z"
}
}
-
Using npm:
npm run z -- build --all # Batch `build` in generic way. npm run z -- test --all # Batch `test` with `--runInBand` option.
-
Using pnpm:
pnpm z build --all # Batch `build` in generic way. pnpm z test --all # Batch `test` with `--runInBand` option.
-
Using Yarn:
yarn z build --all # Batch `build` in generic way. yarn z test --all # Batch `test` with `--runInBand` option.
See also:
With named batches it is possible to batch tasks across part of package dependency graph.
-
Using npm:
# Batch the `build` task across package dependencies and the package itself. npm run build -- --with-deps # Batch the `build` task across package dependencies. # Do not run for the package itself. npm run build -- --only-deps # Batch the `build` task for the package and all the packages depending on it. npm run build -- --with-dependants # Batch the `build` task across packages depending on current one. # Do not run for the package itself. npm run build -- --only-dependants
-
Using pnpm:
# Batch the `build` task across package dependencies and the package itself. pnpm build --with-deps # Batch the `build` task across package dependencies. # Do not run for the package itself. pnpm build --only-deps # Batch the `build` task for the package and all the packages depending on it. pnpm build --with-dependants # Batch the `build` task across packages depending on current one. # Do not run for the package itself. pnpm build --only-dependants
-
Using Yarn:
# Batch the `build` task across package dependencies and the package itself. yarn build --with-deps # Batch the `build` task across package dependencies. # Do not run for the package itself. yarn build --only-deps # Batch the `build` task for the package and all the packages depending on it. yarn build --with-dependants # Batch the `build` task across packages depending on current one. # Do not run for the package itself. yarn build --only-dependants