Code-Apprentice
Code-Apprentice

Reputation: 83557

Publish an NPM package to GitLab package registry

I followed the instructions in the GitLab docs to publish my project as a package to the project's registry. Here is my .gitlab-ci.yml file:

image: node:18

stages:
  - publish

publish:
  stage: publish
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  script:
    - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}">.npmrc
    - npm publish

When I run this pipeline, it gives the following error:

npm ERR! code ENEEDAUTH
npm ERR! need auth This command requires you to be logged in to https://registry.npmjs.org/
npm ERR! need auth You need to authorize this machine using `npm adduser`
npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2023-02-16T19_08_00_397Z-debug-0.log

Why does it say I need to authenticate with registry.npmjs.org? I am trying to publish to my GitLab package registry, not to NPM. More importantly, how do I correctly authenticate with GitLab and publish my NPM package to the project's registry?

More Details

I tried adding this line at the top of my script block:

- echo "registry=https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/">.npmrc

This gives the following error:

npm notice Publishing to https://gitlab.com/api/v4/projects/<project-id>/packages/npm/ with tag latest and default access
npm ERR! code E403
npm ERR! 403 403 Forbidden - PUT https://gitlab.com/api/v4/projects/<project-id>/packages/npm/npm-publish-gitlab
npm ERR! 403 In most cases, you or one of your dependencies are requesting
npm ERR! 403 a package version that is forbidden by your security policy, or
npm ERR! 403 on a server you do not have access to.
npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2023-02-16T19_26_48_321Z-debug-0.log

If I also change image: node:18 to image: node:14, it works. So something appears to have changed since nodejs 14 that breaks the gitlab pipeline implementation. Any ideas what it might be?


I changed my script to

  script:
    - cd ui
    - echo "@${CI_PROJECT_NAMESPACE}:${CI_JOB_TOKEN}" >> .npmrc
    - cat .npmrc
    - npm publish --registry=https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/

Now this gives:

npm ERR! code E404
npm ERR! 404 Not Found - PUT https://gitlab.com/api/v4/projects/<project-id>/packages/npm/ui
npm ERR! 404 
npm ERR! 404  '[email protected]' 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!     /root/.npm/_logs/2023-02-24T16_54_47_061Z-debug.log

I am the author and this is an attempt to publish the package. So this error makes absolutely no sense. What do I try next?

Upvotes: 4

Views: 3765

Answers (2)

Uder Moreira
Uder Moreira

Reputation: 932

I know I'm a bit late with this response, but an approach from 2024 that helped me solve this problem even using the node:latest image (which at that time corresponded to version 21) was to use the following ci-cd configuration:

publish-npm:
  stage: deploy
  script:
    - NPM_TOKEN=$CI_DEPLOY_PASSWORD
    - echo "@scope:registry=https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/" > .npmrc
    - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=\"${NPM_TOKEN}\"" >> .npmrc
    - npm publish --verbose

Where CI_DEPLOY_PASSWORD is a special type of GitLab Deploy Token, automatically available to the pipeline.

I also configured the package.json with the publishConfig option:

"publishConfig": {
  "@<my-scope>:registry": "https://<my-server>:<my-server-port>/api/v4/projects/<my-project-id>/packages/npm/"
}

And with the name option using:

{
  "name": "@<my-scope>/<my-package>"
}

I hope this solution can help.

Upvotes: 2

Mureinik
Mureinik

Reputation: 311938

It looks like you're missing a definition to publish your package to the internal registry.

This can be done in the package.json (although I don't think there's a convenient way of using environment variables there):

"publishConfig": {
    "registry":"http://my-internal-registry.local"
}

or directly in the .npmrc:

registry=https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/

this can also be limited to a specific scope:

@myscope:registry=https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/

Upvotes: 2

Related Questions