Manual Distributed Task Execution on Github Actions
Using Nx Agents is the easiest way to distribute task execution, but it your organization may not be able to use hosted Nx Agents. You can set up distributed task execution on your own CI provider using the recipe below.
Run Custom Agents on GitHub
Our reusable GitHub workflow represents a good set of defaults that works for a large number of our users. However, reusable GitHub workflows come with their limitations.
If the reusable workflow above doesn't satisfy your needs you should create a custom workflow. If you were to rewrite the reusable workflow yourself, it would look something like this:
.github/workflows/ci.yml
1name: CI
2on:
3 push:
4 branches:
5 - main
6 pull_request:
7
8# Needed for nx-set-shas when run on the main branch
9permissions:
10 actions: read
11 contents: read
12
13env:
14 NX_CLOUD_DISTRIBUTED_EXECUTION: true # this enables DTE
15 NX_BRANCH: ${{ github.event.number || github.ref_name }}
16 NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
17 NPM_TOKEN: ${{ secrets.NPM_TOKEN }} # this is needed if our pipeline publishes to npm
18
19jobs:
20 main:
21 name: Nx Cloud - Main Job
22 runs-on: ubuntu-latest
23 steps:
24 - uses: actions/checkout@v4
25 name: Checkout [Pull Request]
26 if: ${{ github.event_name == 'pull_request' }}
27 with:
28 # By default, PRs will be checked-out based on the Merge Commit, but we want the actual branch HEAD.
29 ref: ${{ github.event.pull_request.head.sha }}
30 # We need to fetch all branches and commits so that Nx affected has a base to compare against.
31 fetch-depth: 0
32 filter: tree:0
33
34 - uses: actions/checkout@v4
35 name: Checkout [Default Branch]
36 if: ${{ github.event_name != 'pull_request' }}
37 with:
38 # We need to fetch all branches and commits so that Nx affected has a base to compare against.
39 fetch-depth: 0
40 filter: tree:0
41
42 # Set node/npm/yarn versions using volta
43 - uses: volta-cli/action@v4
44 with:
45 package-json-path: '${{ github.workspace }}/package.json'
46
47 - name: Use the package manager cache if available
48 uses: actions/setup-node@v3
49 with:
50 node-version: 20
51 cache: 'npm'
52
53 - name: Install dependencies
54 run: npm ci
55
56 - name: Check out the default branch
57 run: git branch --track main origin/main
58
59 - name: Initialize the Nx Cloud distributed CI run and stop agents when the build tasks are done
60 run: npx nx-cloud start-ci-run --distribute-on="manual" --stop-agents-after=e2e-ci
61
62 - name: Run commands in parallel
63 run: |
64 # initialize an array to store process IDs (PIDs)
65 pids=()
66
67 # function to run commands and store the PID
68 function run_command() {
69 local command=$1
70 $command & # run the command in the background
71 pids+=($!) # store the PID of the background process
72 }
73
74 # list of commands to be run on main has env flag NX_CLOUD_DISTRIBUTED_EXECUTION set to false
75 run_command "NX_CLOUD_DISTRIBUTED_EXECUTION=false npx nx-cloud record -- nx format:check"
76
77 # list of commands to be run on agents
78 run_command "npx nx affected -t lint,test,build,e2e-ci --parallel=3"
79
80 # wait for all background processes to finish
81 for pid in ${pids[*]}; do
82 if ! wait $pid; then
83 exit 1 # exit with an error status if any process fails
84 fi
85 done
86
87 exit 0 # exits with success status if a all processes complete successfully
88
89 agents:
90 name: Agent ${{ matrix.agent }}
91 runs-on: ubuntu-latest
92 strategy:
93 matrix:
94 # Add more agents here as your repository expands
95 agent: [1, 2, 3]
96 steps:
97 - name: Checkout
98 uses: actions/checkout@v4
99
100 # Set node/npm/yarn versions using volta
101 - uses: volta-cli/action@v4
102 with:
103 package-json-path: '${{ github.workspace }}/package.json'
104
105 - name: Use the package manager cache if available
106 uses: actions/setup-node@v3
107 with:
108 node-version: 20
109 cache: 'npm'
110
111 - name: Install dependencies
112 run: npm ci
113
114 - name: Start Nx Agent ${{ matrix.agent }}
115 run: npx nx-cloud start-agent
116 env:
117 NX_AGENT_NAME: ${{ matrix.agent }}
118
There are comments throughout the workflow to help you understand what is happening in each section.