Releasing a package on the npm registry should be boring. In this blog post, we describe how we set up Travis CI to release npm packages on each git tag.

Automated npm releases with Travis CI

At TailorDev, we like to automate many important steps required to build software. One of these steps is to release the final, production-ready, bundle of an application, also known as artifact or package. Today, we focus on the JavaScript world and we describe how to automate the release process of packages on the npm registry without any effort.

First thing first, npm has introduced two-factor authentication (2FA for short) in 2017 and that was an excellent idea until we discovered that it was “all or nothing” :confused:. Indeed, npm 2FA relies on One Time Passwords to protect everything related to your account and automating that would defeat the purpose of enabling 2FA.

But, why is it so important? I am glad you ask! Because we need an API token in the sequel, and it is currently not possible to generate and use tokens without triggering the 2FA mechanism. In other words, with 2FA enabled, it is nearly impossible to automate the npm release process, “nearly” because npm implements two levels of authentication: auth-only and auth-and-writes. By restricting the 2FA usage to auth-only, it becomes possible to use API tokens in an automated fashion, but it is less secure. We really hope npm will allow to generate auth tokens designed for automated tasks in the near future, meanwhile:

$ npm profile enable-2fa auth-only

Once your account has 2FA enabled for auth-only usage (which is better than not having 2FA enabled by the way), let’s create a token:

$ npm token create

+----------------+--------------------------------------+
| token          | a73c9572-f1b9-8983-983d-ba3ac3cc913d |
+----------------+--------------------------------------+
| cidr_whitelist |                                      |
+----------------+--------------------------------------+
| readonly       | false                                |
+----------------+--------------------------------------+
| created        | 2017-10-02T07:52:24.838Z             |
+----------------+--------------------------------------+

This token will be used by Travis CI to authenticate on your behalf. We can either encrypt this token as an environment variable using the Travis CLI or define a variable in Travis CI repository settings, which we find to be more convenient. Declare two secret environment variables NPM_EMAIL and NPM_TOKEN:

Travis CI settings

Now, the most important part is to create a job to actually release the npm package. We decided to leverage the build stages (beta) feature combined to Travis CI recommended way to release npm packages. For the record, we want to release the package only once per build, no matter the existing build matrix and we also want to release npm packages on git tags to be consistent between the npm releases and the GitHub releases.

We start with a standard .travis.yml file for JavaScript projects, where the code is linted and tested for both Node 8 and 9, and yarn is used as package manager:

language: node_js
node_js:
  - "8"
  - "9"

cache: yarn

install: yarn
script:
  - yarn lint
  - yarn test

Standard Travis CI output with two JavaScript
jobs

We can now configure our “deploy” job by adding the configuration below to our previous .travis.yml file:

jobs:
  include:
    - stage: npm release
      if: tag IS present
      node_js: "8"
      script: yarn compile
      before_deploy:
        - cd dist
      deploy:
        provider: npm
        email: "$NPM_EMAIL"
        api_key: "$NPM_TOKEN"
        skip_cleanup: true
        on:
          tags: true

Let’s break it line by line. First, we “include” a new stage npm release if and only if tag IS present, which means the build has been triggered by a git tag. We select node 8 (our production version) and we execute yarn compile to build our package. This script creates a dist/ folder containing our package files ready to be published on the npm registry. Last but not the least, we invoke the Travis CI deploy command to actually publish the package on the npm registry (and we restrict this command to git tags only as an extra protection layer).

Note: skip_cleanup must be set to true to prevent Travis CI to clean up any additional files and changes you made before the release.

Travis CI with build stages for
JavaScript

How cool is this? :sunglasses:

Bonus: npm releases like a pro

In order to create a new release, we use npm version (it is built-in in npm :rocket:). Assuming we are at version 0.3.2 and we want to release 0.3.3. Locally, on the master branch, we run the following command:

$ npm version patch

This command performs the following tasks:

  1. bump (update) the version number in package.json
  2. create a new commit
  3. create a git tag

We can use npm version minor to release 0.4.0 from 0.3.1 (it bumps the second number and resets the last number). We can also use npm version major to release 1.0.0 from 0.3.1.

Once done with the npm version command, you can just run git push origin master --tag and wait a bit until your package is published on the npm registry :tada: