Skip to content

Build - fix(ncurc): update Jest version comment for clarity and accuracy #346

Build - fix(ncurc): update Jest version comment for clarity and accuracy

Build - fix(ncurc): update Jest version comment for clarity and accuracy #346

Workflow file for this run

name: Build & Release
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
version:
description: "@photostructure/sqlite release: semver bump"
required: true
type: choice
default: "patch"
options:
- patch
- minor
- major
run-name: ${{ github.event_name == 'workflow_dispatch' && format('Release - {0}', github.event.inputs.version) || format('Build - {0}', github.event.head_commit.message || github.event.pull_request.title) }}
permissions:
contents: read
defaults:
run:
shell: bash
jobs:
lint:
runs-on: ubuntu-24.04
timeout-minutes: 30 # Extend timeout to 30 minutes (default is 6 hours for a job)
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- run: sudo apt-get update
- run: sudo apt-get install -y clang-tidy bear build-essential
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: "npm"
- run: npm ci --ignore-scripts
- run: npm run build:dist
- run: npm run lint
timeout-minutes: 20 # Give the lint step more time
# Native static analysis. This job already installed clang-tidy and bear
# but never actually ran them: `npm run lint` is only lint:ts + lint:eslint.
# clang-tidy gates on the ownership/lifetime checks (see .clang-tidy's
# WarningsAsErrors); style findings stay advisory.
- run: npm run lint:native
timeout-minutes: 20
# Each prebuild job uploads the one binary it built. The pack job refuses to
# package anything unless all eight arrive under the names it expects.
prebuild-mac-x64:
runs-on: macos-15-intel # Intel x64 runner
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: "npm"
- run: npm ci --ignore-scripts
- run: npm run build:native
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: prebuild-darwin-x64
path: prebuilds/
if-no-files-found: error
- run: git diff --exit-code
prebuild-mac-arm64:
runs-on: macos-14 # Apple Silicon ARM64 (macos-14+ are ARM64)
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: "npm"
- run: npm ci --ignore-scripts
- run: npm run build:native
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: prebuild-darwin-arm64
path: prebuilds/
if-no-files-found: error
- run: git diff --exit-code
prebuild-win-x64:
runs-on: windows-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: "npm"
- run: npm ci --ignore-scripts
- run: npm run build:native
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: prebuild-win32-x64
path: prebuilds/
if-no-files-found: error
- run: git diff --exit-code
prebuild-win-arm64:
runs-on: windows-11-arm # Native ARM64 runner (public repos only)
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: "npm"
- run: npm ci --ignore-scripts
- run: npm run build:native
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: prebuild-win32-arm64
path: prebuilds/
if-no-files-found: error
- run: git diff --exit-code
prebuild-linux-glibc:
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ubuntu-24.04
- arch: arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- run: npm ci --ignore-scripts
- name: Build in Debian 11 for glibc 2.31 compatibility
env:
TARGET_ARCH: ${{ matrix.arch }}
run: npm run build:native:linux
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: prebuild-linux-${{ matrix.arch }}-glibc
path: prebuilds/
if-no-files-found: error
- run: git diff --exit-code
prebuild-linux-musl:
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ubuntu-24.04
platform: linux/amd64
- arch: arm64
runner: ubuntu-24.04-arm
platform: linux/arm64
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Build the prebuild and the test extension in Alpine
env:
DOCKER_PLATFORM: ${{ matrix.platform }}
run: |
CONTAINER_NAME="node-sqlite-musl-build-$$"
docker run -d --name "$CONTAINER_NAME" --platform "$DOCKER_PLATFORM" \
node:22-alpine sleep 3600
docker cp . "$CONTAINER_NAME:/tmp/project"
docker exec "$CONTAINER_NAME" sh -c "cd /tmp/project && apk add build-base git python3 py3-setuptools --update-cache && npm ci --ignore-scripts && npm run build:native && cd test/fixtures/test-extension && node build.js --force"
docker cp "$CONTAINER_NAME:/tmp/project/prebuilds" .
docker cp "$CONTAINER_NAME:/tmp/project/test/fixtures/test-extension/test_extension.so" test/fixtures/test-extension/ 2>/dev/null || true
docker rm -f "$CONTAINER_NAME" >/dev/null
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: prebuild-linux-${{ matrix.arch }}-musl
path: prebuilds/
if-no-files-found: error
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: test-extension-linux-${{ matrix.arch }}-musl
path: test/fixtures/test-extension/test_extension.so
if-no-files-found: warn
- run: git diff --exit-code
test-mac-win:
needs:
- prebuild-mac-x64
- prebuild-mac-arm64
- prebuild-win-x64
- prebuild-win-arm64
strategy:
fail-fast: false
matrix:
os: [macos-15-intel, macos-14, windows-latest, windows-11-arm]
node-version: [22, 24, 26]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: prebuild-*
path: ./prebuilds
merge-multiple: true
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- run: npm ci --ignore-scripts
- run: npm run build:dist
- run: npm test
test-ubuntu:
needs:
- prebuild-linux-glibc
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-24.04]
arch: [x64, arm64]
node-version: [22, 24, 26]
runs-on: ${{ matrix.arch == 'arm64' && format('{0}-arm', matrix.os) || matrix.os }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: prebuild-linux-*-glibc
path: ./prebuilds
merge-multiple: true
- run: npm ci --ignore-scripts
- run: npm run build:dist
- run: npm test
test-alpine:
needs:
- prebuild-linux-musl
strategy:
fail-fast: false
matrix:
arch: [x64, arm64]
node-version: [22, 24, 26]
include:
- arch: x64
runner: ubuntu-24.04
platform: linux/amd64
- arch: arm64
runner: ubuntu-24.04-arm
platform: linux/arm64
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: prebuild-linux-*-musl
path: ./prebuilds
merge-multiple: true
- name: Download test extension for this architecture
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: test-extension-linux-${{ matrix.arch }}-musl
path: ./test/fixtures/test-extension
continue-on-error: true
- run: DOCKER_PLATFORM=${{ matrix.platform }} NODE_VERSION=${{ matrix.node-version }} bash scripts/test-docker-alpine.sh
# Node.js compatibility tests require Node.js 22.5.0+ (node:sqlite is RC since v25.7.0)
# We test only on Node 24 to keep CI scope manageable
test-api-compatibility:
needs:
- prebuild-mac-x64
- prebuild-mac-arm64
- prebuild-win-x64
- prebuild-win-arm64
- prebuild-linux-glibc
strategy:
fail-fast: false # Don't cancel other jobs if one fails
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [24]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: prebuild-*
path: ./prebuilds
merge-multiple: true
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- run: npm ci --ignore-scripts
- run: npm run build:dist
- name: Check API compatibility types (TypeScript compile-time validation)
run: npm run lint:api
- name: Run API type compatibility tests (ensures our TypeScript types match node:sqlite)
run: npm run test:api
- name: Run behavioral compatibility tests (validates runtime behavior matches node:sqlite)
run: npm run test:node
# The release path, rehearsed on every push: publish.yaml is frozen at the tag
# it runs from, so a packaging defect discovered there costs a whole version.
pack:
name: Pack the release tarball
needs:
- prebuild-mac-x64
- prebuild-mac-arm64
- prebuild-win-x64
- prebuild-win-arm64
- prebuild-linux-glibc
- prebuild-linux-musl
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
# Node.js 24.19.0 bundles npm 11.17.0; the floor check below is what enforces the minimum.
node-version: 24.19.0
package-manager-cache: false
- name: Verify the release npm version
run: node scripts/verify-npm-version.mjs 11.10.0
- run: npm ci --ignore-scripts
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: prebuild-*
path: ./prebuilds
merge-multiple: true
- name: Verify that all eight prebuilds arrived
run: npm run release:verify-prebuilds -- --project-root .
- run: npm run build:dist
- name: Pack and inventory the package
run: |
npm run release:pack-package -- \
--project-root . \
--artifact-dir package-artifact
- run: git diff --exit-code
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: npm-package
path: package-artifact/
if-no-files-found: error
verify-package:
name: Verify packed package on ${{ matrix.os }}
needs: pack
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, macos-14, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
# Node.js 24.19.0 bundles npm 11.17.0; the floor check below is what enforces the minimum.
node-version: 24.19.0
package-manager-cache: false
- name: Verify the package-test npm version
run: node scripts/verify-npm-version.mjs 11.10.0
- run: npm ci --ignore-scripts
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: npm-package
path: package-artifact/
- name: Install the packed package with the dependency age gate
# The packed tarball is the subject under test.
run: | # zizmor: ignore[adhoc-packages]
npm run release:install-package -- \
--project-root . \
--artifact-dir package-artifact \
--install-root package-install
- name: Install a different Node.js major
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 26
package-manager-cache: false
- name: Load the packed package
run: |
npm run release:load-package -- \
--project-root . \
--install-root package-install
- run: git diff --exit-code
verify-package-alpine:
name: Verify packed package on Alpine
needs: pack
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: npm-package
path: package-artifact/
- name: Install the packed package with the dependency age gate
run: |
docker run --rm \
-v "$PWD:/tmp/project" \
--entrypoint /bin/sh \
node:24.19.0-alpine \
-c 'cd /tmp/project && node scripts/verify-npm-version.mjs 11.10.0 && npm ci --ignore-scripts && npm run release:install-package -- --project-root . --artifact-dir package-artifact --install-root package-install'
- name: Load the packed package on a different Node.js major
run: |
docker run --rm \
-v "$PWD:/tmp/project" \
--entrypoint /bin/sh \
node:26-alpine \
-c 'cd /tmp/project && npm run release:load-package -- --project-root . --install-root package-install'
- run: git diff --exit-code
release:
name: Create signed release commit and tag
if: ${{ github.event_name == 'workflow_dispatch' }}
runs-on: ubuntu-24.04
needs:
- lint
- test-mac-win
- test-ubuntu
- test-alpine
- test-api-compatibility
- verify-package
- verify-package-alpine
outputs:
tag: ${{ steps.version.outputs.tag }}
concurrency:
group: ${{ github.repository }}-release
cancel-in-progress: false
queue: single
permissions:
contents: write # Push the release commit and signed tag.
steps:
- name: Checkout the tested commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
# This isolated job must push the release commit and tag. It installs no
# dependencies and holds no npm publishing authority.
persist-credentials: true
- name: Verify the release source
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/$DEFAULT_BRANCH" ]]; then
echo "::error::Releases must be dispatched from $DEFAULT_BRANCH, not $GITHUB_REF"
exit 1
fi
git fetch --no-tags origin "$DEFAULT_BRANCH"
if [[ "$(git rev-parse "origin/$DEFAULT_BRANCH")" != "$GITHUB_SHA" ]]; then
echo "::error::$DEFAULT_BRANCH moved after this release run started; run it again"
exit 1
fi
- name: Install the release Node.js toolchain
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
# Node.js 24.19.0 bundles npm 11.17.0; the floor check below is what enforces the minimum.
node-version: 24.19.0
package-manager-cache: false
- name: Verify the release npm version
run: node scripts/verify-npm-version.mjs 11.10.0
- name: Set up SSH signing
uses: photostructure/git-ssh-signing-action@abd2a642ab7d704f66193472b47c72375d85a0c1 # v2.0.1
with:
ssh-signing-key: ${{ secrets.SSH_SIGNING_KEY }}
git-user-name: ${{ secrets.GIT_USER_NAME }}
git-user-email: ${{ secrets.GIT_USER_EMAIL }}
- name: Bump the package version
id: version
env:
BUMP: ${{ inputs.version }}
run: |
case "$BUMP" in
patch|minor|major) ;;
*)
echo "::error::Unsupported version bump: $BUMP"
exit 1
;;
esac
npm version "$BUMP" --no-git-tag-version --ignore-scripts
if ! git diff --quiet -- . \
':(exclude)package.json' \
':(exclude)package-lock.json'; then
echo "::error::The version bump changed unexpected files"
git diff --name-only
exit 1
fi
VERSION="$(node -p "require('./package.json').version")"
node -e '
const pkg = require("./package.json")
const lock = require("./package-lock.json")
if (lock.version !== pkg.version || lock.packages[""].version !== pkg.version) {
throw new Error("package.json and package-lock.json versions do not match")
}
'
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
- name: Create the signed release commit and annotated tag
env:
TAG: ${{ steps.version.outputs.tag }}
VERSION: ${{ steps.version.outputs.version }}
run: |
git add package.json package-lock.json
git commit -S -m "chore(release): $VERSION"
git tag -s -m "Release $VERSION" "$TAG"
- name: Push the commit and tag atomically
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
TAG: ${{ steps.version.outputs.tag }}
run: git push --atomic origin "HEAD:refs/heads/$DEFAULT_BRANCH" "refs/tags/$TAG"
dispatch:
name: Start tag-bound publishing
runs-on: ubuntu-24.04
needs: release
permissions:
actions: write # Start the tag-bound publishing workflow.
steps:
- name: Start the publishing workflow
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.release.outputs.tag }}
run: gh workflow run publish.yaml --repo "$GITHUB_REPOSITORY" --ref "$TAG"