MikkoTikkanen.

How to: Npm release & changelog automation with Github Actions

Cover for How to: Npm release & changelog automation with Github Actions
Mikko Tikkanen
Mikko Tikkanen

One of the hallmarks of highly functioning development teams is speed of the release cycle - Highly functioning agile teams release more often than those that are still lagging behind. One of the cornerstones of such teams is high level of automation as time spent doing releases is off from development and repetitive manual work equates to high risk of human errors. Additionally, release process is also one the most critical things to automate as errors during release can have high impact on business and/or end user experience. Thus, to fix that problem, here is a quick tutorial how to set up automation to publish your packages to npm, version them correctly and create clean, human readable changelogs for each version released.

How it works

There are three pieces we need for the automation: Conventional Commits, Github Actions and semantic-release.

This setup is based on trunk based development workflow, where pull requests are merged to master and releases are made directly from there. If you have different type of workflow, you need to modify the settings according.

Conventional Commits

Conventional Commits is a convention for writing commit messages (or pull request merges if you use squash and merge) that makes them machine readable, this way automation can deduct the scope of the release and build human readable changelog based on it. We will be using Conventional Commits to write our commit messages/pull requests.

Commit message following Conventional Commits should be structured as follows:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Example of simple commit message: fix(package.json): Fixed the package namespacing

Read more at conventionalcommits.org

Github Actions

Github Actions are simple way to automate development workflows. We will be using simple Github Action to run our release & publish action whenever anything new lands on master branch.

Read more at github.com/features/actions

semantic-release

Semantic-release is a release automation package that does it all for you based on commit messages written following Conventional Commits. It reads the git history, figures out what is new, what should the version number be, writes changelog and publishes the package. We will be using this for doing the actual release.

Read more at github.com/semantic-release.

Setting it up

How to set everything up in three simple steps

1. Enforce Conventional Commits

Semantic Pull Requests check

In order to make sure that all of our commits/pull requests are machine readable we need to enforce that they follow the Conventional Commits. There are tons of Github actions and apps for this, one that I have personally been using is Semantic Pull requests. Whatever you choose, enable it as required pull request check for the repository.

2. Add release action

Next we need to define the release workflow that runs the semantic-release package and set it to be executed when anything gets pushed/merged to master.

Create file at .github/workflows/release.yml

name: Release

on:
  push:
    branches:
      - master

jobs:
  release:
    name: Release
    runs-on: ubuntu-18.04
    steps:
      - name: Checkout
        uses: actions/checkout@v1
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: Install dependencies
        run: npm ci
      - name: Run build
        run: npm run build --if-present
      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npm run release

3. Configure NPM_TOKEN

In order for sematic-release to be able to publish the package to npm you need to provide an access token for it through Github secrets.

Log in to npmjs.com and generate new access token, make sure it has Publish access level.

Create new access token

Set it to secrets as NPM_TOKEN in your repository settings

Set Github secret

All done

And there you have it. You should now have automation that triggers when anything is pushed/merged to master branch, releasing your module without any human interaction.

What the automation does:

  1. Git history is scanned for any new commits matching Conventional Commits standard
  2. New version number is set according to the commit history since last release
  3. The module is published to npm with matching version number
  4. New Github release is created and human readable changelog is created for it

Published npm package:

Npm package

Github release with changelog:

Github Release

Happy releasing!