Skip to content

chore(release): v0.4.2 #6

chore(release): v0.4.2

chore(release): v0.4.2 #6

Workflow file for this run

name: Release
on:
push:
tags:
- "v*.*.*"
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions: {}
jobs:
package:
name: Verify And Package
runs-on: ubuntu-latest
permissions:
contents: read
env:
HUSKY: 0
outputs:
name: ${{ steps.metadata.outputs.name }}
version: ${{ steps.metadata.outputs.version }}
tarball: ${{ steps.metadata.outputs.tarball }}
sha256: ${{ steps.checksum.outputs.sha256 }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
persist-credentials: false
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6
with:
version: 11.17.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 24
cache: pnpm
- name: Install
run: pnpm install --frozen-lockfile
- name: Verify Tag Matches Package Version
id: metadata
shell: bash
run: |
set -euo pipefail
PACKAGE_NAME="$(node -p "require('./package.json').name")"
PACKAGE_VERSION="$(node -p "require('./package.json').version")"
if [[ ! "${PACKAGE_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Only stable semantic versions can be released"
exit 1
fi
if [ "${GITHUB_REF_NAME}" != "v${PACKAGE_VERSION}" ]; then
echo "::error::Tag ${GITHUB_REF_NAME} does not match package version ${PACKAGE_VERSION}"
exit 1
fi
if ! git merge-base --is-ancestor "${GITHUB_SHA}" "origin/main"; then
echo "::error::Release commit is not on the main branch"
exit 1
fi
{
echo "name=${PACKAGE_NAME}"
echo "version=${PACKAGE_VERSION}"
echo "tarball=${PACKAGE_NAME}-${PACKAGE_VERSION}.tgz"
} >> "${GITHUB_OUTPUT}"
- name: Full Verification
run: pnpm run verify
- name: Create Release Tarball
id: checksum
shell: bash
env:
TARBALL: ${{ steps.metadata.outputs.tarball }}
run: |
set -euo pipefail
pnpm pack --out "${TARBALL}"
test -s "${TARBALL}"
SHA256="$(sha256sum "${TARBALL}")"
echo "sha256=${SHA256%% *}" >> "${GITHUB_OUTPUT}"
- name: Upload Release Tarball
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: npm-package
path: ${{ steps.metadata.outputs.tarball }}
if-no-files-found: error
retention-days: 14
e2e:
name: Playwright E2E
needs: package
runs-on: ubuntu-latest
permissions:
contents: read
env:
HUSKY: 0
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6
with:
version: 11.17.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 24
cache: pnpm
- name: Install
run: pnpm install --frozen-lockfile
- name: Download Release Tarball
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: npm-package
- name: Verify And Extract Packaged Build
shell: bash
env:
SHA256: ${{ needs.package.outputs.sha256 }}
TARBALL: ${{ needs.package.outputs.tarball }}
run: |
set -euo pipefail
printf '%s %s\n' "${SHA256}" "${TARBALL}" | sha256sum --check --strict
rm -rf dist dist-browser
tar -xzf "${TARBALL}" --strip-components=1
test -s dist/index.cjs
test -s dist/index.mjs
test -s dist-browser/index.min.js
- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps chromium firefox webkit
- name: E2E
run: pnpm run e2e:all
publish:
name: Publish To Npm
needs: [package, e2e]
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 24
registry-url: "https://registry.npmjs.org"
- name: Download Release Tarball
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: npm-package
- name: Verify Release Tarball
shell: bash
env:
SHA256: ${{ needs.package.outputs.sha256 }}
TARBALL: ${{ needs.package.outputs.tarball }}
run: |
set -euo pipefail
printf '%s %s\n' "${SHA256}" "${TARBALL}" | sha256sum --check --strict
- name: Check Published Version
id: registry
env:
PACKAGE_NAME: ${{ needs.package.outputs.name }}
PACKAGE_VERSION: ${{ needs.package.outputs.version }}
TARBALL: ${{ needs.package.outputs.tarball }}
run: |
node --input-type=module <<'NODE'
import { createHash } from "node:crypto";
import { appendFile, readFile } from "node:fs/promises";
const { GITHUB_OUTPUT, PACKAGE_NAME, PACKAGE_VERSION, TARBALL } =
process.env;
const url =
"https://registry.npmjs.org/" +
`${encodeURIComponent(PACKAGE_NAME)}/` +
encodeURIComponent(PACKAGE_VERSION);
const response = await fetch(url, {
headers: { accept: "application/json" },
});
if (response.status === 404) {
await appendFile(GITHUB_OUTPUT, "exists=false\n");
process.exit(0);
}
if (!response.ok) {
throw new Error(`npm registry returned HTTP ${response.status}`);
}
const metadata = await response.json();
const bytes = await readFile(TARBALL);
const localIntegrity =
"sha512-" + createHash("sha512").update(bytes).digest("base64");
if (metadata?.dist?.integrity !== localIntegrity) {
throw new Error(
`${PACKAGE_NAME}@${PACKAGE_VERSION} already exists with different contents`,
);
}
await appendFile(GITHUB_OUTPUT, "exists=true\n");
console.log(
`${PACKAGE_NAME}@${PACKAGE_VERSION} already exists; skipping publish`,
);
NODE
- name: Publish Release Tarball
if: steps.registry.outputs.exists != 'true'
env:
TARBALL: ${{ needs.package.outputs.tarball }}
run: npm publish "./${TARBALL}" --access public --provenance
github-release:
name: Create GitHub Release
needs: [package, publish]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
persist-credentials: false
- name: Download Release Tarball
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: npm-package
- name: Verify Release Tarball
shell: bash
env:
SHA256: ${{ needs.package.outputs.sha256 }}
TARBALL: ${{ needs.package.outputs.tarball }}
run: |
set -euo pipefail
printf '%s %s\n' "${SHA256}" "${TARBALL}" | sha256sum --check --strict
- name: Generate Changelog
shell: bash
run: |
set -euo pipefail
TAG="${GITHUB_REF_NAME}"
PREV_TAG="$(git describe --tags --abbrev=0 --match 'v*.*.*' "${TAG}^" 2>/dev/null || true)"
{
echo "## ${TAG}"
echo
if [ -n "${PREV_TAG}" ]; then
echo "Changes since ${PREV_TAG}:"
echo
git log "${PREV_TAG}..${TAG}" --pretty=format:'- %s (%h)'
else
echo "Changes:"
echo
git log "${TAG}" --pretty=format:'- %s (%h)'
fi
echo
} > RELEASE_NOTES.md
- name: Create Or Update GitHub Release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3
with:
body_path: RELEASE_NOTES.md
files: ${{ needs.package.outputs.tarball }}
fail_on_unmatched_files: true
overwrite_files: true