Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,23 @@ jobs:
name: nub-${{ matrix.platform }}
path: npm/nub-${{ matrix.platform }}

- name: Assemble loader platform package (addon only)
shell: bash
env:
MATRIX_PLATFORM: ${{ matrix.platform }}
run: |
# The standalone loader (npm/loader) ships the SAME nub-native addon
# staged above, as its own per-platform package — the addon is the only
# platform-specific part of the loader; its JS is a verbatim slice of
# runtime/ that the publish job stages once (scripts/build-loader-npm.mjs).
cp runtime/addons/nub-native.node "npm/loader-$MATRIX_PLATFORM/nub-native.node"

- name: Upload loader platform package
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: loader-${{ matrix.platform }}
path: npm/loader-${{ matrix.platform }}

glibc-floor-guard:
# The real glibc-floor gate. test-install runs on glibc-2.39 hosts and would
# NOT catch a floor regression (0.0.44 shipped a GLIBC_2.39-requiring
Expand Down Expand Up @@ -1600,6 +1617,77 @@ jobs:
with:
path: artifacts

- name: Preflight — loader packages must exist and be trusted on npm
run: |
# npm OIDC cannot perform a package's FIRST publish (npm/cli#8544), so
# the nine loader packages must have been created and trusted once by
# scripts/npm-first-publish-loader.sh. Check EXISTENCE here, before
# anything publishes: without this, @nubjs/nub would publish and then
# the loader step would fail, leaving the two families version-skewed
# on the registry until a manual fix. (Trust configuration cannot be
# read unauthenticated; a missing trust still fails the loader publish
# itself — but that failure now happens before @nubjs/nub goes out.)
missing=0
ROOT="$(node -p "require('./npm/loader/package.json').name")"
for name in "$ROOT" @nubjs/loader-darwin-arm64 @nubjs/loader-darwin-x64 @nubjs/loader-linux-x64 @nubjs/loader-linux-x64-musl @nubjs/loader-linux-arm64 @nubjs/loader-linux-arm64-musl @nubjs/loader-win32-x64 @nubjs/loader-win32-arm64; do
if ! npm view "$name" versions >/dev/null 2>&1; then
echo "::error::$name does not exist on npm — run scripts/npm-first-publish-loader.sh once (see its header) before releasing"
missing=1
fi
done
exit $missing

- name: Prepare and publish loader packages (idempotent)
run: |
# The standalone loader publishes FIRST, deliberately: it is the newest
# package family, so if anything is going to fail it must fail before
# the irreversible @nubjs/nub publishes below — a half-published
# release must never leave @nubjs/nub@X on the registry without its
# matching loader. Within the family: 8 addon-only platform packages,
# then the root LAST (it exact-pins them, same ordering safety as the
# CLI's packages). Same idempotent skip on an already-published
# version. Each platform leg uploaded its addon package
# (loader-<platform> artifact); the root's JS is staged here from this
# checkout by build-loader-npm.mjs (no addon on this runner, by design).
for platform in darwin-arm64 darwin-x64 linux-x64 linux-x64-musl linux-arm64 linux-arm64-musl win32-x64 win32-arm64; do
PKG="artifacts/loader-$platform"
if [ ! -d "$PKG" ]; then
echo "⚠️ Skipping loader-$platform (not built)"
continue
fi
cp "npm/loader-$platform/package.json" "$PKG/package.json"
node -e "
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('$PKG/package.json', 'utf8'));
p.version = process.env.VERSION;
fs.writeFileSync('$PKG/package.json', JSON.stringify(p, null, 2));
"
NAME="@nubjs/loader-$platform"
if [ "$(npm view "$NAME@$VERSION" version 2>/dev/null)" = "$VERSION" ]; then
echo "✓ $NAME@$VERSION already published — skipping"
continue
fi
echo "→ $NAME@$VERSION"
(cd "$PKG" && npm publish --access public)
done
node scripts/build-loader-npm.mjs --addon /nonexistent
node -e "
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('npm/loader/package.json', 'utf8'));
p.version = process.env.VERSION;
for (const k of Object.keys(p.optionalDependencies || {})) {
p.optionalDependencies[k] = process.env.VERSION;
}
fs.writeFileSync('npm/loader/package.json', JSON.stringify(p, null, 2) + '\n');
"
NAME="$(node -p "require('./npm/loader/package.json').name")"
if [ "$(npm view "$NAME@$VERSION" version 2>/dev/null)" = "$VERSION" ]; then
echo "✓ $NAME@$VERSION already published — skipping"
else
echo "→ $NAME@$VERSION"
(cd npm/loader && npm publish --access public)
fi

