Assignment Rules
Assignment rules allow you to control which tasks can run on which agents.
- Save on agent costs by provisioning different sizes of agents to suit the individual needs of your tasks.
- Ensure resource intensive targets like
e2e-ci
andbuild
have what they need by using larger agents and with a specified parallelism. - Lighter tasks like
lint
andtest
can run on smaller agents.
Assignment rules are defined in yaml
files within your workspace's .nx/workflows
directory. You can use assignment rules with self-hosted agents or with dynamic Nx agents. Note that additional configuration is required when using self-hosted agents.
How to Define an Assignment Rule
Each assignment rule has at least one of the following properties that it matches against tasks: projects
, targets
, and/or configurations
. You can provide a list of globs to match against any of these properties in your workspace. It also has a list of possible agent types that tasks with the matching properties can run on. Rules are defined in yaml like the following:
1assignment-rules:
2 - projects:
3 - app1
4 targets:
5 - e2e-ci*
6 run-on:
7 - agent: linux-medium
8 parallelism: 5
9
10 - targets:
11 - lint,build
12 run-on:
13 - agent: linux-large
14 parallelism: 10
15
The first rule will match any task that has a project named app1
, any targets that begin with e2e-ci
, and a configuration named production
. Any tasks that match this rule will only be allowed to run on agents with linux-medium-js
launch templates. Agents assigned these tasks will also be able to execute up to five tasks in parallel.
The second rule above will match any task that has a lint
or build
target. These tasks only run on linux-large-js
agents and up to ten tasks can be executed in parallel by agents of that type.
You can mix and match any of the properties in an assignment rule provided that you follow these constraints:
- At least one of the following properties is defined:
projects
,targets
,configurations
. - There is at least one agent type specified in the
run-on
field. If no parallelism is specified, the parallelism of the executed command will be used instead. If that is not specified, then the parallelism will default to1
- For assignment rules with Nx Agents, every changeset in your
distribute-on
field must include at least one agent that matches each agent type specified in therun-on
field across all assignment rules. For example, if your rules distribute tasks onlinux-small-js
,linux-medium-js
, andlinux-large-js
, then at least one agent of each type must be available. Otherwise, tasks associated with those rules cannot be executed.
You must define your own agent types and attach them to your self-hosted agents using the NX_AGENT_LAUNCH_TEMPLATE
environment variable. Ensure that for each run-on
field in your assignment rules, you have corresponding agents in your agent pool that have the same agent type. See below for an example of how to define your own agent types when using self-hosted agents.
Assignment Rule Property Reference
projects
A list of string globs that matches against projects in your workspace.
targets
A list of string globs that matches against targets in your workspace.
configurations
A list of string globs that matches against configurations in your workspace.
run-on
Specification of which agent and how to run your tasks:
- agent: the type of agent to run on (i.e.
linux-medium-js
,linux-large-js
) - parallelism: the number of parallel executions allowed for agents of a given type
Glob Reference
You can use globs for better control over how to define your assignment rules.
*
matches zero or more characters
- ✅
lint*
matcheslint-js
,linting-test
- ✅
*test*
matchesbusiness-test-2
,test-12
,10-test
- ❌
lint*
does not matcheslint
,lin-test
,lin
?
matches exactly one character
- ✅
app?
matchesapp1
,app3
,apps
- ❌
app?
does not matchapp10
,apps1
,bus-app1
!
at start negates the pattern
- ✅
!prod
matchesdevelopment
,staging
- ❌
!prod
does not matchprod
List delimited globs
If you provide a list of globs to an individual rule property (projects
, targets
, configurations
), it will match any of the patterns for that given property.
1assignment-rules:
2 - targets:
3 - e2e-ci*
4 - lint*
5 run-on:
6 - agent: linux-medium
7 parallelism: 2
8
The following rule will match the following tasks:
- starts with
e2e-ci
(i.ee2e-ci--playwright-button-test
) - starts with
lint
(i.elint-js
)
Comma delimited globs
Within each list entry, you can define a list of globs. This notation will match a given property only if all globs match.
1assignment-rules:
2 - targets:
3 - 'e2e-ci*,*server-test'
4 - 'lint*'
5 run-on:
6 - agent: linux-large
7 parallelism: 5
8
The following rule will match the following tasks:
- starts with
e2e-ci
and ends withserver-test
(i.ee2e-ci--playwright-server-test
) - starts with
lint
(i.elint-js
)
Assignment Rule Precedence
Having multiple assignment rules means that often rules may overlap or apply to the same tasks. For a given task, only one rule will ever be applied. To determine which rule takes priority, more specific rules take precedence over more general rules. You can consult our precedence chart for a full list of rule priorities. A checkmark indicates that a rule has a particular property defined.
Priority | Configuration | Target | Project |
---|---|---|---|
1 | ✅︎ | ✅︎ | ✅︎ |
2 | ✅︎ | ✅︎ | |
3 | ✅︎ | ✅︎ | |
4 | ✅︎ | ✅︎ | |
5 | ✅︎ | ||
6 | ✅︎ | ||
7 | ✅ |
Rule Precedence Example
In this example, the task defined below can match multiple assignment rules. However, since the first rule specifies all three properties (project
, target
, and configuration
) rather than just two (project
and target
), it takes precedence, and we automatically apply the second rule when distributing the task.
1{
2 "project": "app1",
3 "target": "build",
4 "configuration": "production"
5}
6
1assignment-rules:
2 # A task for app1:build:production will use this rule because it is more specific (matches all three properties instead of just two)
3 - projects:
4 - app1
5 targets:
6 - build
7 configurations:
8 - production
9 run-on:
10 - agent: linux-medium-js
11 parallelism: 5
12
13 - projects:
14 - app1
15 targets:
16 - build
17 run-on:
18 - agent: linux-large-js
19 parallelism: 3
20
Using Assignment Rules with Self-Hosted Agents
A typical assignment-rules.yaml
file might look like this:
1assignment-rules:
2 - projects:
3 - app1
4 targets:
5 - build
6 configurations:
7 - production
8 run-on:
9 - agent: linux-medium
10 parallelism: 5
11 - agent: linux-large
12
13 - targets:
14 - lint
15 run-on:
16 - agent: linux-medium
17
18 - configurations:
19 - development
20 run-on:
21 - agent: linux-medium
22 - agent: linux-large
23
Note that the agent types supplied in the run-on
property will be used to determine which agents will have rules applied to them. You can choose to name your agent types anything you want, but they must be set on your agents via the NX_AGENT_LAUNCH_TEMPLATE
environment variable.
You can then reference your assignment rules file within your start-ci-run
command:
❯
npx nx-cloud start-ci-run --distribute-on="manual" --assignment-rules=".nx/workflows/assignment-rules.yaml"
The following is an example of what this looks like within a Github Actions pipeline:
1jobs:
2 main:
3 name: Main Job
4 runs-on: ubuntu-latest
5 steps:
6 - ... # setup steps for your main job
7
8 - run: npx nx-cloud start-ci-run --distribute-on="manual" --assignment-rules=".nx/workflows/assignment-rules.yaml" --stop-agents-after="e2e-ci"
9
10 - ... # Nx commands you want to distribute
11
12 medium-agents:
13 name: Agents ${{ matrix.agent }}
14 runs-on:
15 group: medium-agents
16 strategy:
17 matrix:
18 agent: [1, 2, 3]
19 steps:
20 - name: Checkout
21 uses: actions/checkout@v4
22
23 - uses: actions/setup-node@v4
24 with:
25 node-version: 20
26 cache: 'npm'
27
28 - ... # other setup steps you may need
29
30 - name: Install dependencies
31 run: npm ci --legacy-peer-deps
32
33 - name: Start Agent ${{ matrix.agent }}
34 run: npx nx-cloud start-agent
35 env:
36 NX_AGENT_NAME: ${{ matrix.agent }}
37 NX_AGENT_LAUNCH_TEMPLATE: 'linux-medium' # This value needs to match one of the 'run-on' values defined in the assignment rules
38
39 large-agents:
40 name: Agents ${{ matrix.agent }}
41 runs-on:
42 group: large-agents
43 strategy:
44 matrix:
45 agent: [1, 2, 3]
46
47 steps:
48 - name: Checkout
49 uses: actions/checkout@v4
50
51 - uses: actions/setup-node@v4
52 with:
53 node-version: 20
54 cache: 'npm'
55
56 - ... # other setup steps you may need
57
58 - name: Install dependencies
59 run: npm ci --legacy-peer-deps
60
61 - name: Start Agent ${{ matrix.agent }}
62 run: npx nx-cloud start-agent
63 env:
64 NX_AGENT_NAME: ${{ matrix.agent }}
65 NX_AGENT_LAUNCH_TEMPLATE: 'linux-large' # This value needs to match one of the 'run-on' values defined in the assignment rules
66
Using Assignment Rules with Dynamic Nx Agents
A typical distribution-config.yaml
file might look like this:
1distribute-on:
2 default: 5 linux-medium-js, 5 linux-large-js
3
4assignment-rules:
5 - projects:
6 - app1
7 targets:
8 - build
9 configurations:
10 - production
11 run-on:
12 - agent: linux-large-js
13
14 - targets:
15 - lint
16 run-on:
17 - agent: linux-medium-js
18 parallelism: 3
19
20 - configurations:
21 - development
22 run-on:
23 - agent: linux-medium-js
24 - agent: linux-large-js
25
You can then reference your distribution configuration in your CI pipeline configuration:
1...
2jobs:
3 - job: main
4 name: Main Job
5 ...
6 steps:
7 ...
8 - run: npx nx-cloud start-ci-run --distribute-on=".nx/workflows/distribution-config.yaml" --stop-agents-after="e2e-ci"
9 - ...
10
More Examples of Assignment Rules with Dynamic Agents
Invalid Assignment Rules Example
1distribute-on:
2 # Invalid small-changeset that is missing `linux-large-js`. Tasks assigned to large agents won't be able to execute.
3 small-changeset: 1 linux-small-js, 2 linux-medium-js
4 medium-changeset: 2 linux-small-js, 2 linux-medium-js, 3 linux-large-js
5 large-changeset: 3 linux-small-js, 3 linux-medium-js, 4 linux-large-js
6
7assignment-rules:
8 # Missing one of `projects`, `targets`, `configurations`
9 - run-on:
10 - agent: linux-medium-js
11 parallelism: 1
12 - agent: linux-large-js
13 parallelism: 3
14
15 # Missing `run-on`
16 - targets:
17 - lint
18 configurations:
19 - production
20
21 # Agent type not found in any of the `distribute-on` changesets
22 - projects:
23 - lib1
24 targets:
25 - test
26 run-on:
27 - agent: linux-extra-large-js
28
Valid Assignment Rules Example
1distribute-on:
2 default: 3 linux-small-js, 2 linux-medium-js, 1 linux-large-js
3
4# All rules below are valid assignment rules
5assignment-rules:
6 - projects:
7 - app1
8 run-on:
9 - agent: linux-medium-js
10 - agent: linux-large-js
11
12 - targets:
13 - lint
14 configurations:
15 - production
16 run-on:
17 - agent: linux-large-js
18 parallelism: 10
19
20 - projects:
21 - lib1
22 targets:
23 - test
24 run-on:
25 - agent: linux-medium-js
26