diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 086e210..7132bde 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,10 +9,29 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - id-token: write # required for npm provenance + id-token: write # required for npm trusted publishing and provenance steps: - uses: actions/checkout@v6 + - name: Check release against package version + env: + TAG: ${{ github.event.release.tag_name }} + PRERELEASE: ${{ github.event.release.prerelease }} + run: | + VERSION=$(node -p "require('./package.json').version") + if [ "${TAG#v}" != "$VERSION" ]; then + echo "::error::Release tag $TAG does not match package.json version $VERSION" + exit 1 + fi + case "$VERSION" in + *-*) IS_PRE=true ;; + *) IS_PRE=false ;; + esac + if [ "$PRERELEASE" != "$IS_PRE" ]; then + echo "::error::Version $VERSION needs the release's pre-release setting to be $IS_PRE" + exit 1 + fi + - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v6 @@ -20,14 +39,26 @@ jobs: node-version: '24' registry-url: 'https://registry.npmjs.org' - - name: Update npm for trusted publishing - run: npm install -g npm@latest # trusted publishing needs npm >= 11.5.1 + - name: Install pinned npm + run: npm install -g npm@11.21.1 # trusted publishing needs npm >= 11.5.1 - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Lint + run: pnpm run lint + - name: Build run: pnpm run build + - name: Test (Node) + run: pnpm run test:node + + - name: Install Playwright browsers + run: pnpm exec playwright install --with-deps chromium + + - name: Test (Browser) + run: pnpm run test:browser + - name: Publish to npm - run: npm publish + run: npm publish --tag ${{ github.event.release.prerelease && 'beta' || 'latest' }} diff --git a/README.md b/README.md index c525858..1de477b 100644 --- a/README.md +++ b/README.md @@ -1302,6 +1302,8 @@ pnpm test # lint + node tests (vitest) pnpm run test:browser # playwright (run `pnpm exec playwright install chromium` first) ``` +To publish a release, see [RELEASING.md](RELEASING.md). + ## Contribute PRs accepted. diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000..1d7e631 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,57 @@ +# Releasing + +Publishing to npm is done by the +[Publish workflow](.github/workflows/publish.yml), which runs when a GitHub +release is published. + +## One-time setup + +The workflow uses npm +[trusted publishing](https://docs.npmjs.com/trusted-publishers), so no npm token +or GitHub secret is needed. An npm admin of `@digitalcredentials/verifier-core` +registers the workflow once, on npmjs.com: package **Settings** → **Trusted +Publisher** → **GitHub Actions**: + +- Organization: `digitalcredentials` +- Repository: `verifier-core` +- Workflow filename: `publish.yml` +- Environment: leave blank +- Allowed actions: tick **Allow npm publish**; leave **Allow npm dist-tag** + unticked + +Renaming `publish.yml` breaks this registration. + +## Cut a release + +The npm version comes from `package.json`, not from the tag. First set `version` +in `package.json` in a pull request, and merge it to `main`. + +Then, on GitHub, go to **Releases** → **Draft a new release**: + +| Field | Prerelease | Release | +| ------------------------- | ----------------------------------- | ---------------------------- | +| `package.json` version | `2.0.0-beta.1` | `2.0.0` | +| Tag | `v2.0.0-beta.1` (create on publish) | `v2.0.0` (create on publish) | +| Target | `main` | `main` | +| Title | `v2.0.0-beta.1` | `v2.0.0` | +| Set as a pre-release | ticked | unticked | +| Set as the latest release | unticked | ticked | +| npm dist-tag | `beta` | `latest` | + +Click **Publish release**. Saving a draft does not publish. + +A prerelease installs with `npm install @digitalcredentials/verifier-core@beta`; +a release is what a plain `npm install` gets. + +## When the workflow fails + +The workflow stops before publishing if: + +- the tag, without its leading `v`, differs from the `package.json` version; +- a version with a prerelease suffix (`-beta.1`) is not marked as a pre-release, + or a version without one is; +- lint, the build, or the Node or browser tests fail. + +To retry, fix the problem on `main`, delete the GitHub release and its tag, and +publish the release again. npm never accepts the same version twice, so if a +version did reach npm, bump the version instead.