Publishing Node.js packages
In this tutorial, you'll learn how to publish Node.js packages to a registry as part of your continuous integration (CI) workflow.
In this article
Introduction
This guide shows you how to create a workflow that publishes Node.js packages to the GitHub Packages and npm registries after continuous integration (CI) tests pass.
Prerequisites
We recommend that you have a basic understanding of workflow configuration options and how to create a workflow file. For more information, seeWriting workflows.
For more information about creating a CI workflow for your Node.js project, seeBuilding and testing Node.js.
You may also find it helpful to have a basic understanding of the following:
- Working with the npm registry
- Store information in variables
- Using secrets in GitHub Actions
- Use GITHUB_TOKEN for authentication in workflows
About package configuration
Thename andversion fields in thepackage.json file create a unique identifier that registries use to link your package to a registry. You can add a summary for the package listing page by including adescription field in thepackage.json file. For more information, seeCreating a package.json file andCreating Node.js modules in the npm documentation.
When a local.npmrc file exists and has aregistry value specified, thenpm publish command uses the registry configured in the.npmrc file. You can use thesetup-node action to create a local.npmrc file on the runner that configures the default registry and scope. Thesetup-node action also accepts an authentication token as input, used to access private registries or publish node packages. For more information, seesetup-node.
You can specify the Node.js version installed on the runner using thesetup-node action.
If you add steps in your workflow to configure thepublishConfig fields in yourpackage.json file, you don't need to specify the registry-url using thesetup-node action, but you will be limited to publishing the package to one registry. For more information, seepublishConfig in the npm documentation.
Publishing packages to the npm registry
You can trigger a workflow to publish your package every time you publish a new release. The process in the following example is executed when the release event of typepublished is triggered. If the CI tests pass, the process uploads the package to the npm registry. For more information, seeManaging releases in a repository.
To perform authenticated operations against the npm registry in your workflow, you'll need to store your npm authentication token as a secret. For example, create a repository secret calledNPM_TOKEN. For more information, seeUsing secrets in GitHub Actions.
By default, npm uses thename field of thepackage.json file to determine the name of your published package. When publishing to a global namespace, you only need to include the package name. For example, you would publish a package namedmy-package tohttps://www.npmjs.com/package/my-package.
If you're publishing a package that includes a scope prefix, include the scope in the name of yourpackage.json file. For example, if your npm scope prefix is "octocat" and the package name is "hello-world", thename in yourpackage.json file should be@octocat/hello-world. If your npm package uses a scope prefix and the package is public, you need to use the optionnpm publish --access public. This is an option that npm requires to prevent someone from publishing a private package unintentionally.
If you would like to publish your package with provenance, include the--provenance flag with yournpm publish command. This allows you to publicly and verifiably establish where and how your package was built, which increases supply chain security for people who consume your package. For more information, seeGenerating provenance statements in the npm documentation.
This example stores theNPM_TOKEN secret in theNODE_AUTH_TOKEN environment variable. When thesetup-node action creates an.npmrc file, it references the token from theNODE_AUTH_TOKEN environment variable.
name: Publish Package to npmjson: release: types: [published]jobs: build: runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - uses: actions/checkout@v5 # Setup .npmrc file to publish to npm - uses: actions/setup-node@v4 with: node-version: '20.x' registry-url: 'https://registry.npmjs.org' - run: npm ci - run: npm publish --provenance --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}name:PublishPackagetonpmjson:release:types: [published]jobs:build:runs-on:ubuntu-latestpermissions:contents:readid-token:writesteps:-uses:actions/checkout@v5# Setup .npmrc file to publish to npm-uses:actions/setup-node@v4with:node-version:'20.x'registry-url:'https://registry.npmjs.org'-run:npmci-run:npmpublish--provenance--accesspublicenv:NODE_AUTH_TOKEN:${{secrets.NPM_TOKEN}}In the example above, thesetup-node action creates an.npmrc file on the runner with the following contents:
//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}registry=https://registry.npmjs.org/always-auth=truePlease note that you need to set theregistry-url tohttps://registry.npmjs.org/ insetup-node to properly configure your credentials.
Publishing packages to GitHub Packages
You can trigger a workflow to publish your package every time you publish a new release. The process in the following example is executed when the release event of typepublished is triggered. If the CI tests pass, the process uploads the package to GitHub Packages. For more information, seeManaging releases in a repository.
Configuring the destination repository
Linking your package to GitHub Packages using therepository key is optional. If you choose not to provide therepository key in yourpackage.json file, then your package will not be linked to a repository when it is published, but you can choose to connect the package to a repository later.
If you do provide therepository key in yourpackage.json file, then the repository in that key is used as the destination npm registry for GitHub Packages. For example, publishing the belowpackage.json results in a package namedmy-package published to theoctocat/my-other-repo GitHub repository.
{"name":"@octocat/my-package","repository":{"type":"git","url":"https://github.com/octocat/my-other-repo.git"},}Authenticating to the destination repository
To perform authenticated operations against the GitHub Packages registry in your workflow, you can use theGITHUB_TOKEN. TheGITHUB_TOKEN secret is set to an access token for the repository each time a job in a workflow begins. You should set the permissions for this access token in the workflow file to grant read access for thecontents permission and write access for thepackages permission. For more information, seeUse GITHUB_TOKEN for authentication in workflows.
If you want to publish your package to a different repository, you must use a personal access token (classic) that has permission to write to packages in the destination repository. For more information, seeManaging your personal access tokens andUsing secrets in GitHub Actions.
Example workflow
This example stores theGITHUB_TOKEN secret in theNODE_AUTH_TOKEN environment variable. When thesetup-node action creates an.npmrc file, it references the token from theNODE_AUTH_TOKEN environment variable.
name: Publish package to GitHub Packageson: release: types: [published]jobs: build: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v5 # Setup .npmrc file to publish to GitHub Packages - uses: actions/setup-node@v4 with: node-version: '20.x' registry-url: 'https://npm.pkg.github.com' # Defaults to the user or organization that owns the workflow file scope: '@octocat' - run: npm ci - run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}name:PublishpackagetoGitHubPackageson:release:types: [published]jobs:build:runs-on:ubuntu-latestpermissions:contents:readpackages:writesteps:-uses:actions/checkout@v5# Setup .npmrc file to publish to GitHub Packages-uses:actions/setup-node@v4with:node-version:'20.x'registry-url:'https://npm.pkg.github.com'# Defaults to the user or organization that owns the workflow filescope:'@octocat'-run:npmci-run:npmpublishenv:NODE_AUTH_TOKEN:${{secrets.GITHUB_TOKEN}}Thesetup-node action creates an.npmrc file on the runner. When you use thescope input to thesetup-node action, the.npmrc file includes the scope prefix. By default, thesetup-node action sets the scope in the.npmrc file to the account that contains that workflow file.
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}@octocat:registry=https://npm.pkg.github.comalways-auth=truePublishing packages using Yarn
If you use the Yarn package manager, you can install and publish packages using Yarn.
name: Publish Package to npmjson: release: types: [published]jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 # Setup .npmrc file to publish to npm - uses: actions/setup-node@v4 with: node-version: '20.x' registry-url: 'https://registry.npmjs.org' # Defaults to the user or organization that owns the workflow file scope: '@octocat' - run: yarn - run: yarn npm publish // for Yarn version 1, use `yarn publish` instead env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}name:PublishPackagetonpmjson:release:types: [published]jobs:build:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v5# Setup .npmrc file to publish to npm-uses:actions/setup-node@v4with:node-version:'20.x'registry-url:'https://registry.npmjs.org'# Defaults to the user or organization that owns the workflow filescope:'@octocat'-run:yarn-run:yarnnpmpublish//forYarnversion1,use`yarnpublish`insteadenv:NODE_AUTH_TOKEN:${{secrets.NPM_TOKEN}}To authenticate with the registry during publishing, ensure your authentication token is also defined in youryarnrc.yml file. For more information, see theSettings article in the Yarn documentation.