Make the npm project-level endpoint work with all npm commands
Problem to solve
GitLab's package API is structure slightly differently than NPM's API, and this causes issues when using the npm
command-line tool to publish NPM packages to GitLab's NPM registry.
In our NPM registry docs, we recommend setting up a .npmrc
with a registry
entry like this:
@nfriend:registry=https://gitlab.com/api/v4/packages/npm/
This allows some npm
commands to work, for example npm view
:
❯ npm view @nfriend/npm-test-project version
1.0.2
However, this does not allow commands like npm publish
to work:
❯ npm publish
npm notice
npm notice 📦 @nfriend/npm-test-project@1.0.2
npm notice === Tarball Contents ===
npm notice 137B index.js
npm notice 273B package.json
npm notice 40B README.md
npm notice 1.2kB .gitlab-ci.yml
npm notice === Tarball Details ===
npm notice name: @nfriend/npm-test-project
npm notice version: 1.0.2
npm notice package size: 955 B
npm notice unpacked size: 1.7 kB
npm notice shasum: 359557fb53f1f29f696b329d05d8244fd94b7c29
npm notice integrity: sha512-fEns1JvpptkWl[...]ypIIp11jAXDCg==
npm notice total files: 4
npm notice
npm ERR! code E404
npm ERR! 404 Not Found - PUT https://gitlab.com/api/v4/packages/npm/@nfriend%2fnpm-test-project - 404 Not Found
npm ERR! 404
npm ERR! 404 '@nfriend/npm-test-project@1.0.2' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/nathanfriend/.npm/_logs/2020-06-09T19_06_43_137Z-debug.log
Notice in the logs above that npm
is attempting to make a PUT request to https://gitlab.com/api/v4/packages/npm/@nfriend%2fnpm-test-project
, which isn't supported by GitLab - it expects packages to be published to a project specific endpoint: https://gitlab.com/api/v4/projects/18806182/packages/npm/@nfriend%2fnpm-test-project
.
In order to get publish
to work, the registry
setting in .npmrc
can be updated to point to the project-specific endpoint:
@nfriend:registry=https://gitlab.com/api/v4/projects/18806182/packages/npm/
With this config, npm publish
succeeds:
❯ npm publish
npm notice
npm notice 📦 @nfriend/npm-test-project@1.0.3
npm notice === Tarball Contents ===
npm notice 137B index.js
npm notice 273B package.json
npm notice 40B README.md
npm notice 1.2kB .gitlab-ci.yml
npm notice === Tarball Details ===
npm notice name: @nfriend/npm-test-project
npm notice version: 1.0.3
npm notice package size: 955 B
npm notice unpacked size: 1.7 kB
npm notice shasum: 3a29ceaa6960ef1b2c326df6ac41eabd98288718
npm notice integrity: sha512-IDFoxBcQawjBz[...]nKS+Euc+znDdg==
npm notice total files: 4
npm notice
+ @nfriend/npm-test-project@1.0.3
... but npm view
fails:
❯ npm view @nfriend/npm-test-project version
npm ERR! code E404
npm ERR! 404 '@nfriend/npm-test-project' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it
npm ERR! 404 (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
npm ERR! 404
npm ERR! 404 '@nfriend/npm-test-project@latest' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/nathanfriend/.npm/_logs/2020-06-09T19_10_49_642Z-debug.log
What's the workaround?
We work around this by asking users to specify a publishConfig
in their package.json
:
Before you will be able to upload a package, you need to specify the registry for NPM. To do this, add the following section to the bottom of
package.json
:"publishConfig": { "@foo:registry":"https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/" }
Note the https as this won't work with http (added this after ZD Ticket (Internal)
This allows the npm
command-line tool to use the "generic" endpoint (i.e. https://gitlab.com/api/v4/packages/npm/
) for all commands except publish
, which will instead use the endpoint specified in publishConfig
.
This is an okay workaround, but it has a few downsides:
- It adds extra friction to getting set up to publish packages to GitLab's NPM registry
- It makes it harder to automate. For example, environment variables can be replaced inside a
.npmrc
(which we recommend doing in our docs), but this isn't possible inpackage.json
. Because of this, users have to hard-code the GitLab project ID intopackage.json
. - It doesn't match the expectations developers bring from using NPM's official registry
Intended users
Anyone who interacts with GitLab's NPM package registry. (Particularly when setting up automation).
User experience goal
Users of GitLab's NPM registry should be able to use npm
(the command-line tool) exactly the same way as they do when interacting with packages on https://www.npmjs.com/.
Proposal
Standardize on using https://gitlab.com/api/v4/projects/<project ID>/packages/npm/
as the one and only NPM registry endpoint. This would allow users to configure their .npmrc
like this:
@nfriend:registry=https://gitlab.com/api/v4/projects/18806182/packages/npm/
and perform all npm
commands (publish
, view
, etc.) without needing to edit package.json
.
Further details
I'm not sure if this is a ~bug or a feature request, but I think I'll categorize this as a feature since the current behavior is well documented.
Documentation
If implemented, this would allow us to remove some setup steps from our documentation, in particular: https://docs.gitlab.com/ee/user/packages/npm_registry/#uploading-packages.