ws-affected
is a command-line tool that helps you identify and/or run scripts only on npm workspaces affected by the changes on a git branch (default: current branch/commit). This script does not have any dependencies but node.js and git.
-
Local development: Run linting, type checks, tests etc only on changed workspaces
Run scripts on workspaces and their dependents affected by changes on a branch. This is useful on local development to run tests and lint only on workspaces that have changed.
npx ws-affected --run lint --run test
β lint:service1 (748ms) β lint:service3 (1289ms) β test:shared-lib (2816ms) β±οΈ Took 2.89s (3 tasks)
-
CI/CD change detection: "Tell me what workspaces needs to be deployed"
List workspaces affected by changes on a branch. This is useful for CI/CD scripts to determine affected workspaces to deploy.
npx ws-affected --list # or npx ws-affected --list --base master --head HEAD # or npx ws-affected --list --base origin/master --head origin/HEAD
service1 service3 shared-lib
You can exclude a workspace (like shared-*) with pattern matching and then e.g. you can then start deployment of the affected services:
AFFECTED_SERVICES=$(npx ws-affected --list --base=origin/master | awk -F', ' '{ for( i=1; i<=NF; i++ ) print $i }' | grep -vE '^shared-' | sort)
service1 service3
-
CI/CD packaging: "Tell me how to deploy a single workspace"
List a single workspace's prod dependencies. This is useful for CI/CD scripts for packaging only the prod dependencies of a single workspace / service.
npx ws-affected --workspace service1 --list-dependencies --dep-types prod
service1 shared-lib
You can use it to delete the rest of the workspaces temporarily to not just speed up the build process but in serverless environments like AWS Lambda this will reduce the size of the deployment package.
You can run ws-affected
directly using npx
:
npx ws-affected [options]
Usage: npx ws-affected [options]
Options:
-r, --run <script> Run the specified commands on affected workspaces (repeatable flag)
-l, --list List recursively the dependents (inclusive) of affected workspaces or workspaces selected by --workspace flag
-b, --base <branch> The base branch to compare against (default: master)
-h, --head <branch> The head branch to compare for (default: HEAD)
-c, --concurrency <n> The number of concurrent tasks to run (default: 0 = number of CPUs)
-u, --print-success Print output for successful scripts as well
-a, --all-workspaces --run scripts on all workspaces
-w, --workspace --run scripts or --list dependencies of specific workspaces (repeatable flag)
--list-dependencies List recursively the dependencies (inclusive) of workspaces selected by --workspace flag
--dep-types What dependencies to look at. Options: 'all' (default) or 'prod'. 'prod' means "dependencies" and "peerDependencies" in package.json
-h, --help Show the help text
Examples:
ws-affected --list
ws-affected --run lint --run test --concurrency 4
ws-affected --base main --run build
ws-affected --run lint --run test --print-success
Workspace vs package
They are synonyms as far as this tool is concerned.
Dependents vs Dependencies
Dependents are the packages the depend on a given package. Dependencies are packages that a given package depends on.
Let's say A depends on B, which depends on C, which depends on D, which depends on E. The tree looks like the following:
A
- B
- C
- D
- E
Focus on C for a moment (you can use --workspace C flag), and the following are definitions for some terms:
- "Dependents" of C are A and B
- "Dependents inclusive" of C are A, B and C
- "Dependencies" of C are D and E.
- "Dependencies inclusive" of C are C, D and E.
"Affected workspaces" means the workspaces that was directly edited by changes on `--head` branch and the
dependents of those workspaces.
A note about --workspace flag
When --list or --list-dependencies is used, dependents/dependencies of \`--workspace\`s are included.
When --run is used, only those \`--workspace\`s are used without including dependents/dependencies.
npx ws-affected --list
# or npx ws-affected --list --base master --head HEAD
# or npx ws-affected --list --base origin/master --head origin/HEAD
service1
service3
shared-lib
npx ws-affected --run lint --run test
β lint:service1 (748ms)
β lint:service3 (1289ms)
β test:shared-lib (2816ms)
β±οΈ Took 2.89s (3 tasks)
npx ws-affected --run lint --print-success
β lint:service1 $ npm run -w service1 --if-present lint
β > service1@0.1.0 lint
β > ./scripts/lint.sh
ββ Success (748ms)
β lint:service3 $ npm run -w service3 --if-present lint
β > service3@0.1.0 lint
β > ./scripts/lint.sh
ββ Success (1289ms)
β±οΈ Took 2.03s (2 tasks)
npx ws-affected --workspace service1 --list-dependencies --dep-types prod
service1
shared-lib
How it works:
- ws-affected reads the root package.json file to determine the workspaces directory.
- It creates a map of workspace dependencies by reading the package.json files of each workspace.
- It finds the point where the current branch diverged from the base branch (default: master).
- It runs git diff-tree to identify the files that have changed between the divergence point and the current branch.
- It determines the workspaces that have changed based on the changed files and adds them to a "affected workspaces" list.
- It recursively adds all the workspaces that depend on the changed workspaces to the "affected workspaces" list.
- If the --list flag is used, it prints the affected workspaces.
- If the --run flag is used, it runs the specified scripts on the affected workspaces, respecting the concurrency limit.
This project is licensed under the MIT License. See the LICENSE file for more information.