NPM release automation

Philippe Modard
Jan 30, 2018 · 4 min read

Do you maintain a NPM package? Or are you just curious about what you can do with Google Cloud Container Builder (GCB)? In this post, I’m going to show you how to streamline your NPM publish process using GCB.

GCB is a service that executes your builds on Google Cloud Platform’s infrastructure. It executes your build as a series of build steps, where each build step is run in a Docker container. A build step can do anything that can be done from a container irrespective of the environment.

When you want to publish a new version of your NPM package, you probably follow the following steps from your trusted branch:

npm test
npm version patch
git push --tags
npm publish

As a developer, it’s annoying to have to publish your package to two different places for each change. Let’s automate the NPM publish so that we only have to create a new git tag.

GCB triggers

GCB supports triggers from Github that you can use to trigger a new build when a branch is modified or a tag is created.

Let’s use this feature so that when a new tag is created, we publish the new code to NPM.

In the Google Cloud Platform console, go to Container Registry > Build triggers. You may need to first enable the API if you see the corresponding message.

Let’s enter all the information needed to create the trigger.

The important part is to choose the Tag option for Trigger type. Choosing this option will trigger a build when a new tag is created in your repository.

The build configuration used is going to live in a cloudbuild.yaml file along with your code. Specify the path and click Create trigger.

Now, you’ve created a trigger!

Build configuration

Before creating a new tag to trigger on, let’s create the build configuration. As mentioned earlier, a build consists of a series of build steps that you run in a Docker container. You can create your own builders (a Docker image used to run a step) or you can use the official ones.

In our case, we only need the NPM tool, so let’s use the official NPM builder.

steps:
- name: 'gcr.io/cloud-builders/npm'
args: ['install']
- name: 'gcr.io/cloud-builders/npm'
args: ['test']
- name: 'gcr.io/cloud-builders/npm'
args: ['publish']

Wait, you don’t use Docker? I thought GCB was aimed for Docker builds? GCB uses Docker to run the steps you define, but you can run any script and produce any type of output, not limited to Docker images.

NPM authentication

In order to be able to publish to NPM (last step), the build needs your authorization key. We are going to store it in Google Cloud Key Management Service.

First, if you haven’t done it yet, enable this API in your GCP project.

Then, let’s create a keyring and the key:

gcloud kms keyrings create my-keyring --location=globalgcloud kms keys create npm-key \
--location=global \
--keyring=my-keyring \
--purpose=encryption

Now, let’s encrypt the ~/.npmrc file:

gcloud kms encrypt \
--plaintext-file=$HOME/.npmrc \
--ciphertext-file=npmrc.enc \
--location=global \
--keyring=my-keyring \
--key=npm-key

Add the encrypted file npmrc.enc to the source that will be decrypted in the build. You need to grant the Container Builder service account permission to access and decrypt the CryptoKey during the build, see this documentation for more information.

Now, let’s modify the build configuration to decrypt and use the .npmrc file.

steps:
- name: 'gcr.io/cloud-builders/gcloud'
args:
- kms
- decrypt
- --ciphertext-file=npmrc.enc
- --plaintext-file=/root/.npmrc
- --location=global
- --keyring=my-keyring
- --key=npm-key
volumes:
- name: 'home'
path: /root/
- name: 'gcr.io/cloud-builders/npm'
args: ['install']
- name: 'gcr.io/cloud-builders/npm'
args: ['test']
- name: 'gcr.io/cloud-builders/npm'
args: ['publish']
env:
- HOME=/root/
volumes:
- name: 'home'
path: /root/

We use a docker volume to store the NPM authentication so the file doesn’t end up in the /workspace directory along with the source.

Wrapping up

In order to facilitate the process a bit more, I added a postversion script in the package.json that will push the new tags to Github when a new version is created with the NPM command. So the only command needed to publish the new version of your package is now:

npm version <VERSION>
Successful build

Conclusions

This setup provides a safe environment to test, build and publish the new version of your NPM package. It also removes the need for NPM access; anybody who has write access to the Github repository can create a new tag, which will trigger this build and release the new code to NPM.

How much does it cost? GCB is currently free up to 120 minutes/day, which is likely enough for this purpose. Google Cloud KMS is not free, but if you have fewer than 10,000 operations a month, it will cost you $0.09/month.

What else could we do? We could also add more steps to run the tests for different versions of Node.js, we could publish the status of the build on our Slack channel, we could create another trigger for master branch to only run the tests — there are a lot of possibilities to streamline your workflow.

Feel free to contact me on Twitter with any comments or questions.

Philippe Modard

Written by

Aerospace engineer, converted to software. @google. #golang, #nodejs. Traveller. Musician.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade