# Using semantic-release with [GitHub Actions](https://help.github.com/en/categories/automating-your-workflow-with-github-actions)

## Environment variables

The [Authentication](../../usage/ci-configuration.md#authentication) environment variables can be configured with [Secret Variables](https://docs.github.com/en/actions/reference/encrypted-secrets).

In this example a publish type [`NPM_TOKEN`](https://docs.npmjs.com/creating-and-viewing-authentication-tokens) is required to publish a package to the npm registry. GitHub Actions [automatically populate](https://docs.github.com/en/actions/security-guides/automatic-token-authentication) a [`GITHUB_TOKEN`](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) environment variable which can be used in Workflows.

## Trusted publishing and npm provenance

For improved security and automation, it is recommended to leverage [trusted publishing](https://docs.npmjs.com/trusted-publishers) through [OpenID Connect (OIDC)](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect) when publishing to npm from GitHub Actions.
GitHub Actions is a [trusted identity provider](https://docs.npmjs.com/trusted-publishers#identity-providers) for npm, enabling configuration of a trust relationship between your GitHub repository and npm so that no long-lived secret (like an `NPM_TOKEN`) is required to publish packages to npm from GitHub Actions.
The npm registry [recently increased restrictions for use of long-lived access tokens](https://github.blog/changelog/2025-09-29-strengthening-npm-security-important-changes-to-authentication-and-token-management/), further encouraging trusted publishing as the preferred approach for publishing to npm from GitHub Actions.
Enabling trusted publishing requires granting the `id-token: write` permission to the job performing the publish step and [configuring a trust relationship](https://docs.npmjs.com/trusted-publishers#step-1-add-a-trusted-publisher-on-npmjscom) between your GitHub repository and npm.

**Note**: When setting up a Trusted Publisher on npmjs for GitHub Actions, it's crucial to specify the workflow file that triggers the release process, not necessarily the one that contains the release logic itself.  
If your release job is encapsulated in a [reusable workflow](https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows), the workflow file you must reference is the caller workflow—typically the one triggered by events like `push` or `workflow_dispatch` on your main branch.  
This is because npm's Trusted Publisher mechanism authorizes the workflow that initiates the run, not any downstream workflows it invokes.

[npm provenance](https://docs.npmjs.com/generating-provenance-statements) is valuable for increasing supply-chain security for your npm packages.
Before trusted publishing was available, generating provenance attestations required configuring your project to enable publishing with provenance.
With trusted publishing, npm provenance is automatically generated for packages published to npm from GitHub Actions without any additional configuration.

## Important: Avoid `registry-url` in `setup-node`

**Do not** set the `registry-url` option in the `actions/setup-node` step when using semantic-release for npm publishing. The `registry-url` option causes `setup-node` to create an `.npmrc` file that can conflict with semantic-release's npm authentication mechanism, leading to `EINVALIDNPMTOKEN` errors even when your token is valid.

```yaml
# ❌ Don't do this - can cause conflicts with semantic-release
- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
    node-version: "lts/*"
    registry-url: "https://registry.npmjs.org"

# ✅ Do this instead - let semantic-release handle npm authentication
- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
    node-version: "lts/*"
```

If you need to specify a custom registry, configure it in your project's `.npmrc` file instead. This ensures consistent behavior between local development and CI environments, and avoids conflicts with semantic-release.

## Node project configuration

[GitHub Actions](https://github.com/features/actions) support [Workflows](https://help.github.com/en/articles/configuring-workflows), allowing to run tests on multiple Node versions and publish a release only when all test pass.

**Note**: The publish pipeline must run on a [Node version that meets our version requirement](../../support/node-version.md).

### `.github/workflows/release.yml` configuration for Node projects

The following is a minimal configuration for [`semantic-release`](https://github.com/semantic-release/semantic-release) with a build running on the latest LTS version of Node when a new commit is pushed to a `master/main` branch.
See the [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions) for additional configuration options.

```yaml
name: Release
on:
  push:
    branches:
      - master # or main

permissions:
  contents: read # for checkout

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    permissions:
      contents: write # to be able to publish a GitHub release
      issues: write # to be able to comment on released issues
      pull-requests: write # to be able to comment on released pull requests
      id-token: write # to enable use of OIDC for trusted publishing and npm provenance
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "lts/*"
      - name: Install dependencies
        run: npm clean-install
      - name: Verify the integrity of provenance attestations and registry signatures for installed dependencies
        run: npm audit signatures
      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release
```

## Pushing `package.json` changes to your repository

If you choose to commit changes to your `package.json` [against our recommendation](../../support/FAQ.md#making-commits-during-the-release-process-adds-significant-complexity), the [`@semantic-release/git`](https://github.com/semantic-release/git) plugin can be used.

**Note**: Automatically populated `GITHUB_TOKEN` cannot be used if branch protection is enabled for the target branch.
It is **not** advised to mitigate this limitation by overriding an automatically populated `GITHUB_TOKEN` variable with a [Personal Access Tokens](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line), as it poses a security risk.
Since Secret Variables are available for Workflows triggered by any branch, it becomes a potential vector of attack, where a Workflow triggered from a non-protected branch can expose and use a token with elevated permissions, yielding branch protection insignificant.
One can use Personal Access Tokens in trusted environments, where all developers should have the ability to perform administrative actions in the given repository and branch protection is enabled solely for convenience purposes, to remind about required reviews or CI checks.

If the risk is acceptable, some extra configuration is needed. The [actions/checkout `persist-credentials`](https://github.com/marketplace/actions/checkout#usage) option needs to be `false`, otherwise the generated `GITHUB_TOKEN` will interfere with the custom one. Example:

```yaml
- name: Checkout
  uses: actions/checkout@v2
  with:
    fetch-depth: 0
    persist-credentials: false # <--- this
```

## Trigger semantic-release on demand

### Using GUI:

You can use [Manual Triggers](https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/) for GitHub Actions.

### Using HTTP:

Use [`repository_dispatch`](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#repository_dispatch) event to have control on when to generate a release by making an HTTP request, e.g.:

```yaml
name: Release
on:
  repository_dispatch:
    types: [semantic-release]
jobs:
# ...
```

To trigger a release, call (with a [Personal Access Tokens](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) stored in `GITHUB_TOKEN` environment variable):

```
$ curl -v -H "Accept: application/vnd.github.everest-preview+json" -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/[org-name-or-username]/[repository]/dispatches -d '{ "event_type": "semantic-release" }'
```

### Using 3rd party apps:

If you'd like to use a GitHub app to manage this instead of creating a personal access token, you could consider using a project like:

- [Actions Panel](https://www.actionspanel.app/) - A declaratively configured way for triggering GitHub Actions
- [Action Button](https://github-action-button.web.app/#details) - A simple badge based mechanism for triggering GitHub Actions
