HomeAboutBlogPortfolio

Publishing to npm using GitHub Actions

June 28, 2020 - 4 min read

GitHub Actions present a great way to automate tasks. In this case, we are setting up a way to update a React component library, zati, on the npm registry. The end resulting behavior is the following:

  • We create a new release on GitHub
  • Our workflow is triggered
  • A new commit with the release number is created
  • The package is published to npm

The workflow file

Workflow files are .yml files that live in the .github/workflows folder. This is the complete workflow file which we will inspect step-by-step.

name: Publish to npm

on:
  release:
    types: [published]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: actions/setup-node@v1
        with:
          node-version: 12
          registry-url: https://registry.npmjs.org/
      - run: yarn install
      - run: yarn build

      - name: Get version number from release
        run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//}
        id: tag

      - name: Create commit with version number
        run: |
          git config user.name $GITHUB_ACTOR
          git config user.email gh-actions-${GITHUB_ACTOR}@github.com
          npm version ${RELEASE_VERSION}
        env:
          RELEASE_VERSION: ${{ steps.tag.outputs.version }}

      - name: Run publish command
        run: yarn publish --new-version ${RELEASE_VERSION}
        env:
          RELEASE_VERSION: ${{ steps.tag.outputs.version }}
          NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}

      - name: Push version commit to GitHub
        run: |
          git remote add gh-origin https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
          git push gh-origin HEAD:master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

The trigger

This tells GitHub we want to run this action when a release is published. Note there are many triggers you can substitute, such as push events to master. Reference more triggers here.

on:
  release:
    types: [published]

Setup environment

The first block of steps gets access to our repository files, sets up a node environment, and builds our project. The yarn build step can be subsituted with your eqvuialent command to prepare your package.

- uses: actions/checkout@v1
- uses: actions/setup-node@v1
  with:
    node-version: 12
    registry-url: https://registry.npmjs.org/
- run: yarn install
- run: yarn build

Get version number

When we create a release on GitHub we enter a version number and we want to re-use that number to match the version number with our npm package. To get this number we use the following command with the set-output flag which lets us reference this in other steps as an environment variable.

- name: Get version number from release
  run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//}
  id: tag

Create commit

This step allows us to make a commit in our repository, with the npm version command updating our package.json version and creating a commit with the version number. The $GITHUB_ACTOR variable comes for free. We are also using the version number we saved as a variable above.

- name: Create commit with version number
  run: |
    git config user.name $GITHUB_ACTOR
    git config user.email gh-actions-${GITHUB_ACTOR}@github.com
    npm version ${RELEASE_VERSION}
  env:
    RELEASE_VERSION: ${{ steps.tag.outputs.version }}

Configure npm secret

We need to create a secret in our GitHub repository using a token generated from npm. This will authenticate us with npm when we reference the token in the next step. To get a token from npm, follow these steps:

  • Login to npmjs.com
  • Click your profile icon and choose "Auth Tokens"
  • Click "Create New Token"

Next, we add this to our repository's secrets:

  • In your GitHub repository, click "Settings"
  • Go to the "Secrets" section and click "New Secret"
  • Enter NODE_AUTH_TOKEN as the key
  • Use the generated token from npm as the value

Publish to npm

This command will push our updated code to the npm registry. Using the --new-version flag lets us specify the exact version number to set. We are using the RELEASE_VERSION variable similar to above, as well as the NODE_AUTH_TOKEN secret we set up in the previous step.

- name: Run publish command
  run: yarn publish --new-version ${RELEASE_VERSION}
  env:
    RELEASE_VERSION: ${{ steps.tag.outputs.version }}
    NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}

Push commit to GitHub

We made a new commit with the version number in a previous step, but we still need to push that update to our repository. Doing this as a last step makes sure this step will only run if the publishing to npm succeeds. The secret GITHUB_TOKEN, as well as all three variables in the git url are built-in.

- name: Push version commit to GitHub
  run: |
    git remote add gh-origin https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
    git push gh-origin HEAD:master
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Further reading

Another option to consider for automating releases, is semantic-release. This is even more convenient because it generates release numbers and changelogs automatically. For a walkthrough of setting this up with GitHub Actions, take a look at this guide.

GitHubLinkedInYouTube
Boston, MA 2021