Install NPM Private Packages in CI/CD with GitHub Actions

Deploying a project using NPM private registry with GitHub Actions.

Continuous Integration and Deployment are now a part of every project lifecycle from the development to delivery. CI & CD are the solutions to problems like “integration hell” in which integrating new code can result in various bugs and issues. In this blog post, we will be discussing more about deploying a project using NPM private registry with GitHub Actions.

What is an NPM private registry?

NPM private registries are generally used by enterprises to store their own private javascript code and can semversion them similar to every npm package. NPM private registry also has the features of the scoped registry. There are a lot of third-party services that provide the hosted npm private registry to seamlessly use them in our development/production environment. There are some of the open-source projects that provide self-hosted npm registries which can be public/private like Verdaccio.

As JavaScript developers, we might think NPM is the only registry for shared packaged code but it is far from being true.

For example, when sharing reusable components to Bit.dev we are publishing to Bit’s registry — not to NPM’s. (Even when using NPM commands to install shared components from a Bit component collection).

Example: browsing through components published on Bit’s registry

Example: publishing reusable components from a React project to Bit’s registry

Issues with installing NPM packages on CI

There are some issues that we face while installing npm packages on CI using npm private/self-hosted public registries.

The default registry that npm understands in the npm registry and installs packages from it so while installing npm packages from private/self-hosted public registries, we need to define the registry. If the package is private, we need to pass an authentication token to the CI so it can be installed on our CI or deployment server.

Both of these issues will be resolved by using .npmrc (NPM Runtime Configuration) file.

How to Install NPM packages On CI

As we have discussed above the problems/issues we are having while installing NPM packages on CI. Suppose we are trying to install a public NPM package on our CI using our self-hosted npm registry.

There are multiple ways to resolve this:

We can pass the registry to NPM CLI while installing a package like this.

2. Best practice to solve this issue is to use the .npmrc file in which we can define our registry. We can define our npmrc file globally, per-project, per-user as well. It depends on our requirements. We are defining a per-project config ( path/to/project/.npmrc ) —

As we can see that we have defined our self-hosted registry (http://myregistry.local) in line 2 and also set @myregistry scoped packages to use my self-hosted registry in line 1. Similarly, we can configure this for any scoped packages.

Suppose we have created another local registry on our system which is running at http://localhost:4180 and created @abc scoped packages. So to install those packages, we can define our .npmrc file as shown below —

How to install private NPM packages on CI

We know how to install any public npm packages from any self-hosted registry on any CI or deployment server but what about private npm packages. Private npm packages always require some token to authenticate our request of installing/fetching packages.

Every private npm registries provide some kind of authentication with which a npm auth token is generated which we can find in our .npmrc file. For example, Run npm login and complete the login procedure by providing a username, password and our public email address. Now, open ~/.npmrc file, we can see something similar to this —

//registry.npmjs.org/:_authToken=abcdef-xxxxx-xxxx-xxxx-xyz

#always-auth=true

NOTE: This is for our npm default registry. Every self-hosted npm registries have their different method of setting auth token in .npmrc file.

Use this auth token to install the private npm packages on any CI/CD server. Pass this token in .npmrc file to get authenticated for private registry.

It is the best practice to use a separate user for such deployments (npm-ci@company.com) so that we can track as well as the token won’t get reset. There are other reasons for not using company employees token as if the employee left the company, the data associated with the company also get deleted so it is always recommended to use separate user for such CI & CD tasks or any automation tasks.

CI using GitHub Actions

We know what are the issues while installing npm packages on CI and how to fix them. Let’s integrate our project with GitHub Actions for CI/CD.

Create a project directory npm-github-actions and run npm init —

mkdir npm-github-actions

cd npm-github-actions npm init -y

Now, open package.json file and add some npm packages and private npm packages as dependencies or we can directly install them locally.

npm i @myregistry/helloworld vue

Our file will look something like this —

Let’s create a .npmrc file to install packages from @myregistry scoped registry and also add the token for installing private components if any. Also, export NPM_AUTH_TOKEN as an environment variable for local installation as local .npmrc file has more priority than global ~/.npmrc file.

NOTE: We can use ngrok to create a public HTTPS/HTTP URL for our private registry running on our local development machine. In this blog, I will be using ngrok to demonstrate it in GitHub Actions.

Let’s use ngrok to create a public HTTP URL and replace the local registry URL with our ngrok public HTTP URL in .npmrc file.

We will pass this NPM_AUTH_TOKEN from GitHub Secrets so that this auth token wouldn't be exposed directly in our GitHub repo else anyone who has the token can access our private packages.

Define Our GitHub Action Workflows

GitHub Actions read yaml files in the .github/workflows directory in our GitHub repo. Let's create a directory and workflow file named nodejs.yml inside our project npm-github-actions

mkdir -p .github/workflows

touch .github/workflows/nodejs.yml

we can also set up GitHub Actions workflow by going to github actions tab in our GitHub repository and select accordingly to our project. They have already provided basic yml configuration for different languages (Node, Python, Ruby etc)

Let’s add our workflow in nodejs.yml file.

name: NPM GitHub Actions



on: [push]



jobs:

build:



runs-on: ubuntu-latest



strategy:

matrix:

node-version: [10.x, 12.x]



steps:

- uses: actions/checkout@v1

- name: Use Node.js ${{ matrix.node-version }}

uses: actions/setup-node@v1

with:

node-version: ${{ matrix.node-version }}

- name: Installing Tree

run: sudo apt-get install tree

- name: Showing Tree

run: tree -L 4

- name: npm install

run: npm install

env:

NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}

- name: Showing Tree

run: tree -L 4

As we can see that we are passing NPM_AUTH_TOKEN as an environment variable to our workflow file in npm install step.

- name: npm install

run: npm install

env:

NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}

Let’s add this token in GitHub Secrets. Click on Settings>Secrets in the GitHub Repo as shown in the image below —

GitHub Secrets

Now click on “Add a new Secret” and add the Name of the key i.e NPM_AUTH_TOKEN and add the corresponding value which we get from our global ~/.npmrc file.

Now, copy the value against _authToken for our local registry and add it as the value for NPM_AUTH_TOKEN key in GitHub Secrets.

Let’s push our code in the GitHub repo and see the logs under GitHub Actions Tab.

As we can see, all the builds are passed successfully. We can also see that I have used the tree command to describe the directory structure before and after the installation of an npm package.

Conclusion

With this, I would like to conclude this article “Install NPM private packages in CI/CD With GitHub Actions”. It is not only for GitHub Actions as I have described how we can install any npm private packages in any CI/CD environment using npmrc file. You can find the code on my GitHub repo ankitjain28may/npm-github-actions. In my next article, I will write about deploying npm private registry using Docker.

Feel free to comment and ask me anything. You can follow me on Twitter and Medium. Thanks for reading! 👍

Learn More