Running Nx Affected Commands in GitHub Actions
Tags: angular, webdev, github, javascript
Published: 2021-04-08 12:23:16

Preston Lamb | ng-conf | Oct 2020

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6f29eqmvgmudb23tlqku.png)
 
### **tldr;**
Working in an Nx monorepo over the last year has been really great. Sharing code between projects is really convenient. The only problem is that as you add more libraries and applications and projects, the time it takes to build or test applications grows as well. The good thing is that Nx monorepos come with a variety of commands that run on only portions of the codebase. For example, if your change only affects one library in your project, you can test just that library instead of the entire project. This is especially useful on your CI/CD server when you create pull requests. Tests can be run on the pull request branch, making sure that any new code is working and that it didn’t break any previous portions of the app. In this post, we’ll go over how to create a GitHub Action workflow to run the affected tests when a pull request is created.

### **The Setup**
In my situation, I have an Nx monorepo with two applications in it. There are a lot of libraries included as well. Some of the libraries are shared, and some are specific to the application. What I needed was a solution for running the `nx affected:test` command when a pull request was created. This would run the tests for just those projects affected by the code changes. If the tests pass, the PR can safely be merged.

I first started to implement this using Google Cloud, as that is the product we use to build and deploy our applications at my full time job. I was never able to get it to work, though, because for `nx affected` to work it needs the git history for the repo. I tried many solutions, but could never get the git history into the cloud build instance. My only solution was to run all the tests on each PR. This worked for a while, but as the repository has grown, more tests and libraries have been added. Last week, the tests started timing out and wouldn’t finish. It no longer became a viable solution. Because of that, I came to GitHub Actions to try and solve the issue.

### **Creating Your GitHub Action**
If you’ve never tried GitHub Actions before, you’ll find the process straightforward and convenient. Before creating your action, switch to a new branch in your repo. Next, create a `.github` folder in the root of your repository, with a nested `workflows` folder:

```
mkdir .github
mkdir.github/workflows
```

The `yaml` files that we place inside the `.github/workflows` folder will be run as GitHub Actions. In this case, the next step is creating a new yaml file, which I’ll call `nx-affected.yml`. This file will define the steps for the action. I won’t go into all the details of each step; that’s more suited for another article. I will provide insight on the more important steps to accomplish our goals here, though. Here’s the full contents of the YAML file, after which we’ll break it down piece by piece.

```
name: Nx Affected CI
on:
  pull_request:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [12.x]
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}
      - run: git fetch origin main
      - run: npm install
      - name: Run Affected Tests
        shell: bash
        run: npm run affected:test -- --base=remotes/origin/main
```

Let’s break this down piece by piece and explain what’s going on.

```
name: Nx Affected CI
on:
  pull_request:
    branches: [main]
```

At the top of the workflow yaml file we give our workflow a name. After that we determine when the workflow will be run. In this case, the workflow will run when pull requests are created for merging into the main branch. Other branches can also be targeted by being added to the array.

```
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [12.x]
```

The next part of the yaml file is the meat of the workflow. The first part I’ll point out is that we determine what operating system to use for the action with the `runs-on` attribute. In this case, `ubuntu-latest`. Next, the `strategy` and `matrix` attributes allow us to determine multiple versions of node to use for running the tests. This part is optional. You can choose just one version if you’d like, or select multiples. The action will run for each version of node that you provide in the array.

```
steps:
  - uses: actions/checkout@v2
    with:
      fetch-depth: 0
  - name: Use Node.js ${{ matrix.node-version }}
    uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
  - run: git fetch origin main
  - run: npm install
```

The `steps` section of our workflow file is where we will accomplish the goal of the workflow. In other words we will prepare to run the tests and run them. These first three steps checkout the git repository into the context of the workflow. `fetch-depth: 0` ensures that we get the full git history, which is necessary for running the `nx affected` commands. The second step determines the node version to use (using our `matrix` from the `strategy` section above). The third step fetches the latest information from the main branch. We need that information because Nx runs compares the current branch to the `main` branch to determine what has changed. The last step I’ve included here is to run `npm install`. This ensures that all necessary packages are ready for the application to be built and tested.

```
- name: Run Affected Tests
  shell: bash
  run: npm run affected:test -- --base=remotes/origin/main
```

This last step is where we actually run the tests. We gave the step a `name`, and specify the `shell` to be used while running the tests. When this step runs, we run an npm command declared in the `package.json`. This will run the Nx command that runs tests against projects that have changed between the branch of the pull request and the `main` branch. The tests will be run, and if they are successful the workflow will end in a success status. If any tests fail, the workflow ends with a failure status. Both of these statuses will show on the pull request page in GitHub.

### **Running the Action**
To test the action, push your changes to the repository and create a pull request using the branch that you did this work on, with the intent to merge it into `main`. When you create the pull request, the action you just created will start running. You can see it in the repository. You can get there by clicking the “Actions” tab on the repository’s main page:

![screenshot of the GitHub header tool bar. The are 9 different tabs, each with a unique icon. The tabs read: Code, Issues, Pull requests, Actions, Projects, Wiki Security, Insight, and Settings.](https://miro.medium.com/max/700/1*_TXS_F-8eI7Ms1240hZusA.png)
###### Location for the Actions in a GitHub repository

Once you’ve clicked on that tab, you’ll see a table of the actions that you’ve run in this repository. If the workflow is currently running, you’ll see a yellow circle. If it was unsuccessful, it’s marked with a red x. If it was successful, you’ll see a green check mark.

![Screenshot of the actions page for a GitHub repository. On the left hand side is a small menu named Workflows that has opened to the All Workflows menu, that has the option of Nx Affected Ci. All workflows is highlighted in blue. The main page reads "All workflows" at the top, there is a search bar under that labeled "Filter workflows". Under the search bar it states 38 results. one result named "Workflow edit" is shown.](https://miro.medium.com/max/700/1*DbXjukQuykn_POArXHZ-vw.png)
###### List of all the actions run in a repository

Clicking on one of the rows will show you the details of that action. It will show each step that was defined in your action and the logs that are pertinent to that step. Each time you create a pull request, or push updates to an existing PR, the tests will run.

### **Additional Information**
You can use this same step, or duplicate it, to run other Nx affected commands, such as `lint`, `build`, or `e2e`. They can all be run in a single workflow as separate steps, or you can have one workflow for each of them. In addition, you could use an action to build your application in a Docker image and push the image to GitHub’s package registry (or another registry like Docker Hub). Here are a couple previous articles of mine that may help you out. In addition, here’s a reference to a post on Dev.to that I used to help me get started with testing affected projects in my Nx monorepo.

* [Docker-izing your Angular Application](https://www.prestonlamb.com/blog/dockerizing-angular)
* [Create a Docker Image with GitHub Actions](https://www.prestonlamb.com/blog/creating-a-docker-image-with-github-actions)
* [Running Nx Affected Commands in GitHub Actions by Devin Shoemaker](https://www.prestonlamb.com/blog/creating-a-docker-image-with-github-actions)

## **ng-conf: The Musical is coming**
ng-conf: The Musical is a two-day conference from the ng-conf folks coming on April 22nd & 23rd, 2021. Check it out at [ng-conf.org](https://www.2021.ng-conf.org/)