Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 65 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,20 @@ jobs:

## Inputs

| Input | Description | Required | Default |
|-------------------------|-----------------------------------------------------------------------------------------------------|----------|------------------------------|
| `github-token` | GitHub token for creating PRs, tags, and releases | Yes | — |
| `release-label` | Label that marks a PR for release (only used when `require-release-label` is `true`) | No | `change-release` |
| `require-release-label` | Require the release label to trigger a release PR. When `false`, every merged PR triggers a release | No | `false` |
| `version-prefix` | Prefix for version tags (e.g., `v` produces `v1.2.3`) | No | `v` |
| `create-tag` | Create a git tag when the release PR is merged | No | `true` |
| `create-release` | Create a GitHub release when the release PR is merged | No | `true` |
| `draft-release` | Create the GitHub release as a draft (unpublished) | No | `true` |
| `changelog` | Generate or update `CHANGELOG.md` in the release PR | No | `true` |
| `publish-npm` | Publish the package to an npm registry when the release PR is merged | No | `false` |
| `npm-token` | Auth token for the npm registry (required when `publish-npm` is `true`) | No | — |
| `npm-registry` | npm registry URL (set to `https://npm.pkg.github.com` for GitHub Packages) | No | `https://registry.npmjs.org` |
| `npm-build-command` | Build command to run before `npm publish` (e.g., `npm run build`) | No | — |
| Input | Description | Required | Default |
|-------------------------|-------------------------------------------------------------------------------------------------------------------|----------|------------------------------|
| `github-token` | GitHub token for creating PRs, tags, and releases | Yes | — |
| `release-label` | Label that marks a PR for release (only used when `require-release-label` is `true`) | No | `change-release` |
| `require-release-label` | Require the release label to trigger a release PR. When `false`, every merged PR triggers a release | No | `false` |
| `version-prefix` | Prefix for version tags (e.g., `v` produces `v1.2.3`) | No | `v` |
| `create-tag` | Create a git tag when the release PR is merged | No | `true` |
| `create-release` | Create a GitHub release when the release PR is merged | No | `true` |
| `draft-release` | Create the GitHub release as a draft (unpublished) | No | `true` |
| `changelog` | Generate or update `CHANGELOG.md` in the release PR | No | `true` |
| `publish-npm` | Publish the package to an npm registry when the release PR is merged | No | `false` |
| `npm-token` | Auth token for the npm registry. Omit to use [Trusted Publishers](#publish-to-npm-with-trusted-publishers) (OIDC) | No | — |
| `npm-registry` | npm registry URL (set to `https://npm.pkg.github.com` for GitHub Packages) | No | `https://registry.npmjs.org` |
| `npm-build-command` | Build command to run before `npm publish` (e.g., `npm run build`) | No | — |

## Outputs

Expand Down Expand Up @@ -182,6 +182,57 @@ Commits that can't be linked to a PR will reference the commit SHA instead.
npm-build-command: 'npm run build'
```

### Publish to npm with Trusted Publishers

[npm Trusted Publishers](https://docs.npmjs.com/trusted-publishers) lets you publish without a long-lived token. npm
exchanges a GitHub OIDC token at publish time and attaches a provenance attestation automatically.

**Setup:**

1. On npmjs.com, open your package's settings → **Publishing access** and add a trusted publisher. Match the repo
(`owner/repo`), the workflow filename (e.g., `release.yml`), and the environment if you use one. The values must
match exactly — a mismatch will reject the publish.
2. Use Node 24+ in your workflow. Trusted Publishers requires npm ≥ 11.5.1; Node 24 ships it by default, older Node
versions don't.
3. Add `id-token: write` to the workflow's `permissions`.
4. Omit `npm-token`. If a token is set, the action falls back to token auth and skips OIDC.

> **First publish:** Trusted Publishers can only be configured on a package that already exists on npm. For a brand-new
> package, do the initial publish manually (or with a token) so the package exists, then set up the trusted publisher
> and remove the token.

```yaml
name: Release

on:
pull_request:
types: [ closed ]

permissions:
contents: write
pull-requests: write
id-token: write # required for Trusted Publishers

jobs:
release:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'
- uses: offload-project/release-champion@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
publish-npm: true
npm-build-command: 'npm run build'
```

### Publish to GitHub Packages

```yaml
Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ inputs:
required: false
default: 'false'
npm-token:
description: 'Auth token for the npm registry (required when publish-npm is true)'
description: 'Auth token for the npm registry. Omit to use npm Trusted Publishers (OIDC) — requires id-token:write permission and npm >= 11.5.1.'
required: false
npm-registry:
description: 'npm registry URL (e.g., https://npm.pkg.github.com for GitHub Packages)'
Expand Down
16 changes: 9 additions & 7 deletions scripts/finalize-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,19 @@ main() {
exit 1
fi

if [[ -z "${INPUT_NPM_TOKEN:-}" ]]; then
echo "::error::npm-token is required when publish-npm is true"
exit 1
fi

local registry="${INPUT_NPM_REGISTRY:-https://registry.npmjs.org}"
local registry_host
registry_host=$(echo "$registry" | sed 's|https:||' | sed 's|/$||')

echo "${registry_host}/:_authToken=${INPUT_NPM_TOKEN}" > .npmrc
echo "registry=${registry}" >> .npmrc
if [[ -n "${INPUT_NPM_TOKEN:-}" ]]; then
echo "${registry_host}/:_authToken=${INPUT_NPM_TOKEN}" > .npmrc
echo "registry=${registry}" >> .npmrc
else
# No token: rely on npm Trusted Publishers (OIDC).
# Requires npm >= 11.5.1 and `id-token: write` workflow permission.
echo "registry=${registry}" > .npmrc
echo "No npm-token provided — using Trusted Publishers (OIDC)"
fi

if [[ -n "${INPUT_NPM_BUILD_COMMAND:-}" ]]; then
echo "Running build: ${INPUT_NPM_BUILD_COMMAND}"
Expand Down