Continuously Deploying an NPM Package with GitLab CI/CD

Setting up continuous deployment is important to me, even when publishing is as simple as it is on npm. The official GitLab documentation, though, is a little more than I need and geared toward their own npm repository, so I'd like to gather the information I need here in a brief article.

Generate and store an authentication token

The npm team has made this straightforward.

Generating the token in npm

  1. Go to npmjs.com and log in if you haven't already.

  2. Click on your profile picture at the top right.

  3. Select the fifth item, "Access Tokens."

  4. Click "Generate New Token" on the top right of the page.

  5. Select the middle option, "automation" for the right security settings.

  6. Click "Generate Token."

  7. Copy the token to your clipboard.

Storing the token in GitLab

  1. Log into GitLab and open the project you intend to automate.

  2. Select "Settings" at the bottom of the menu on the left. This will open a submenu.

  3. Select "CI/CD."

  4. Find the "Variables" section of the CI/CD menu and click "expand" on the right.

  5. Click the green "Add variable" button at the bottom.

  6. Fill in the "Key" text box with "NPM_TOKEN".

  7. Fill in the "Value" box with the token you copied from earlier.

  8. Make sure the "Type" is set to "variable" instead of "file."

  9. Make sure both checkboxes are checked to protect and mask the variable.

A word on security

Clearly, an authentication token, especially one that controls deployment to production, is very sensitive information, so it's worthwhile to familiarize oneself with the protections GitLab offers.

Masking an environment variable protects the variable from being seen in the console output. It is easy to imagine a scenario where an error message (or just a simple scripting mistake) could lead to this kind of information being printed to the console, and once the toothpaste is out of the tube and on the internet, there's no putting it back in--you have to revoke that token and generate a new one. Masking prevents this easy-to-make security mistake.

Protecting an environment variable is a kind of access control. A protected environment variable can only be used in protected branches or on protected tags, and it can't be seen by all contributors.

A critically sensitive authentication token like an NPM publish token should be both protected and masked.

Set up the pipeline with your .gitlab.yml

This is the easy part. Copy the following text and save it to a file called .gitlab.yml

.gitlab.yml

image: node:latest
stages:
  - deploy

deploy:
  stage: deploy
  script:
    - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc
    - npm publish

Just to break it down: This file grabs an image that has node installed. It deploys by creating a file called .npmrc that defines where our registry is and what our authentication token is based on the environment variable NPM_TOKEN we created earlier. With that file in place, npm publish will run.

Celebrate

Update your package.json with a fresh version number to make sure the push succeeds, then commit and push the new .gitlab.yml and the edited package.json. The pipeline will succeed every time you increment the version number.