GitHub Actions: Setting up CI for a JS/TS/Node project
Tags: github, git, devops, opensource
Published: 2020-08-12 05:21:31

Having used and modified CI/CD systems in Jenkins and GitLab CI in the past, I have never set it up myself. Wanting to learn something new, I decided to look into GitHub Actions to add CI/CD to an open-source project of mine called [flooent](https://github.com/MZanggl/flooent). In this series of articles, I will share how I set up CI, test coverage, and CD.

I will show you how you
- can run tests automatically when pushing a change or creating/updating a PR
- create and save a test coverage report and show its results in your README as well as in PRs
- Automatically publish different versions of your project to NPM by creating a release on GitHub.

Even if your project is set up a little differently, I hope this can give you some ideas for how to create a pipeline for your use case.

## Setting up CI

In this post, we will cover how to run tests automatically when pushing a change to a repository or creating/updating a PR.

To get started you need to create a `.yml` file in a specific directory. While you can do that through GitHub (under "Actions"), in this post we will set it up on our local. It's really simple.

In the root of your repository create the directories `.github/workspaces`.

```bash
mkdir .github
cd .github
mkdir workspaces
cd workspaces
```

GitHub Actions will pick up `.yml` files inside this directory. Let's create the file `ci.yml`.

Basically it goes like this: 
- checkout the branch
- install node (on ubuntu)
- install the dependencies of your project and build it if necessary
- finally, run the tests


I added comments to almost every line explaining the setup.

```yml
# This workflow will do a clean install of node dependencies, build the source code and run tests
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: CI Pipeline

# trigger build when pushing, or when creating a pull request
on: [push, pull_request]

jobs:
  build:

    # run build on latest ubuntu
    runs-on: ubuntu-latest

    steps:
    # this will check out the current branch (https://github.com/actions/checkout#Push-a-commit-using-the-built-in-token)
    - uses: actions/checkout@v2
    # installing Node
    - name: Use Node.js 12.x
      uses: actions/setup-node@v1
      with:
        # this will use the latest Node 12 version
        node-version: 12.x
    # install dependencies using clean install to avoid package lock updates
    - run: npm ci
    # build the project if necessary
    - run: npm run build --if-present
    # finally run the tests
    - run: npm test
```

Note how we make use of other GitHub actions like [actions/checkout@v2](https://github.com/actions/checkout#Push-a-commit-using-the-built-in-token). Actions like these handle common tasks, and of course, you can create your own!

If you want to run tests across different versions of Node, you can specify a matrix. The script would look like this:

```yml
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Node.js CI

# trigger build when pushing, or when creating a pull request
on: [push, pull_request]

jobs:
  build:

    # run build on latest ubuntu
    runs-on: ubuntu-latest

    strategy:
      matrix:
        # Run build for both Node version 12 and version 14
        node-version: [12.x, 14.x]

    steps:
    # for checking out the branch (https://github.com/actions/checkout#Push-a-commit-using-the-built-in-token)
    - uses: actions/checkout@v2
    # installing Node
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        # this is regarding the matrix strategy specified above
        node-version: ${{ matrix.node-version }}
    # install dependencies
    - run: npm ci
    # build the project if necessary
    - run: npm run build --if-present
    - run: npm test
```

Believe it or not, but that's it!

Now when you push this, you should see a pipeline built under "Actions" as well as the status of the last build on the repository:
![showing the last build status](https://dev-to-uploads.s3.amazonaws.com/i/mdicd0w908auk4j7pihz.png)

Notice the checkmark next to the commit hash. Clicking on it will also lead you to the build.

If any of your tests fail, the job will fail and alert you per email (You can configure this in your GitHub settings).

Furthermore, when a PR is created the build will also be triggered and you will see the results directly in the PR.

Take a look at the script I use for flooent: https://github.com/MZanggl/flooent/blob/latest/.github/workflows/ci.yml

---

And that's about it. I was pleasantly surprised by how easy it was to set it up. Next time let's check out how to add test coverage!