From a17e5851d66ce417f5bba3f7c064d42999a8d040 Mon Sep 17 00:00:00 2001 From: Jeffery Lofoneh Asamani Date: Tue, 15 Sep 2026 00:34:10 +0000 Subject: [PATCH] test(npm): run the pack smoke through bun as well as npm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pack-smoke.sh proved the tarball install only under npm, so a wrapper change that broke bun (bin linking, optionalDependency os/cpu filtering, or the wrapper under bun's own runtime) would pass CI and fail for a bunx user. The script now takes the managers to exercise as arguments — default npm, CI passes `npm bun` — builds and packs once, and installs into a fresh project per manager with lifecycle scripts disabled. A manager that is asked for but not installed fails the run rather than being skipped. The bun leg also runs the wrapper with `bun --bun`, since bun's node-API layer can break independently of its installer. package.json is written by hand instead of `npm init`/`bun init` so the script still touches no registry. --- .github/workflows/ci.yml | 11 +++++-- npm/test/pack-smoke.sh | 66 +++++++++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 891e539..8afa5ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -261,6 +261,9 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 20 + - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 + with: + bun-version: 1.x - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version-file: go.mod @@ -270,6 +273,8 @@ jobs: run: node --test npm/test/*.test.mjs # DoD 10: `npm install --ignore-scripts` produces a working install. Builds # the real binary, packs the wrapper + this platform's package, installs the - # tarballs with --ignore-scripts, and runs `pgbot --version` through it. - - name: pack + --ignore-scripts install smoke - run: bash npm/test/pack-smoke.sh + # tarballs with --ignore-scripts, and runs `pgbot --version` through it — + # once per package manager, so a wrapper change that only breaks bun fails + # here rather than for a bunx user. + - name: pack + --ignore-scripts install smoke (npm, bun) + run: bash npm/test/pack-smoke.sh npm bun diff --git a/npm/test/pack-smoke.sh b/npm/test/pack-smoke.sh index 0175845..6fb7e26 100755 --- a/npm/test/pack-smoke.sh +++ b/npm/test/pack-smoke.sh @@ -4,13 +4,24 @@ # package, install the tarballs with --ignore-scripts, and run `pgbot --version` # through the installed wrapper. Proves the install needs no lifecycle scripts and # that the wrapper resolves + execs the binary. No registry, no publish. +# +# Usage: pack-smoke.sh [manager...] — default npm; CI passes `npm bun`. +# The tarballs are built once and installed by every manager named, each into +# its own project: a wrapper change that only breaks bun would otherwise pass an +# npm-only smoke unnoticed. set -euo pipefail +[ $# -gt 0 ] || set -- npm root="$(cd "$(dirname "$0")/../.." && pwd)" work="$(mktemp -d)" trap 'rm -rf "$work"' EXIT version="0.0.0-smoke" +# Hard-require rather than soft-skip: a skipped leg reports green for a manager it never ran. +for pm in "$@"; do + command -v "$pm" >/dev/null || { echo "✗ $pm is not installed — pass only the managers you have; CI passes them all" >&2; exit 1; } +done + goos="$(cd "$root" && go env GOOS)" goarch="$(cd "$root" && go env GOARCH)" exe="pgbot" @@ -32,18 +43,43 @@ mkdir -p "$work/tarballs" ( cd "$work/staging/@pgbot/$platkey" && npm pack --pack-destination "$work/tarballs" >/dev/null 2>&1 ) ( cd "$work/staging/pgbot" && npm pack --pack-destination "$work/tarballs" >/dev/null 2>&1 ) -echo "→ install with --ignore-scripts" -proj="$work/proj"; mkdir -p "$proj" -( cd "$proj" && npm init -y >/dev/null 2>&1 ) -# Install both tarballs explicitly; the wrapper's other-platform optionalDeps are -# skipped (not published) but that is not fatal — that's the whole point. -( cd "$proj" && npm install --ignore-scripts --no-save --no-audit --no-fund \ - "$work/tarballs"/pgbot-*.tgz "$work/tarballs"/pgbot-"$platkey"-*.tgz >/dev/null 2>&1 ) - -echo "→ run pgbot --version through the installed wrapper" -out="$("$proj/node_modules/.bin/pgbot" --version)" -echo " $out" -case "$out" in - "pgbot version"*) echo "✓ pack-smoke OK ($platkey, --ignore-scripts)";; - *) echo "✗ unexpected --version output: $out"; exit 1;; -esac +# Install both tarballs into a fresh project with lifecycle scripts disabled. The +# wrapper's other-platform optionalDeps are skipped (not published) — that's the +# point. package.json is written by hand: `bun init` would hit the registry. +install_with() { + local pm="$1" proj="$work/proj-$1" + mkdir -p "$proj" + printf '{"name":"pgbot-smoke","private":true}\n' > "$proj/package.json" + case "$pm" in + npm) ( cd "$proj" && npm install --ignore-scripts --no-save --no-audit --no-fund \ + "$work/tarballs"/pgbot-*.tgz >/dev/null 2>&1 ) ;; + bun) ( cd "$proj" && bun add --ignore-scripts "$work/tarballs"/pgbot-*.tgz >/dev/null 2>&1 ) ;; + *) echo "✗ no install recipe for package manager '$pm'" >&2; exit 1 ;; + esac + echo "$proj" +} + +for pm in "$@"; do + echo "→ $pm install with --ignore-scripts" + proj="$(install_with "$pm")" + + echo "→ run pgbot --version through the $pm-installed wrapper" + out="$("$proj/node_modules/.bin/pgbot" --version)" + echo " $out" + case "$out" in + "pgbot version"*) echo "✓ pack-smoke OK ($platkey, $pm, --ignore-scripts)";; + *) echo "✗ unexpected --version output via $pm: $out"; exit 1;; + esac + + # The .bin shim runs the wrapper under node; `bunx --bun` runs it under bun's + # runtime, whose node-API compatibility (spawn, signals) can break separately. + if [ "$pm" = bun ]; then + echo "→ run the wrapper under bun's runtime (--bun)" + out="$(bun --bun "$proj/node_modules/@pgbot/cli/bin/pgbot.js" --version)" + echo " $out" + case "$out" in + "pgbot version"*) echo "✓ wrapper OK under bun runtime";; + *) echo "✗ unexpected --version output under bun runtime: $out"; exit 1;; + esac + fi +done