Files
scriptc/packages/libnode-common/fetch-dev-pack.mjs
T
Malte UblandClaude Opus 5.5 75aa8509f6 Assemble libnode packs with NI-1's build-pack.mjs and run island tests in CI
Stack the libnode packs on the in-process loader (#1685) and use its
pack assembler and manifest format instead of a second one:
build-pack.mjs keeps its CLI and fields (schema, nodeVersion,
moduleVersion, bridgeAbi, platform, arch, files), adds the libnode and
bridge names, strips and (on macOS) re-signs the bridge and links it with
-z defs, and exports buildPack(), which the platform packs call with their
package, target and build inputs as extra manifest fields.

libnodeRecord falls back to the installed @scriptc/libnode-<platform>
pack, found from the entry's directory and then next to the compiler,
when neither --libnode nor SCRIPTC_LIBNODE names one.

The Linux test lanes restore the libnode build that the libnode-packs
workflow cached, assemble the linux-x64 pack from it in seconds
(build.mjs --from-cache never builds Node) and export SCRIPTC_LIBNODE, so
the Node island corpus and harness tests run instead of skipping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 17:52:22 -07:00

60 lines
2.3 KiB
JavaScript

#!/usr/bin/env node
/* Assembles a development libnode pack from the pinned, checksum-verified
* inputs in dev-pack.json: a prebuilt libnode of the repository's Node
* release and Node's official headers, with the bridge built against them
* by build-pack.mjs. CI's Linux test lanes fall back to it
* (.github/actions/libnode-linux) until the libnode-packs workflow has
* cached a build of @scriptc/libnode-linux-x64-gnu for their ref.
*
* node packages/libnode-common/fetch-dev-pack.mjs --out <pack directory> */
import { execFileSync } from "node:child_process";
import { createHash } from "node:crypto";
import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { parseArgs } from "node:util";
const here = fileURLToPath(new URL(".", import.meta.url));
const { values } = parseArgs({ options: { out: { type: "string" } } });
if (!values.out) {
console.error("usage: fetch-dev-pack.mjs --out <pack directory>");
process.exit(2);
}
const platform = `${process.platform}-${process.arch}`;
const pins = JSON.parse(readFileSync(join(here, "dev-pack.json"), "utf8"))[platform];
if (pins === undefined) {
console.error(`dev-pack.json pins no libnode for ${platform}`);
process.exit(1);
}
const work = mkdtempSync(join(tmpdir(), "scriptc-libnode-dev-"));
async function fetchVerified({ url, sha256 }, name) {
const response = await fetch(url);
if (!response.ok) throw new Error(`${url}: HTTP ${response.status}`);
const bytes = Buffer.from(await response.arrayBuffer());
const actual = createHash("sha256").update(bytes).digest("hex");
if (actual !== sha256) throw new Error(`${url}: sha256 ${actual}, expected ${sha256}`);
const path = join(work, name);
writeFileSync(path, bytes);
execFileSync("tar", ["-xzf", path, "-C", work]);
}
await fetchVerified(pins.libnode, "libnode.tar.gz");
await fetchVerified(pins.headers, "headers.tar.gz");
mkdirSync(resolve(values.out), { recursive: true });
execFileSync(
process.execPath,
[
join(here, "build-pack.mjs"),
"--libnode",
join(work, pins.libnode.file),
"--headers",
join(work, pins.headers.dir),
"--out",
resolve(values.out),
],
{ stdio: "inherit" },
);