7

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.

Tobi
  • 1,492
  • 1
  • 13
  • 20

1 Answers1

2

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
DustInComp
  • 1,742
  • 8
  • 18
  • I saw this solution before, but I found it strange. What's the point of a project-level configuration if you overwrite it in CI again? – Tobi Feb 18 '21 at 11:14
  • I haven't had the need for it yet. Since npm has its own storage for auth tokens, moving them into env variables just so you can package your ci config just seems like a hassle. – DustInComp Feb 18 '21 at 13:44
  • This solution is unfortunately insufficient as it can't be extended to work in all CI situations. For example, Netlify and Cloudflare Pages deployments don't appear to have the ability to define anything similar. From my perspective the only valid solution currently is having each user define the `NPM_TOKEN` env variable... which sucks... – Trappar Dec 05 '22 at 20:39