Skip to Content
Edmond Kacaj

6 mins read


Publishing npm Packages with GitLab CI

Learn how to automate npm publishing using GitLab CI and OIDC trusted publishing—no manual tokens required. A practical guide to CI/CD for package maintainers.


Publishing npm Packages with GitLab CI and Trusted Publishers

When you publish npm packages from a CI/CD pipeline, two things really matter: security and traceability. npm Trusted Publishers, combined with OIDC-based authentication, give you both without the operational pain of managing long-lived access tokens.

  • Trusted Publishers let npm verify that a specific CI system, repository, and workflow are allowed to publish a package. Once this relationship is established, your GitLab CI pipeline can publish directly to npm—no secrets checked into the repo, no tokens stored in CI variables, and no local credentials required.

  • OIDC (OpenID Connect) provides short-lived, cryptographically verifiable identity tokens. GitLab issues an OIDC token for each job, describing exactly who it is (project, pipeline, job). npm validates that identity at publish time. When the job ends, the token is gone.

The result is a clean and auditable release flow: every published version is tied to a commit, a pipeline, and a tag—and only CI can publish.


Prerequisites

Before starting, make sure you have:

  • An npm account with a verified email
  • A GitLab project containing an npm package
  • Node.js 18 or newer (Trusted Publishers require modern npm versions)
  • Basic familiarity with .gitlab-ci.yml

About the Project and the Publishing Model

For this guide, we’ll publish a small example project:

dice-rolling https://gitlab.com/e.kacaj/dice-rolling

It’s a simple CLI tool that rolls dice,useful for quick games or testing randomness. More importantly, it’s small enough to focus on the publishing workflow rather than application complexity.

Our approach is straightforward:

  • Publish once manually to establish the package on npm
  • Configure Trusted Publishers
  • Let GitLab CI handle all future releases
  • Trigger releases only via git tags

Part 2: Initial Publication and Trusted Publisher Setup

Before CI can publish anything, npm needs an initial release and a trusted connection to GitLab.

Step 1: Log in to npm locally

  1. Open a terminal.
  2. Run:
bash
npm login
  1. Follow the browser-based authentication flow.
  2. Once complete, your local environment can publish to npm.

Step 2: Publish the Initial Version

  1. From the dice-rolling project root, confirm we are on current directory:
bash
cd path/to/dice-rolling
  1. Publish the package:
bash
npm publish --access public
  1. Verify the package is live: https://www.npmjs.com/package/dice-rolling

This manual publish is required only once. From here on, CI will handle releases.


Step 3: Configure Trusted Publishers

  1. Go to npmjs.com → ProfilePackagesdice-rollingSettings
  2. Scroll to Trusted Publishers
  3. Click Add a Trusted Publisher
  4. Enter:
    • GitLab namespace/project: e.kacaj/dice-rolling
    • Top-level CI file path: .gitlab-ci.yml
    • Environment name: optional (leave empty unless you use environments)
  5. Save the configuration

From this point forward, npm will accept publish requests only from matching GitLab CI jobs.


Part 3: Configuring GitLab CI for Automated Publishing

Below is a minimal .gitlab-ci.yml that publishes to npm using Trusted Publishers and OIDC.

yaml
stages: - release variables: NODE_VERSION: "24" publish: stage: release image: node:${NODE_VERSION} id_tokens: NPM_ID_TOKEN: aud: "npm:registry.npmjs.org" SIGSTORE_ID_TOKEN: aud: sigstore script: - npm install -g npm@latest - npm install # Install dependencies and update package-lock.json - npm ci - npm run build - npm publish only: - tags environment: name: npm-registry url: https://www.npmjs.com/package/dice-rolling

The id_tokens Section

yaml
id_tokens: NPM_ID_TOKEN: aud: "npm:registry.npmjs.org" SIGSTORE_ID_TOKEN: aud: sigstore

This tells GitLab to issue OIDC tokens for npm and (optionally) Sigstore. npm automatically picks up the token during npm publish, no configuration required.


The script Section

yaml
script: - npm install -g npm@latest - npm install # Install dependencies and update package-lock.json - npm ci - npm run build - npm publish

Each step is deliberate:

  1. Ensure npm supports Trusted Publishers
  2. Install dependencies deterministically
  3. Build exactly what will be published
  4. Publish using a short-lived OIDC identity

Restricting Publishing to Tags

yaml
only: - tags

This is a critical safeguard. Publishing happens only when a git tag is pushed. Commits, branches, and merge requests will never publish a package.


Part 4: Releasing a New Version (Manual Versioning & Tagging)

Instead of using npm version, we’ll keep versioning explicit and transparent.

Step 1: Update the Version Manually

  1. Edit package.json by hand.
  2. Change the version, for example:
json
{ "version": "1.0.1" }

and run npm install to update package-lock.json accordingly.

  1. Commit the change:
bash
git add package.json package-lock.json git commit -m "chore(release): v1.0.1"

Step 2: Create and Push a Git Tag Manually

  1. Create an annotated tag:
bash
git tag -a v1.0.1 -m "Release v1.0.1"
  1. Push commits and tags:
bash
git push origin master --tags

Step 3: Verify the Release

If everything is configured correctly, the new version will be published automatically.