DEV Community

Cover image for Verify your Pull Requests with GitHub Actions in Node.js projects
OctoLab Team
OctoLab Team

Posted on

Verify your Pull Requests with GitHub Actions in Node.js projects

One of the most common uses of GitHub Actions in Node.js projects is to automate code validation every time someone proposes a change via a pull request.

This type of validation usually involves several key steps:

  • Install dependencies to make sure the project can run correctly.
  • Running the linter, a tool that analyzes the style and quality of the code.
  • Run the tests that automatically verify that the project's functionality continues to work.
  • Build the project to check for errors before deploying or publishing.

In this article we will set up a GitHub Actions workflow that automates this whole process every time someone opens or updates a pull request. We will explain step by step what each part of the workflow does and why it is important.

🎯 The purpose of the workflow

We want that, every time a pull request is opened in our project, a set of tasks is executed to verify that the code complies with the project standards:

  • It installs correctly
  • Passes the linter tool
  • Passes the tests
  • Compiles without errors

🧬 General workflow structure

name: Node.js 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: npm run lint

      - name: Run tests
        run: npm run test

      - name: Build package
        run: npm run build
Enter fullscreen mode Exit fullscreen mode

βš™οΈ What parts compose a GitHub Actions workflow?

Before going into detail, it is useful to understand how a GitHub Actions workflow is structured. The main elements are:

Trigger (on:)
Defines when the workflow is executed. It can be when pushing, opening a pull request, publishing a release, executing manually, etc.
In our case, we use pull_request, which is triggered every time a PR is created or updated.

Job (jobs:)
Each workflow can have one or several jobs. A job is a set of tasks that are executed in the same environment.
All the steps of a job share the same filesystem and context. In our example, we have a single job called verify.

Runner (runs-on:)
It is the operating system where the job is executed. GitHub provides hosted runners, such as ubuntu-latest, windows-latest or macos-latest, but we also have the possibility to use self-hosted runners.

Steps (steps:)
These are the actions or commands that are executed within a job. They can be:

  • Reusable actions such as actions/checkout or actions/setup-node.
  • Specific commands defined with run, such as npm install or npm test.

πŸͺœ Step-by-step of our workflow

Now that we understand how a workflow is structured, let's analyze each of the steps that make up our workflow. We will see what each action does, why it is necessary and what additional configurations we could apply depending on the case.

on: pull_request

This block indicates that the workflow will be triggered when a pull request is opened, updated or reopened in the repository. It is ideal for branch-based continuous integration flows.

uses: actions/checkout@v4

This step downloads the code from the repository so that it is available within the runtime environment.

Some additional options that this action allows are:

  • fetch-depth: 0 clones the entire repository history (by default only the current commit).
  • ref: branch-name** you can set a specific branch
  • path: subdirectory clone the code in a specific path

For this case, just use it without extra configuration:

- uses: actions/checkout@v4
Enter fullscreen mode Exit fullscreen mode

uses: actions/setup-node@v4

This action installs a specific version of Node.js, in our case version 22. It also allows you to configure dependency caching, authentication with registries, and more.

- uses: actions/setup-node@v4
  with:
    node-version: "22"
Enter fullscreen mode Exit fullscreen mode

Other useful options are:

  • cache: β€˜npm’ enables dependency caching using actions/cache underneath
  • check-latest: true** forces to use the latest available version that complies with the semver.
  • registry-url: to configure publishing to NPM

Working scripts

- run: npm install
- run: npm run lint
- run: npm run test
- run: npm run build
Enter fullscreen mode Exit fullscreen mode

These steps execute the commands defined in the project's package.json file. Their purpose is to prepare and validate the code before it goes to production:

  • npm install will install all the project's dependencies.
  • npm run lint will run the linter, which helps to detect style errors or common problems in the code.
  • npm run test** will run the automatic tests defined by the team.
  • npm run build** will generate the final package, either an app, a library or a bundle ready to deploy.

πŸ’‘ If you are using package-lock.json, you can replace npm install with npm ci, which is faster and guarantees a more consistent and reproducible installation in CI environments.

βœ… Final result

With this flow you guarantee that all code proposed via pull request has gone through a basic verification, without the need for manual reviews or local builds. You can integrate it with other additional steps such as:

  • Static analysis (Sonar, extended ESLint...).
  • Automatic comments on Pull Request
  • Deploys to staging environments
  • ...

πŸ™ Do you want to avoid writing it by hand? There is a more convenient way

Understanding how a workflow works in Github Actions is indispensable. It gives you control and helps you customize everything to your needs.

Now... if you don't feel like struggling with the syntax, that's fine too.
At OctoLab we offer you the ability to set up this same flow visually: you choose the actions, fill in the fields and it generates the YAML for you on the fly.

βœ… Without indentation errors
βœ… With built-in validations
βœ… Copy, paste and go.

🧠 Conclusion

This workflow is an excellent basis for quality assurance in Node.js projects. It can be easily adapted to other needs: monorepos, automatic deployments, publishing to NPM or running on multiple versions of Node.

If you prefer to use OctoLab we will be very grateful for your feedback! πŸ€—

Top comments (0)