Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] publishConfig.registry in package.json should take higher priority than project level .npmrc #7043

Closed
2 tasks done
JounQin opened this issue Dec 1, 2023 · 10 comments
Closed
2 tasks done
Labels
Bug thing that needs fixing Needs Triage needs review for next steps Release 9.x work is associated with a specific npm 9 release

Comments

@JounQin
Copy link

JounQin commented Dec 1, 2023

Is there an existing issue for this?

  • I have searched the existing issues

This issue exists in the latest npm version

  • I am using the latest npm

Current Behavior

For example, If I have publishConfig.registry = registryA in @scope/foo's package.json, and $cwd/.npmrc with @scope:registry=registryB, when I run npm publish on @scope/foo, I'd expect to publish it to registryA instead of registryB.

However, the current behavior is unexpected to publish on registryB.

Expected Behavior

As title

Steps To Reproduce

As described above

Environment

  • npm: 9.8.1
  • Node.js: v18.18.2
  • OS Name: Darwin arm64
  • System Model Name: macOS 14.1.2
  • npm config:
; "user" config from /Users/JounQin/.npmrc

//internal-mirrors.alauda.cn/repository/npm/:_authToken = (protected) 
//registry.npmjs.org/:_authToken = (protected) 

; "project" config from /Users/JounQin/Workspaces/Alauda/octopus/.npmrc

@alauda/dp-cli:registry = "https://registry.npmjs.org/"
@alauda/dp-dynamic-plugin-backend-core:registry = "https://registry.npmjs.org/"
@alauda/dp-dynamic-plugin-frontend-core:registry = "https://registry.npmjs.org/"
@alauda:registry = "https://build-nexus.alauda.cn/repository/npm/"

; node bin location = /Users/JounQin/Library/Application Support/fnm/node-versions/v18.18.2/installation/bin/node
; node version = v18.18.2
; npm local prefix = /Users/JounQin/Workspaces/Alauda/octopus
; npm version = 9.8.1
; cwd = /Users/JounQin/Workspaces/Alauda/octopus
; HOME = /Users/JounQin
; Run `npm config ls -l` to show all defaults.
@JounQin JounQin added Bug thing that needs fixing Needs Triage needs review for next steps Release 9.x work is associated with a specific npm 9 release labels Dec 1, 2023
@JounQin
Copy link
Author

JounQin commented Dec 1, 2023

Also,

@alauda/dp-cli:registry = "https://registry.npmjs.org/"

This does not work to me neither.

@wraithgar
Copy link
Member

The project level .npmrc and publishConfig in the package.json are technically of equal priority. They are both "project" level configurations. Having both is not recommended, npm has to pick one over the other and there is no "correct" choice. npm prioritizes the file because it is historically something that folks can have in a project that is overriding things in the project itself. The current way of doing things is intentional and the best attempt of parsing an conflicting setup.

@wraithgar wraithgar closed this as not planned Won't fix, can't repro, duplicate, stale Dec 4, 2023
@JounQin
Copy link
Author

JounQin commented Dec 4, 2023

So no way to publish with correct registry without --registry option?

@JounQin
Copy link
Author

JounQin commented Dec 5, 2023

The project level .npmrc and publishConfig in the package.json are technically of equal priority.

@wraithgar I still don't understand this statement, other package manager like yarn berry prefers publishConfig.registry over project level .yarnrc.yml, having both configs is absolutely valid usage for multi npm registries IMO. Your statement is just giving up trying to fix the problem which is very disappointing.

https://yarnpkg.com/configuration/yarnrc#npmPublishRegistry

@Kenneth-Sills
Copy link

Kenneth-Sills commented Jul 25, 2024

So no way to publish with correct registry without --registry option?

It's a bit worse than that, --registry is ignored if either .npmrc or package.json contain registries that match the package's scope. It's not possible to provide a scoped registry via CLI args AFAIK, and the registry with the highest specificity to the package's scope always wins first. Example:

Click to Open

Assuming a package called @demo/package...

Scopeless

