Npm publish woes

I’m experiencing all kinds of errors with npm publish, usually 403 or 404 responses.

There are a few relevant topics on this forum, but most don’t have a clear solution. The docs on how to use npm publish from a pipeline are a bit inconsistent in places, and on top of that there seem to be two relevant bugs:

  1. GitLab does not yet support using dist-tags with tokens
  2. There is a bug in some versions of Node that various people have hit.

I’m trying to publish npm packages to a private project registry from feature branches, with a different tag for each commit that’s been pushed. This is the relevant part of my CI config:

release:review:
    stage: release
    image: node:18-slim
    variables:
        VERSION: $CI_COMMIT_SHORT_SHA
    rules:
        - if: '$CI_COMMIT_BRANCH == "main"'
          when: never
        - when: on_success
    before_script:
        - npm ci --cache .npm --prefer-offline
        - npm config set @${CI_PROJECT_ROOT_NAMESPACE}:registry ${CI_API_V4_URL}/packages/npm/
        - npm config set -- //${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken ${CI_JOB_TOKEN}
        - npm config set always-auth true
    script:
        - npm run build
        - echo "Publishing with --tag ${VERSION}"
        - npm publish --verbose --tag @${VERSION}

The package.json file looks something like this:

{
    "name": "@my-org/my-project",
    ...
    "publishConfig": { "@my-org":" https://gitlab.com/api/v4/projects/my-project-id/packages/npm/" }
}

Has anyone managed to get something like this to work?