Publish your packages to NPM automatically with GitHub Actions

Publish your packages to NPM automatically with GitHub Actions

posted 3 min read

Automating publication prevents manual errors, speeds up releases, and forces you to maintain a repeatable and transparent process.

In this article, we're going to create a GitHub Actions workflow that publishes to NPM when you push to main. The flow installs dependencies, runs tests, compiles, and, if all goes well, publishes the package using a secure token stored as a secret.

What is the purpose of the workflow?

Every time you merge changes to main, we want to:

  • Install dependencies
  • Run tests
  • Build the package
  • Publish to NPM using secure credentials

This standardizes the publishing process and reduces the risk of human error.

General workflow structure

name: Publish to NPM
on:
  push:
    branches:
      - main

jobs:
  publish:
    name: publish
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: "22"

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm run test

      - name: Build package
        run: npm run build

      - name: Publish to NPM
        uses: JS-DevTools/npm-publish@v3
        with:
          token: ${{ secrets.NPM_TOKEN }}

️ ️ What does each step do?

on: push to main

Triggers the workflow when pushing to the main branch. If you prefer to publish only with tags, you can change the trigger to on: push: tags: - ‘v*’.

actions/checkout@v4

Downloads the repository to the runner.

actions/setup-node@v4

Configures Node.js (v22 in the example). You can enable cache: ‘npm’ to speed up installations.

npm ci / npm install

Installs dependencies. npm ci is faster and more reproducible in CI if you use package-lock.json.

npm run test and npm run build

Verify that the package passes tests and compiles correctly before publishing.

JS-DevTools/npm-publish@v3

Publish the package by reading package.json. Use the token you pass through with.token.

Authentication with NPM: NPM_TOKEN

To publish, you need a token in NPM and save it as a secret in GitHub:

  1. Create an Automation Token in your NPM account (recommended for CI; respects 2FA and allows automatic publishing).
  2. In GitHub, go to SettingsSecrets and variablesActionsNew repository secret.
  3. Create the secret NPM_TOKEN with the value of the NPM token.

If your package is scoped (e.g., @your-org/package), make sure that package.json contains “name”: “@your-org/package” and “publishConfig”: { ‘access’: “public” } if you want it to be public.

Example of publishConfig in package.json:

{
  "name": "@tu-org/tu-paquete",
  "version": "1.2.3",
  "publishConfig": {
    "access": "public",
    "tag": "latest"
  }
}

Dry-run and version control

Dry-run: test the flow without actually publishing:

- name: Publish to NPM (dry run)
  uses: JS-DevTools/npm-publish@v3
  with:
    token: ${{ secrets.NPM_TOKEN }}
    dry-run: true

Versioning: this flow publishes the version specified in package.json. Be sure to update the version before merging to main.
If you use automatic versioning (e.g., Conventional Commits + automatic releases), integrate that stage before the publication step.

✅ Final result

With this workflow:

  • You publish to NPM in a consistent and repeatable manner.
  • You avoid broken releases thanks to preliminary tests + builds.
  • You keep credentials secure with GitHub Secrets.
  • You reduce manual steps and time between merge and release.

Would you rather set it up with a visual interface?

If you're interested in defining this flow with a visual interface and getting the YAML instantly, you can use OctoLab:

  • Step-by-step visual editor
  • Dynamic fields for actions and tokens
  • Real-time YAML preview
  • Built-in validations
  • Copy/download and you're done

Try it out: https://www.octolab.app/templates/npm-publish

Conclusion

Automating publication to NPM with GitHub Actions reduces friction and errors. With a simple configuration—tests, build, and a publish step with a secure token—you can standardize releases and focus on building value.

If this was helpful, let me know what you would like to add to the template (tags, prereleases, monorepos, changelogs, etc.). Let's keep going!

If you read this far, tweet to the author to show them you care. Tweet a Thanks
0 votes
0 votes
0 votes
0 votes

More Posts

Streamlining Your Next.js Project with Private GitHub/Gitlab Repositories as NPM Packages

Brian Baliach - Sep 10

Deploy your application on Vercel with GitHub Actions

OctoLab - Aug 20

From Code Push to Docker Hub: CI/CD with GitHub Actions

Imthadh Ahamed - Oct 14

Beyond skeleton pipelines: who owns your software pipeline?

Matt Allford - Aug 13

Mastering CI/CD with AWS DevOps: A Complete 2025 Guide

Aditya Pratap Bhuyan - Apr 29
chevron_left