DEV Community

Caleb O.
Caleb O.

Posted on

Automating npm package releases with GitHub Actions

I should have written this last year, after my talk at DevFest Ibadan 2023. But, I just couldn't get the GitHub workflow to run successfully. It was terrible.

So, recently, I finally figured it out by getting it to work in metadata

GitHub actions tab of the metadata package showing a successful workflow run

Getting started

To cut through the chase, the first thing you need to do is install the semantic-release package with your preferred JavaScript package manager.

yarn add semantic-release
Enter fullscreen mode Exit fullscreen mode

Semantic-release combs through all your commit messages, analyzes them with the angular commit convention, and bumps your package version number with semantic-versioning in mind.

More on that here

This is where you reap the benefits of writing good/semantic commit messages.

Creating a workflow

The snippet below is the basic setup of what you'd need to automate the releases of your npm package.

name: release

on:
  push:
    branches:
      - master

jobs:
  release:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout current branch
        uses: actions/checkout@v2

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies
        run: yarn

      - name: Build package
        run: yarn build

      - name: Semantic Release
        run: npx semantic-release
        env:
          GH_TOKEN: ${{ secrets.GH_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
permissions:
  contents: write
  pages: write
  id-token: write
Enter fullscreen mode Exit fullscreen mode

In your project directory, create a directory and name it .github, move into it, and create another one called workflows, then create a <workflow.yml> file.

In this case, releases.yml. You can call it anything you want. But I'd recommend that you give it a name that encapsulates what it is meant to accomplish.

You may not exactly need to specify any permissions since the GitHub Personal Access Token you'll generate has the repo_scope, so all these permissions could be enabled by default.

on:
  push:
    branches:
      - master
Enter fullscreen mode Exit fullscreen mode

In the snippet above. This step of the workflow controls when and where the workflow runs. In this case, it only runs when a push event in the master branch occurs in your repository.

Make sure to change your branch name if it isn't master.

Creating environment variables

The important part of getting this to work is creating environment variables. This part stressed me so much.

For semantic-release to work it requires two environment variables, GH_TOKEN, short for GitHub Token, and NPM_TOKEN. Although, NPM_TOKEN can be optional, if you don't want it to publish your package to npm for you.

You can omit it if you want to take charge of doing npm publish by yourself. But, note that the workflow run would still fail on GitHub because the CI environment expects that token.

To bypass this, you can modify the Semantic Release step in the workflow to run in dry mode like so:

      - name: Semantic Release
        run: npx semantic-release --dry-run
Enter fullscreen mode Exit fullscreen mode

The objective of the dry-run mode is to get a preview of the pending release. Dry-run mode skips the following steps: prepare, publish, addChannel, success and fail. In addition to this it prints the next version and release notes to the console.

To get your GH_TOKEN go to your account settings and generate a Personal Acess Token. When you're done with that, go to the repository housing your package, click on the settings tab, in the sidebar, click on the "Secrets and variables" dropdown, then click on "Actions"

Repository settings on GitHub showing various options

You should be on this screen by now.

Environment secret settings tab in a GitHub repository

When you're here, click on the green button to create a new repository secret and paste the PAT (Personal Access Token) you generated previously into the textaraea.

Make sure the name matches what you've set in the workflow file and vice versa.

To create an NPM_TOKEN log in to your npm account, if you have one, or create one by visiting npmjs.com/signup.

Click on "Access Token" from your avatar dropdown

Npmjs dot com dashboard

You should be here by now. Click on "Generate New Token", it should open a dropdown menu with two options.

For the new security features npm released, it is recommended that you select the "Granular Access Token"

Access Token UI on npm dashboard

Provide the required details in the next screen. For more info about what to fill in or stuff about NPM access tokens, see this

Testing

When you're done with creating your tokens, make sure you add them as environment secrets in the settings tab of your repository.

Now that you're done with these processes, try creating a pull request or pushing directly to your default branch, you'll find out that a new tag has been generated in the repo.

You can click on the tags element.

metadata repository on GitHub

It'll take you to this UI.

Repository tags

Click on your most recent tag. It'll take you to a new screen where you can "generate a release note" from the tag.

This is what a typical release note would look like when it is generated. I made some tweaks though.

Release note from the metadata npm package repository

Wrapping up.

Automating repeated processes can be fun, but no one tells you about the stress you'd have to go through to get them working sometimes.

It is a good investment if you get it right and worth the stress.

To see another example of automating workflows, you can take a look at how I moved a Husky pre-commit hook into GitHub Actions which in turn saved a lot of time while working in dev mode, it also covers a bit on how to deploy on Vercel with GitHub Actions.

Top comments (0)