Search code examples
node.jsnpmcontinuous-integrationartifactory

How to bypass "resolved" url on "npm clean-install" when having multiple private registries?


How can we bypass "resolved" url when running npm clean-install using (node 16, npm >=7)?

Problem: We have an internal private registry so package-lock.json will refer to the internal url. When we then try running builds in GitHub/Azure it tries to resolve the private registry from package-lock.json instead of our "build registry", which it can't, and times out after 5 minutes.

I thought that "npm ci" was supposed to fall back to the registries in .npmrc and then to registry.npmjs.org if it couldn't fetch from the URL in package-lock.json. It just sits there (in silence, no logs) and timeouts. It used to ignore the resolved field in npm <7 and then it got progressively stricter for each npm version.

Right now I only see three solutions:

  1. Rebuild all package-lock.json in our project with --omit-package-lock-resolve flag. But that's not going to be consistent over time...
  2. Have our build scripts pre-process the package-lock.json and set the resolved field to empty.
  3. Don't use clean-install, making builds non-reproducible and less compliant.

Why: This is a common enterprise standard way of doing things, but it feels like a lot of things in the node ecosystem doesn't take these real-life organizational needs into account. Where did this obsession with hardcoded URLs all over the place came from? In large organization, these things are usually injected by operations/internal IT, behind proxies, using internal "office URLs" and similar.

Here is an example of the same issue: https://github.com/npm/cli/issues/2004


Solution

  • Solved by nuking all resolved entries. Not sure this is "good practice" but it works.

    jq 'walk(if type == "object" then with_entries(select(.key | test("resolved") | not)) else . end)' \
    package-lock.json > package-lock.nuke.json \
    && cp package-lock.nuke.json package-lock.json