DEV Community

Cover image for Verify your pull requests in NX monorepos with GitHub Actions
OctoLab Team
OctoLab Team

Posted on

Verify your pull requests in NX monorepos with GitHub Actions

One of the great advantages of GitHub Actions is its ability to automate validation flows tailored to your project structure. And monorepos created with NX are a perfect case in point.

In this article, we will build a GitHub Actions workflow that automatically validates any pull request in an NX monorepo, running lint, tests, and compilation only on the affected projects. This allows us to speed up CI, reduce noise, and maintain code quality without wasting resources.

🎯 What is the purpose of this workflow?

We want the following actions to be performed every time a pull request is opened:

  • Detect which parts of the monorepo have been affected
  • Run lint only on those parts
  • Run the relevant tests
  • Compile the affected packages or applications

This ensures that only necessary tasks are executed and that errors are detected as soon as possible β€” something that is key in monorepos of a certain size.

🧬 General structure of the workflow

Below, I will show you the complete content of the workflow that we are going to analyze:

name: NX Pull request verify
on:
  pull_request: {}

jobs:
  verify:
    name: verify
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: "22"

      - name: Install dependencies
        run: npm install

      - name: Run lint
        run: npx nx affected --target=lint --head=HEAD --base=origin/main

      - name: Run tests
        run: npx nx affected --target=test --head=HEAD --base=origin/main

      - name: Build package
        run: npx nx affected --target=build --head=HEAD --base=origin/main

Enter fullscreen mode Exit fullscreen mode

Let's now take a step-by-step look at what each section does.

πŸ› οΈ What does each step involve?

on: pull_request
This section indicates that the workflow will run every time a pull request is opened, updated, or reopened. It is the most common trigger in CI flows for collaborative teams.

uses: actions/checkout@v4
This step downloads the code from the repository so that it is available in the runner.

πŸ“Œ Tip: You can configure this step to make a shallow clone or bring in specific branches, but the default configuration is usually sufficient.

uses: actions/setup-node@v4
Here we define the version of Node.js that will be used in the runner (v22 in this case). This ensures consistency between developers and CI.

Some additional useful options:

  • cache: β€˜npm’: speeds up the installation of dependencies
  • check-latest: true: forces the latest available version of semver
  • registry-url: useful if you are going to publish packages to NPM

run: npm install
Install the project dependencies. For CI environments, it is recommended to use npm ci if you have a package-lock.json, as it is faster and more predictable.

βš™οΈ The specific logic of NX

The most interesting thing about this workflow is that it uses the nx affected command, which allows you to run tasks only on projects affected by the changes introduced in the pull request.

npx nx affected --target=lint
Run linter only on modified projects.

npx nx affected --target=test
Run the corresponding tests only on those projects.

npx nx affected --target=build
Only compile the packages or applications that have been affected.

This selective approach is one of the great advantages of NX, and its integration with GitHub Actions makes it especially powerful in large monorepos.

🧠 What do --head and --base mean?

These two options tell NX which branches to compare the changes against to determine what has been affected:

  • --base=origin/main: specifies the reference branch (e.g., main)
  • --head=HEAD: refers to the current commit of the PR

NX will calculate which projects have been modified between main and the HEAD of the pull request, and will only execute the necessary tasks on them.

βœ… Final result: Intelligent and efficient CI

This workflow allows each pull request to go through a well-defined validation system, without the need to run unnecessary tasks across the entire repository.

Key advantages:

  • Saves execution time in CI
  • Less resource consumption
  • Early validation of errors in critical code
  • Improves the experience for external contributors

πŸ’‘ Ideas for extending this workflow

Some ideas to improve it even further:

  • Add caching with actions/cache
  • Run validation on multiple versions of Node using matrix
  • Include automatic comments in the pull request with results
  • Split jobs in parallel (lint, test, build)

But we'll leave that for another article! πŸ˜‰

πŸ™ Would you prefer a visual way to build this workflow?

If you don't want to write this YAML by hand or prefer to focus on logic rather than syntax, you can use OctoLab:

  • βœ… Step-by-step visual editor
  • βœ… Smart fields for NX actions
  • βœ… Real-time YAML preview
  • βœ… Automatic validations
  • βœ… Copy, download, and use instantly

πŸ‘‰ Try it out at: https://www.octolab.app

🧡 Conclusion

Well-managed NX monorepos require efficient automation, and this workflow is an excellent way to ensure quality without wasting resources. With tools like GitHub Actions and approaches like nx affected, you can take your project's CI to the next level.

And if you want to do all this without fighting with YAML, you know where to find help πŸ€—.

Top comments (0)