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
92 changes: 48 additions & 44 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,51 +1,55 @@
name: Release

on:
push:
branches: [main]
paths: [package.json]
workflow_dispatch:
concurrency: release
inputs:
action:
description: Operation
type: choice
options: [verify, stage, finalize]
default: verify
required: true
version:
description: "Required for finalize only, e.g. 1.2.3"
type: string
default: ""
required: false

permissions:
contents: read

concurrency:
group: release
cancel-in-progress: false

jobs:
Release:
runs-on: ubuntu-latest
environment: deployment
Verify:
if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'verify'
permissions:
contents: write # create the tag and the GitHub Release
id-token: write # npm Trusted Publishing
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- id: version
run: |
tag="v$(node -p 'require("./package.json").version')"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
echo "released=true" >> "$GITHUB_OUTPUT"
fi
- if: steps.version.outputs.released != 'true'
uses: actions/setup-node@v7
with:
node-version: 24.x
package-manager-cache: false
registry-url: https://registry.npmjs.org
- if: steps.version.outputs.released != 'true'
run: npm install --global npm@11.21.0
- if: steps.version.outputs.released != 'true'
run: npm ci
- if: steps.version.outputs.released != 'true'
run: npm run build
- if: steps.version.outputs.released != 'true'
run: npx @nlib/cleanup-package-json --file package.json
# Trusted Publishing (OIDC); a maintainer approves the staged version on npmjs.com.
- if: steps.version.outputs.released != 'true'
run: |
name=$(node -p 'require("./package.json").name')
version=$(node -p 'require("./package.json").version')
npm view "$name@$version" version >/dev/null 2>&1 || npm stage publish
- if: steps.version.outputs.released != 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.version.outputs.tag }}
run: |
awk -v h="## $TAG " 'index($0,h)==1{f=1;next} /^## v/{if(f)exit} f' CHANGELOG.md > notes.md
gh release create "$TAG" --target "$GITHUB_SHA" --title "$TAG" --notes-file notes.md
contents: read
uses: nlibjs/actions/.github/workflows/npm-release.yml@986b87befafad2f4f990c934165a90ea37ddbf36
with:
action: verify

Stage:
if: github.event_name == 'push' || github.event.inputs.action == 'stage'
permissions:
contents: write
id-token: write
uses: nlibjs/actions/.github/workflows/npm-release.yml@986b87befafad2f4f990c934165a90ea37ddbf36
with:
action: stage
environment: deployment

Finalize:
if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'finalize'
permissions:
contents: write
uses: nlibjs/actions/.github/workflows/npm-release.yml@986b87befafad2f4f990c934165a90ea37ddbf36
with:
action: finalize
environment: deployment
version: ${{ github.event.inputs.version }}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ Then, set `@nlib/lint-commit` to `commit-msg` hook.
#!/bin/sh
npx @nlib/lint-commit --input "$1"
```

## Releases

Maintainers can follow the [release guide](docs/releases.md).
34 changes: 34 additions & 0 deletions docs/releases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Maintainer release guide

The Release workflow pins `nlibjs/actions` to `986b87befafad2f4f990c934165a90ea37ddbf36`, with helper `70dd80ae972e812efcc9606d0ec5d514c8be3982`.

## Configuration

Configure npm Trusted Publisher for `@nlib/lint-commit` with these values:

| Setting | Value |
| --- | --- |
| Organization or user | `nlibjs` |
| Repository | `lint-commit` |
| Workflow filename | `release.yml` |
| Environment | `deployment` |

Stage and Finalize use the repository's `deployment` environment. Each operation requires its environment approval if protection rules are configured. Verify runs without that environment.

## Operations

1. For a nonpublishing check, select **Release → Run workflow**, choose a branch, select `action=verify`, and leave version empty. Verify runs lint, tests, build, cleanup and tarball checks.
2. Prepare a normal version and changelog update, then merge to main. A package.json push starts Stage automatically. Manual Stage on main accepts the current package version; leave version empty.
3. Check the Stage run and its saved draft for the intended package/version.
4. Approve the exact version on npmjs.com's **Staged Packages** page with maintainer 2FA.
5. Run Release on `main` with `action=finalize` and the approved version without `v`.

Manual dispatch defaults to Verify. Stage and Finalize require main. This package publishes to npm and GitHub Releases.

## Recovery

Follow the shared workflow's [recovery procedure](https://github.com/nlibjs/actions/blob/986b87befafad2f4f990c934165a90ea37ddbf36/README.md#existing-versions-and-failures) for failed or partial releases.

## Updating the workflow

Update all three full SHA references in `.github/workflows/release.yml` together. Confirm that the workflow and its helper pin are preserved in shared main history, Stage and Finalize still use `deployment`, and the existing Lint and Test checks pass before merging.
Loading