- name: Prepare and publish platform packages (idempotent)
run: |
# IDEMPOTENT publish: a re-run of this job (after a partial publish, or
Expand Down Expand Up @@ -2282,6 +2370,67 @@ jobs:
with:
path: artifacts

- name: Preflight — loader packages must exist and be trusted on npm
run: |
# Mirrors publish-npm's preflight (keep the two in sync): the loader
# packages must have been first-published + trusted once
# (scripts/npm-first-publish-loader.sh; npm OIDC cannot create a
# package, npm/cli#8544). Fails BEFORE anything publishes.
missing=0
ROOT="$(node -p "require('./npm/loader/package.json').name")"
for name in "$ROOT" @nubjs/loader-darwin-arm64 @nubjs/loader-darwin-x64 @nubjs/loader-linux-x64 @nubjs/loader-linux-x64-musl @nubjs/loader-linux-arm64 @nubjs/loader-linux-arm64-musl @nubjs/loader-win32-x64 @nubjs/loader-win32-arm64; do
if ! npm view "$name" versions >/dev/null 2>&1; then
echo "::error::$name does not exist on npm — run scripts/npm-first-publish-loader.sh once (see its header)"
missing=1
fi
done
exit $missing

- name: Prepare and publish loader packages (idempotent)
run: |
# Mirrors publish-npm's loader step (keep the two in sync): the loader
# family publishes FIRST so a failure lands before @nubjs/nub's
# irreversible publishes below; within the family, platform addon
# packages first, root last, every publish tagged canary.
for platform in darwin-arm64 darwin-x64 linux-x64 linux-x64-musl linux-arm64 linux-arm64-musl win32-x64 win32-arm64; do
PKG="artifacts/loader-$platform"
if [ ! -d "$PKG" ]; then
echo "⚠️ Skipping loader-$platform (not built)"
continue
fi
cp "npm/loader-$platform/package.json" "$PKG/package.json"
node -e "
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('$PKG/package.json', 'utf8'));
p.version = process.env.VERSION;
fs.writeFileSync('$PKG/package.json', JSON.stringify(p, null, 2));
"
NAME="@nubjs/loader-$platform"
if [ "$(npm view "$NAME@$VERSION" version 2>/dev/null)" = "$VERSION" ]; then
echo "✓ $NAME@$VERSION already published — skipping"
continue
fi
echo "→ $NAME@$VERSION (canary)"
(cd "$PKG" && npm publish --access public --tag canary)
done
node scripts/build-loader-npm.mjs --addon /nonexistent
node -e "
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('npm/loader/package.json', 'utf8'));
p.version = process.env.VERSION;
for (const k of Object.keys(p.optionalDependencies || {})) {
p.optionalDependencies[k] = process.env.VERSION;
}
fs.writeFileSync('npm/loader/package.json', JSON.stringify(p, null, 2) + '\n');
"
NAME="$(node -p "require('./npm/loader/package.json').name")"
if [ "$(npm view "$NAME@$VERSION" version 2>/dev/null)" = "$VERSION" ]; then
echo "✓ $NAME@$VERSION already published — skipping"
else
echo "→ $NAME@$VERSION (canary)"
(cd npm/loader && npm publish --access public --tag canary)
fi

- name: Prepare and publish platform packages (idempotent)
run: |
# Same idempotent loop as publish-npm: a re-run skips already-published
Expand Down
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ npm/nub-*/bin/
npm/nub/*.tgz
npm/nub-*/*.tgz