// package.json
{
    "publishConfig": {
        "registry": "https://pkg.fake.io"
    }
}
# .npmrc
registry=https://rc.fake.io
# Command
npm publish $(pwd) --registry "https://cli.fake.io"

# Attempts to publish to 
# https://cli.fake.io

Partially Scoped

// package.json
{
    "publishConfig": {
        "registry": "https://pkg.fake.io"
    }
}
# .npmrc
@demo:registry=https://rc.fake.io
# Command
npm publish $(pwd) --registry "https://cli.fake.io"

# Attempts to publish to 
# https://rc.fake.io

All Scoped

// package.json
{
    "publishConfig": {
        "@demo:registry": "https://pkg.fake.io"
    }
}
# .npmrc
@demo:registry=https://rc.fake.io
# Command
npm publish $(pwd) --registry "https://cli.fake.io"

# Attempts to publish to 
# https://pkg.fake.io

Note that package.json does consistently take precedence over .npmrc as long as their scopes are identical. See the implementation, where it's the last thing flattened into the configs before publishing.

@wraithgar Could you please re-open this ticket and consider canonizing this behavior? This priority is actually critically important for anyone using Gitlab's NPM package registry, since you need to be able to use .npmrc for installing dependencies from your scoped registry and then override that inside package.jsons publishConfig for publishing dependencies... Gitlab requires you to install from the instance-wide endpoint and publish via a project-specific one.

Kenneth-Sills added a commit to Kenneth-Sills/semantic-release-npm that referenced this issue Jul 30, 2024
This stops a niche issue when using Gitlab registries, where setting the
`.npmrc` to pull packages from the instance-wide registry while also setting
the `package.json:publishConfig` to push to the project-local registry
for a given `@scope` would pass the incorrect `--registry` flag to `npm publish`
as well as associate the `NPM_TOKEN` with the wrong URL in the
generated userconfig file.

This DOES NOT resolve semantic-release#219. So `--registry` is still technically ignored for
scoped packages. See
[npm/cli#7043](npm/cli#7043)
for more details on that.

I made sure not to affect the priority of other resolutions to avoid any
breaking changes. An additional test has been added for this specific
case.
@thierrymichel
Copy link

Any news on this ?

I need to publish my package in a Gitlab private registry at a project level.

I put this in the package.json for publish only.

"publishConfig": {
    "@private/registry": "https://registry-at-project-level"
  },

but this package use other packages at a group level (same private registry, sibling project).

So I need .npmrc to be able to install packages…

@private:registry=https://registry-at-group-level

This does not work.

Even if I use --registry argument with the CLI 😭

@Kenneth-Sills
Copy link

Kenneth-Sills commented Sep 10, 2024

@thierrymichel You should be able to get this to work with a small adjustment! The package.json should have a colon separator between the scope and the registry keyword, not a forward slash:

"publishConfig": {
    "@private:registry": "https://registry-at-project-level"
  },

However, this won't work with automated release tools like Semantic Release, which don't respect scoped registries.

What I ended up doing was setting up a CI component that defines release-related jobs that all override the committed .npmrc after dependencies are installed:

npm config set -L project @private:registry ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/npm

@thierrymichel
Copy link

@Kenneth-Sills Thanks a lot !!!
I don't use semantic-release but release-it and it worked like a charm. 🙏

@JounQin
Copy link
Author

JounQin commented Sep 24, 2024

@Kenneth-Sills I got another issue with npm info now, is that possible to tell npm info use different registry without cli option --@private:registry=?

@Kenneth-Sills
Copy link

I got another issue with npm info now, is that possible to tell npm info use different registry without cli option --@private:registry=?

Yeah! npm view never reads the value of publishConfig.*registry, so you need to add it to .npmrc via npm config set -L project @private:registry $URI. So the way my projects are set up (we use Gitlab for VCS hosting):

  • .npmrc has the group-level registry API endpoint for @scope:registry
  • package.json:publishConfig['@scope:registry'] points to the project-level registry API endpoint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug thing that needs fixing Needs Triage needs review for next steps Release 9.x work is associated with a specific npm 9 release
Projects
None yet
Development

No branches or pull requests

4 participants