NPM package deployment using YAML GitHub Actions

Wednesday, August 21, 2019


Recently GitHub announced that GitHub Actions will be moving away from the original HCL syntax in-favour of a YAML format similar to Travis CI and Bitbucket Pipelines. This means that HCL style actions will no longer work after September 30, 2019. It is possible to migrate using a migration script however in-some cases it may be required to reconfigure.

This particular issue occurred to me as actions which return a neutral result seem to fail the whole build with the YAML format. This means that using actions/bin/filter to trigger a deploy would fail the build unless a release tag was found. With this in mind, reconfiguring my GitHub Actions seemed like the best choice.

Desired Behaviour

My particular use of GitHub Actions is for deploying my small NPM packages.

To keep it simple I wanted the following to occur:

  • Install dependencies, Build and Test package on each commit
  • Publish package if a release tag was created

Creating the Action Configuration

Create the file .github/workflows/workflow.yml

Checking for Tag

This method simply builds and tests the package on any commit.

Then if it finds a tag starting with v, it will trigger a deploy.

So if a GitHub Release is created with the tag v2.3.4, it will trigger a deploy.

This is a bit naive however for my purposes I usually don't tag unless its a release.

One advantage of checking for a tag this way is that it cuts down on unneeded builds as a whole build can only ever run 1 or 2 times (2 in the case a build is deployed).

The GitHub Actions docs mentions being able to restrict actions to certain branches or tags however I could not get this to work.

name: build # Name Action Build
 
on: [push]  # Trigger on push
 
jobs:
  run:
    runs-on: ubuntu-latest                         # Run on Ubuntu Docker image
    steps:
    - name: Checkout Repo                          # Checkout repo
      uses: actions/checkout@v1
    - name: Use Node.js                            # Configure Node.js
      uses: actions/setup-node@v1
      with:
        node-version: '12.9'                       # Set Node.js Version
        registry-url: 'https://registry.npmjs.org' # Set Node.js reigistry
    - name: Deploy Info                            # Print GitHub Deploy info
      env:
        GITHUB_CONTEXT: ${{ toJson(github) }}
      run: echo "$GITHUB_CONTEXT"
    - name: Install                                # Install dependancies
      run: npm install
    - name: Build                                  # Build app if needed
      run: npm run build --if-present
    - name: Test
      run: npm run test --if-present               # Run tests if needed
    - name: Publish
      if: startsWith(github.ref, 'refs/tags/v')    # Check if publish step should run
      run: npm publish --access public             # Publish package
      env:
        NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} # Set NPM auth token from GitHub Secrets

Checking for a Release

If you found the previous method too naive, you may want to check for a GitHub Release before triggering a deploy.

The drawback to this is that a few extraneous builds will be triggered as the release event will fire both when the release is created and published. As far as I am aware this can not be restricted using the on property.

To ensure we only deploy once, we will indicate to only run the Publish step when a release is published.

name: build
 
on:
  push:     # Run build on push (commit in most cases)
    tag: [] # Only run build if not tagged
  release:  # Run build on release
    tag:
    - v*    # Check for release tag
 
jobs:
  run:
    runs-on: ubuntu-latest                         # Run on Ubuntu Docker image
    steps:
    - name: Checkout Repo                          # Checkout repo
      uses: actions/checkout@v1
    - name: Use Node.js                            # Configure Node.js
      uses: actions/setup-node@v1
      with:
        node-version: '12.9'                       # Set Node.js Version
        registry-url: 'https://registry.npmjs.org' # Set Node.js reigistry
    - name: Deploy Info                            # Print GitHub Deploy info
      env:
        GITHUB_CONTEXT: ${{ toJson(github) }}
      run: echo "$GITHUB_CONTEXT"
    - name: Install                                # Install dependancies
      run: npm install
    - name: Build                                  # Build app if needed
      run: npm run build --if-present
    - name: Test
      run: npm run test --if-present               # Run tests if needed
    - name: Publish
      if: github.event_name == 'release' && github.event.action == 'published' # Check if publish step should run
      run: npm publish --access public             # Publish package
      env:
        NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} # Set NPM auth token from GitHub Secrets

Setting NPM Auth Token Secret

Simply go to your repo Settings and select the Secrets tab.

Then Add a new secret with the Name of NPM_AUTH_TOKEN and set the Value to your NPM token.

Adding the GitHub Actions badge

GitHub now offers an undocumented API which will return nice Travis CI like status badge.

An example can be seen on the actions/toolkit repo.

The format for the API is as follows:

https://github.com/<user|org>/<repo>/<action_name>/badge.svg

The action_name propery is the name field in the YAML which in this case is build.

An example of this would be:

https://github.com/woofers/ludum-dare-badges/workflows/build/badge.svg

To make it even nicer we can link the badge to our repo's actions page:

[![img](https://github.com/woofers/ludum-dare-badges/workflows/build/badge.svg)](https://github.com/woofers/ludum-dare-badges/actions)

It will look something like this:


JaxsonVan Doorn