Search code examples
npmnpm-registry

What's the best practice to setup private npm registry authentication for local development and CI?


I wonder if there is a general best practice to set up private npm registry authentication for local development that also works in CI (or vice-versa).

Here is my current understanding:

For local development: Run npm login which will create an access token, create an ~/.npmrc file, and write the access token to that file as follows:

@my-scope:registry=https://registry.npmjs.org/
//registry.npmjs.org/:_authToken=my-auth-token

In my project, I have this .npmrc file (next to the package.json):

@my-scope:registry=https://registry.npmjs.org/
//registry.npmjs.org/:always-auth=true

This seems to work great. I can install my private packages because npm seems to pick up the user-level authentication setting for the registry.

For CI: The NPM docs suggest adding the following to the project-level .npmrc to inject authentication in CI:

//registry.npmjs.org/:_authToken=${NPM_TOKEN}

Unfortunately, this overrides the user-level config on my machine. .npmrc files have the following precedence (highest to lowest): project-level, user-level, global, npm built-in. The npm CLI now tries to authenticate using the NPM_TOKEN environment variable which obviously does not work unless I export it explicitly on my local machine.

Maybe I am missing something obvious. If not, I am curious if there is any common best practice to deal with this? Asking each employee to export the access token on their machine when it is already configured in the user-level .npmrc does not seem like a great solution.

Alternatively, one could simply not bother with the user-level configuration (or npm login) and directly export the access token as NPM_TOKEN on each employee's local machine. But like mentioned, I do not find that a great solution. I imagine a standards solution (like the user-level config file) where each employee can set up the company's private registry.


Solution

  • You could keep the .npmrc that works for development and monkey patch it in CI by overwriting it as part of the run:

    // your-ci.yaml
    steps:
      - env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
      - run: |
          echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
          npm install