Skip to content

deps(node): bump esbuild from 0.25.12 to 0.28.1 in /src/bindings/nodejs in the js-dev-dependencies group across 1 directory #56

deps(node): bump esbuild from 0.25.12 to 0.28.1 in /src/bindings/nodejs in the js-dev-dependencies group across 1 directory

deps(node): bump esbuild from 0.25.12 to 0.28.1 in /src/bindings/nodejs in the js-dev-dependencies group across 1 directory #56

Workflow file for this run

name: CI
on:
push:
branches: [main, develop]
pull_request:
workflow_dispatch:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
# ---------------------------------------------------------------- quality
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
cache-dependency-path: src/bindings/nodejs/package-lock.json
- run: cargo fmt --all -- --check
- run: cargo clippy --workspace --all-targets -- -D warnings
- run: npm ci --no-audit --no-fund
working-directory: src/bindings/nodejs
- run: npm run lint
working-directory: src/bindings/nodejs
# ------------------------------------------------------------------ tests
# The matrix is the whole point of this workflow: "works on my machine" is
# exactly the failure mode this project is trying to eliminate, so every
# supported OS/arch/Node combination has to run the same suites.
test:
name: ${{ matrix.name }} / node ${{ matrix.node }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- { name: linux-x64, os: ubuntu-latest, node: 18 }
- { name: linux-x64, os: ubuntu-latest, node: 20 }
- { name: linux-x64, os: ubuntu-latest, node: 22 }
- { name: linux-arm64, os: ubuntu-24.04-arm, node: 22 }
- { name: macos-arm64, os: macos-latest, node: 18 }
- { name: macos-arm64, os: macos-latest, node: 22 }
# macos-15-intel, not macos-13: GitHub retired the macOS 13 labels on
# 2025-12-04, and a job asking for a retired label is not rejected --
# it queues for a machine that will never arrive, so this leg sat
# pending through every run and took the all-green gate with it.
# This is the last x86_64 macOS image Actions will offer.
- { name: macos-x64, os: macos-15-intel, node: 22 }
- { name: windows-x64, os: windows-latest, node: 20 }
- { name: windows-x64, os: windows-latest, node: 22 }
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.name }}
- uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node }}
cache: npm
cache-dependency-path: src/bindings/nodejs/package-lock.json
- name: Install clang (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y clang
# inotify's default watch limit is low enough that a recursive watch over
# a large tree can exhaust it. Raise it so a genuine bug is not masked by
# an environment limit -- and so the limit-exhaustion test stays
# meaningful rather than firing spuriously.
- name: Raise inotify limits (Linux)
if: runner.os == 'Linux'
run: |
sudo sysctl -w fs.inotify.max_user_watches=524288
sudo sysctl -w fs.inotify.max_user_instances=512
- name: Build C hash engine
run: make build-core
- name: C engine tests
run: make test-core
# retrigger-nodejs-bindings used to be excluded here. It is a `cdylib`
# whose napi_* symbols come from the Node process that loads it, and
# under napi 2 a standalone `cargo test` harness had no host for them:
# it failed to link on Windows and, on x86-64 Linux, linked but died at
# startup resolving napi_reference_unref through a GOT relocation. napi 3
# resolves those symbols at load time instead (napi-sys `dyn-symbols`, on
# by default), so the harness now carries no napi_* imports at all and
# one command is honest on every runner.
- name: Rust tests
run: cargo test --workspace --release
- name: Install JS dependencies
run: npm ci --no-audit --no-fund
working-directory: src/bindings/nodejs
# Build the addon this package actually ships, so the native-parity suite
# (parity-native.test.mjs) runs instead of skipping. Without this step a
# green JS run never proves the fallback matches the real Rust engine --
# the one guarantee the whole package rests on. Gated to match the JS test
# legs below: the addon is a Rust build (Node-version independent), but its
# only consumer here is the vitest run, which the Node 18 legs skip.
- name: Build native addon
if: matrix.node != 18
run: npm run build
working-directory: src/bindings/nodejs
# Unguarded on every leg, Node 18 included, and vite is held at 6 to keep
# it that way. Vitest 4 declares node ^20 || ^22 || >=24, but that is
# advisory and it runs on 18 regardless; vite 7+ is the real constraint,
# because it bundles rolldown, which imports node:util#styleText (Node
# 20.12+). With vite 7+ installed the failure is a startup error -- vitest
# loads this config through vite -- so it costs the entire suite on the
# oldest Node engines.node claims, not just the dev-server file.
- name: JavaScript tests
run: npm test
working-directory: src/bindings/nodejs
# The daemon npm package is a shim over a per-platform Rust binary. This
# proves the shim, the shipped config, and the documented no-binary
# degradation from Node. Plain node:test, so it runs on every leg
# including Node 18.
- name: Daemon package smoke test
run: node scripts/test-daemon.js
working-directory: src/daemon
# The direct answer to "will it work when I install it somewhere else":
# pack the tarball, install it into a clean directory, and require it.
- name: Packaged install proof
run: npm run test:pack
working-directory: src/bindings/nodejs
# FreeBSD has no GitHub-hosted runner. Same free `vmactions/freebsd-vm`
# guest used by the release build: prove the Node package builds, passes its
# suite, and packs on a real FreeBSD x64 kernel. The full Rust workspace
# suite stays on the GitHub-hosted OS matrix above — this leg is the Node
# addon contract for the platform the matrix previously omitted.
test-freebsd:
name: freebsd-x64 / node 22
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v7
- name: Build and test on FreeBSD
uses: vmactions/freebsd-vm@v1
with:
release: '14.3'
usesh: true
copyback: false
prepare: |
pkg install -y gmake curl
pkg install -y node22 || pkg install -y node
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal
run: |
set -eu
. "$HOME/.cargo/env"
cd src/bindings/nodejs
npm ci --no-audit --no-fund
npm run build
npm test
npm run test:pack
# ------------------------------------------------------------- bundler-legs
# test/vite.test.mjs and test/webpack.test.mjs run against the pinned vite@6
# and webpack@5 on every leg above via plain `npm test`. This job re-runs
# those exact same suites retargeted at vite@7 and @rspack/core (see
# vitest.vite7.config.mjs / vitest.rspack.config.mjs) plus the Rspack-only
# persistent-cache case, on the one Node version (22) that clears every
# floor involved: vite@7's rolldown needs node:util#styleText (20.12+),
# @rspack/core needs 20.19+/22.12+, and Astro (already exercised by the
# matrix's Node-22 legs through plain `npm test`, self-skipped elsewhere --
# see test/astro.test.mjs) needs 22.12+. Both scripts are also
# version-gated internally, so this job stays a true no-op rather than a
# failure if that floor ever moves out from under it.
bundler-legs:
name: Bundler compatibility (vite@7, Rspack, Astro)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: bundler-legs
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
cache-dependency-path: src/bindings/nodejs/package-lock.json
- run: sudo apt-get update && sudo apt-get install -y clang
- run: make build-core
- run: npm ci --no-audit --no-fund
working-directory: src/bindings/nodejs
- run: npm run build
working-directory: src/bindings/nodejs
- name: vite@7
run: npm run test:vite7
working-directory: src/bindings/nodejs
- name: Rspack
run: npm run test:rspack
working-directory: src/bindings/nodejs
- name: Astro dev server
run: npx vitest run test/astro.test.mjs
working-directory: src/bindings/nodejs
# ------------------------------------------------------------------- musl
# Alpine is a separate risk surface from Debian: different libc, and the
# package's libc detection has to pick the musl binaries. It has been wrong
# before, so it gets its own job rather than being assumed from linux-x64.
test-musl:
name: linux-x64-musl
runs-on: ubuntu-latest
container:
image: node:22-alpine
steps:
# Before the checkout, deliberately. Without git in the image the action
# falls back to the REST tarball, which is `git archive` and therefore
# honours the export-ignore rules in .gitattributes -- so this job alone
# would run against a tree missing tools/benchmarks and fail on the
# scripts-point-at-real-files check for a reason that is not a defect.
- name: Install git so the checkout is a clone, not an export
run: apk add --no-cache git
- uses: actions/checkout@v7
- name: Install toolchain
run: apk add --no-cache build-base clang clang-dev llvm-dev rust cargo make bash python3
- run: make build-core
- run: make test-core
- run: cargo test --workspace --release
- run: npm ci --no-audit --no-fund
working-directory: src/bindings/nodejs
- run: npm test
working-directory: src/bindings/nodejs
# ----------------------------------------------------------- sanitizers
sanitizers:
name: Sanitizers (ASan + UBSan)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- run: sudo apt-get update && sudo apt-get install -y clang
- name: C engine under ASan/UBSan
run: make test-core-asan
env:
CC: clang
# Compile-only, so it needs no libFuzzer runtime and gives the same answer
# on every machine: it stops a fuzz target from rotting unnoticed between
# the manual campaigns that actually run them.
- name: Fuzz targets still build
run: make check-fuzz
env:
CC: clang
# --------------------------------------------------------- no-native path
# Proves the JavaScript fallback: the package must load and work with no
# native addon present at all. This is the guarantee that an unsupported
# platform degrades instead of throwing at require() time.
fallback:
name: JS fallback (no native binary)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
cache-dependency-path: src/bindings/nodejs/package-lock.json
- run: npm ci --no-audit --no-fund
working-directory: src/bindings/nodejs
# Scoped to this package's own artifacts. The unqualified sweep this
# replaces also deleted node_modules/@rollup/*/rollup.*.node, and vitest
# loads its config through vite, so the suite died at startup with
# MODULE_NOT_FOUND instead of proving anything about the fallback.
- name: Remove this package's native artifacts
run: find . -name '*.node' -not -path './node_modules/*' -print -delete
working-directory: src/bindings/nodejs
# Deliberately without RETRIGGER_FORCE_JS. The absent binary above is the
# real condition being proved; the environment override is a different
# guarantee, is covered in loader.test.mjs, and setting it here also
# disabled the mock addon that the parity suite installs to exercise the
# native path -- so those tests failed asking for an engine this job had
# forbidden. `parity-native.test.mjs` skips itself when no addon exists.
- name: Suite must pass with no addon
run: npm test
working-directory: src/bindings/nodejs
# The JavaScript engine covers a tree with one recursive watch on Windows,
# because a per-directory handle there drops most of a burst. That strategy
# would otherwise be exercised only by the Windows jobs, which are the
# slowest to report and the least pleasant to debug. macOS serves both, so it
# can hold the same code to the whole suite on every push.
fallback-recursive:
name: JS fallback (recursive watch strategy)
runs-on: macos-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
cache-dependency-path: src/bindings/nodejs/package-lock.json
- run: npm ci --no-audit --no-fund
working-directory: src/bindings/nodejs
- name: Remove this package's native artifacts
run: find . -name '*.node' -not -path './node_modules/*' -print -delete
working-directory: src/bindings/nodejs
- name: Suite must pass with one watch per tree
run: npm test
working-directory: src/bindings/nodejs
env:
RETRIGGER_JS_RECURSIVE: '1'
# ------------------------------------------------------------------- MSRV
msrv:
name: Minimum supported Rust version
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Read rust-version from the workspace manifest
id: msrv
run: echo "version=$(grep -m1 '^rust-version' Cargo.toml | cut -d'"' -f2)" >> "$GITHUB_OUTPUT"
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ steps.msrv.outputs.version }}
- run: sudo apt-get update && sudo apt-get install -y clang
- run: cargo check --workspace --all-targets
# ------------------------------------------------------------------ audit
audit:
name: Dependency audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: actions/setup-node@v7
with:
node-version: 22
- name: cargo audit
run: |
cargo install cargo-audit --locked
cargo audit
- name: npm audit
run: npm audit --audit-level=moderate
working-directory: src/bindings/nodejs
# ------------------------------------------------------------------- gate
# A single required check, so branch protection does not need updating every
# time the matrix changes.
ci-passed:
name: CI passed
if: always()
needs:
[lint, test, test-freebsd, bundler-legs, test-musl, sanitizers, fallback, fallback-recursive, msrv]
runs-on: ubuntu-latest
steps:
- name: Fail if any dependency failed
run: |
if echo '${{ join(needs.*.result, ' ') }}' | grep -qE 'failure|cancelled'; then
echo "One or more required jobs did not succeed."
exit 1
fi
echo "All required jobs succeeded."