# Standalone-loader packages (npm/loader, npm/loader-<platform>): the JS is a
# verbatim slice of runtime/ staged in by scripts/build-loader-npm.mjs, and the
# addon comes from the platform build — only package.json + README are source.
npm/loader/*.mjs
npm/loader/*.cjs
npm/loader/LICENSE
npm/loader/*.tgz
npm/loader-*/nub-native.node
npm/loader-*/*.tgz

# nub's localStorage/cache leaking into cwd as `0/<node-version>-<arch>-…` when
# XDG_CACHE_HOME is unset and the store path resolves relative (a real nub bug —
# the cache should always live under ~/.cache/nub). Ignore the stray dirs until
Expand Down
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,20 @@ version-check:
const types = JSON.parse(fs.readFileSync('npm/nub-types/package.json', 'utf8')); \
if (types.version !== v) errors.push('npm/nub-types/package.json has ' + types.version + ', expected ' + v); \
} catch { errors.push('missing or unreadable npm/nub-types/package.json'); } \
try { \
const loader = JSON.parse(fs.readFileSync('npm/loader/package.json', 'utf8')); \
if (loader.version !== v) errors.push('npm/loader/package.json has ' + loader.version + ', expected ' + v); \
for (const [dep, ver] of Object.entries(loader.optionalDependencies || {})) { \
if (ver !== v) errors.push(dep + ' optionalDependency pinned at ' + ver + ', expected ' + v); \
const pkg = 'npm/' + dep.replace('@nubjs/', '') + '/package.json'; \
try { \
const p = JSON.parse(fs.readFileSync(pkg, 'utf8')); \
if (p.version !== v) errors.push(pkg + ' has ' + p.version + ', expected ' + v); \
} catch { errors.push('missing or unreadable ' + pkg); } \
} \
const lrt = (loader.dependencies || {})['@oxc-project/runtime']; \
if (!lrt) errors.push('npm/loader/package.json: @oxc-project/runtime missing from dependencies'); \
} catch { errors.push('missing or unreadable npm/loader/package.json'); } \
const cargo = fs.readFileSync('Cargo.toml', 'utf8'); \
const cm = cargo.match(/^version = \x22([^\x22]*)\x22/m); \
if (!cm) errors.push('Cargo.toml: workspace version line not found'); \
Expand Down
16 changes: 16 additions & 0 deletions npm/loader-darwin-arm64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@nubjs/loader-darwin-arm64",
"version": "0.8.1",
"description": "Nub loader native addon for macOS ARM64 (Apple Silicon)",
"license": "MIT",
"repository": "https://github.com/nubjs/nub",
"os": [
"darwin"
],
"cpu": [
"arm64"
],
"files": [
"nub-native.node"
]
}
16 changes: 16 additions & 0 deletions npm/loader-darwin-x64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@nubjs/loader-darwin-x64",
"version": "0.8.1",
"description": "Nub loader native addon for macOS x64 (Intel)",
"license": "MIT",
"repository": "https://github.com/nubjs/nub",
"os": [
"darwin"
],
"cpu": [
"x64"
],
"files": [
"nub-native.node"
]
}
19 changes: 19 additions & 0 deletions npm/loader-linux-arm64-musl/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@nubjs/loader-linux-arm64-musl",
"version": "0.8.1",
"description": "Nub loader native addon for Linux ARM64 (musl)",
"license": "MIT",
"repository": "https://github.com/nubjs/nub",
"os": [
"linux"
],
"cpu": [
"arm64"
],
"files": [
"nub-native.node"
],
"libc": [
"musl"
]
}
19 changes: 19 additions & 0 deletions npm/loader-linux-arm64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@nubjs/loader-linux-arm64",
"version": "0.8.1",
"description": "Nub loader native addon for Linux ARM64 (glibc)",
"license": "MIT",
"repository": "https://github.com/nubjs/nub",
"os": [
"linux"
],
"cpu": [
"arm64"
],
"files": [
"nub-native.node"
],
"libc": [
"glibc"
]
}
19 changes: 19 additions & 0 deletions npm/loader-linux-x64-musl/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@nubjs/loader-linux-x64-musl",
"version": "0.8.1",
"description": "Nub loader native addon for Linux x64 (musl)",
"license": "MIT",
"repository": "https://github.com/nubjs/nub",
"os": [
"linux"
],
"cpu": [
"x64"
],
"files": [
"nub-native.node"
],
"libc": [
"musl"
]
}
19 changes: 19 additions & 0 deletions npm/loader-linux-x64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@nubjs/loader-linux-x64",
"version": "0.8.1",
"description": "Nub loader native addon for Linux x64 (glibc)",
"license": "MIT",
"repository": "https://github.com/nubjs/nub",
"os": [
"linux"
],
"cpu": [
"x64"
],
"files": [
"nub-native.node"
],
"libc": [
"glibc"
]
}
16 changes: 16 additions & 0 deletions npm/loader-win32-arm64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@nubjs/loader-win32-arm64",
"version": "0.8.1",
"description": "Nub loader native addon for Windows ARM64",
"license": "MIT",
"repository": "https://github.com/nubjs/nub",
"os": [
"win32"
],
"cpu": [
"arm64"
],
"files": [
"nub-native.node"
]
}
16 changes: 16 additions & 0 deletions npm/loader-win32-x64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@nubjs/loader-win32-x64",
"version": "0.8.1",
"description": "Nub loader native addon for Windows x64",
"license": "MIT",
"repository": "https://github.com/nubjs/nub",
"os": [
"win32"
],
"cpu": [
"x64"
],
"files": [
"nub-native.node"
]
}
Loading
Loading