Luke Hansford

S
i
m
p
l
e
G
i
t
h
u
b
A
c
t
i
o
n
s
C
I
f
o
r
J
a
v
a
s
c
r
i
p
t
p
r
o
j
e
c
t
s

Simple Github Actions CI for Javascript projects

3 min read

Over the last few years I've started to default to using Github Actions when it comes to CI. I've worked with a number of different offerings in the past, most noticeable AWS's suite of CI tools and Gitlab, but I've found Github Actions to be the best combination of simplicity and power for my purposes.

In this post I'll share my basic template for getting CI into a Javascript project. It presupposes that your projects already has processes for running linting, tests, and builds, and that you're somewhat familiar with Github Actions syntax.

name: CI
on: [push]

To start off we're going to run this action on any push event to the repository. Depending on your git workflow you may want to exclude your default branch as you might be doing redundant runs of your CI.

jobs:
  install:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: 16
        cache: 'npm'
     - run: npm ci

Next we have our first job, install. The install job will checkout the repository code using actions/checkout@v3(this is repeated on each job). We're then setting up node using actions/setup-node@v3. We specify a node version, but the import parameter is cache. This will maintain a cache of our node_modules. We then run npm ci to install our production dependencies, which will all go into our new cache.

lint:
  needs: install
  runs-on: ubuntu-latest

  steps:
  - uses: actions/checkout@v3
  - uses: actions/setup-node@v3
    with:
      node-version: 16
      cache: 'npm'
  - run: npm ci
  - run: npm run lint

Our next job is lint, and you might notice it's almost exactly the same as the install job. We have two additional lines: needs: install tells the job to wait until after install is complete before starting, and npm run lint runs our actual linting process. The rest of the code performs a nice trick. As we're again setting up the cache with actions/setup-node@v3, when npm ci is called it's going to find that all the dependencies it needs to install are already in the cache and immediately jump to our linting step!

unit-test:
  needs: install
  runs-on: ubuntu-latest
  
  steps:
  - uses: actions/checkout@v3
  - uses: actions/setup-node@v3
    with:
      node-version: 16
      cache: 'npm'
  - run: npm ci
  - run: npm run test
  
build:
  needs: install
  runs-on: ubuntu-latest

  steps:
  - uses: actions/checkout@v3
  - uses: actions/setup-node@v3
    with:
      node-version: 16
      cache: 'npm'
  - run: npm ci
  - run: npm run build

Our last two jobs, unit-test and build repeat the same thing as lint did, just running their own particular processes. So why is it useful to structure the jobs this way? Well you might have noticed that all three jobs have install as a dependency. This means we can run our install job first, and then unit-test, lint, and build can run in parallel, reducing our CI time to the length of whatever our slowest job is.

This set up is a very basic configuration and hopefully something you might find useful for getting started with Github Actions. You can view the full code example here.

Webmentions

No one has interacted with this page yet.