Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
9d8f7a6
CI: run the JavaScriptCore tests against the Linux asan builds
dylan-conway Sep 13, 2026
f32c715
CI: fail the run when JavaScriptCore tests fail
dylan-conway Sep 13, 2026
aa3b110
CI: generate the build lanes from one table in a plan job
dylan-conway Sep 13, 2026
4dbee6f
CI: one workflow instead of build.yml, build-preview.yml and build-re…
dylan-conway Sep 13, 2026
c75e652
CI: main and pull requests share everything but the release name
dylan-conway Sep 13, 2026
3085862
Cross-compile bun-webkit-windows-arm64-debug on Linux like every othe…
dylan-conway Sep 13, 2026
5041c7a
CI: build each toolchain once and keep it as an image, instead of onc…
dylan-conway Sep 13, 2026
8b177f0
CI: a toolchain image that cannot be built or pushed fails the run
dylan-conway Sep 13, 2026
c2792ed
One tool builds a lane; the six *-release.sh scripts are gone
dylan-conway Sep 13, 2026
07d90c6
CI: a failure in one test does not keep the others from running
dylan-conway Sep 13, 2026
e55a912
CI: check out the web-platform-tests the wasm collection reads
dylan-conway Sep 13, 2026
861eb53
Cross-compile the Linux arm64 lanes from x86_64, like every other target
dylan-conway Sep 13, 2026
12745b7
CI: no image job unless a toolchain image is actually missing
dylan-conway Sep 13, 2026
3e218d6
Nothing is downloaded or installed while a lane builds
dylan-conway Sep 13, 2026
fe982d1
CI: old toolchain images are deleted, after a grace period
dylan-conway Sep 13, 2026
0048752
CI: no builds for fork pull requests; image tags cover their build ar…
dylan-conway Sep 13, 2026
73b1e15
CI: plan creates the draft release; fix the linux and linux-musl imag…
dylan-conway Sep 13, 2026
ed7bdac
Fixes from a review of the CI rework
dylan-conway Sep 13, 2026
63fc612
linux image: link ICU's host tools against the ICU being built
dylan-conway Sep 13, 2026
42e4362
Call the glibc toolchain image linux-glibc
dylan-conway Sep 13, 2026
81193de
Dockerfiles: remove what is dead now that every container is linux/amd64
dylan-conway Sep 13, 2026
30b97c5
Remove build.ts, mac-release.bash and windows-release.ps1
dylan-conway Sep 13, 2026
5d0f49b
One place says which ICU is built, and clang builds it everywhere
dylan-conway Sep 13, 2026
a0f500d
Linux arm64: cmake takes programs from the container, not the sysroot
dylan-conway Sep 13, 2026
6981bd1
Test the Linux release lanes too
dylan-conway Sep 13, 2026
a06b052
Test the macOS arm64 and Windows x64/arm64 lanes too
dylan-conway Sep 13, 2026
f2a5705
Failing tests do not fail the run, for now
dylan-conway Sep 13, 2026
25c5af0
Revert "Failing tests do not fail the run, for now"
dylan-conway Sep 13, 2026
778535e
run-javascriptcore-tests: take --jsc-only on macOS and Windows too
dylan-conway Sep 13, 2026
ab82035
Review fixes: test job token, summary on an empty result, arch assert…
dylan-conway Sep 13, 2026
041bf5d
JSCOnly on macOS: one listenForTimeZoneChangeNotifications() in libWTF.a
dylan-conway Sep 13, 2026
e04a875
Test job: a log that can be read
dylan-conway Sep 13, 2026
98ac95f
Test job log: show what is known to be useful, not everything but the…
dylan-conway Sep 13, 2026
345bd75
Test job: write jsc-failures.log when tests fail
dylan-conway Sep 13, 2026
95acfba
Test the lto lanes instead of the release lanes
dylan-conway Sep 13, 2026
6f36320
JSTests: expect this fork's ReferenceError text
dylan-conway Sep 13, 2026
ef516cb
JSTests: superclass-expression-strictness expects this fork's Referen…
dylan-conway Sep 13, 2026
6ed4fb4
Test baselines: this fork's ReferenceError text
dylan-conway Sep 13, 2026
34a4969
JSTests: module error messages of this fork; a test that tripped over…
dylan-conway Sep 13, 2026
dd6b762
jsc: $vm on global objects made by $vm.createGlobalObject() in releas…
dylan-conway Sep 13, 2026
a801de0
JSTests: compare the module errors' exact text
dylan-conway Sep 13, 2026
bbab5d5
JSTests: build the expected module URLs without a regular expression
dylan-conway Sep 13, 2026
65b551e
JSTests: import-error.js without a helper function
dylan-conway Sep 13, 2026
faf7deb
JSTests: the expected module URLs written inline
dylan-conway Sep 13, 2026
39caf5f
JSTests: one call to build each expected module URL
dylan-conway Sep 13, 2026
9fbfdf3
JSTests: intl-datetimeformat-default-timezone-change checks each zone…
dylan-conway Sep 13, 2026
e05cdc4
JSTests: the ffi tests run without the executable allocation fuzzer
dylan-conway Sep 13, 2026
e2af30e
JSTests: out-of-memory-while-creating-undefined-variable-error expect…
dylan-conway Sep 13, 2026
c06f82e
Test job: the asan lanes skip the tests marked slow!
dylan-conway Sep 13, 2026
e9df1dc
CLAUDE.md: the asan test lanes pass --no-slow
dylan-conway Sep 13, 2026
4b5bdb8
Test job: --no-slow only where --quick is not passed
dylan-conway Sep 13, 2026
438e22f
CLAUDE.md: the local repro command passes --no-slow like the asan lanes
dylan-conway Sep 13, 2026
de06a46
JSTests: regress-151324.js expects this fork's ReferenceError text
dylan-conway Sep 13, 2026
46650cc
The asan lanes are built with USE_SYSTEM_MALLOC
dylan-conway Sep 13, 2026
1bd0367
The Windows asan lane keeps bmalloc/libpas
dylan-conway Sep 13, 2026
41b551c
Test job: --no-testlibjsctools
dylan-conway Sep 13, 2026
90df487
Test job: allow_user_segv_handler=1 in ASAN_OPTIONS
dylan-conway Sep 13, 2026
4b0d518
Test job: tell the driver the architecture on Windows
dylan-conway Sep 13, 2026
103ebca
Test job: the tarball's bin/ is on PATH on Windows
dylan-conway Sep 13, 2026
bbbdf37
jsc: open modules on Windows without the CRT's stat
dylan-conway Sep 13, 2026
bcdda91
jsc reads the repacked ICU data: the decompression hook, in jsc.cpp
dylan-conway Sep 13, 2026
85372b8
jsc: resolve a file:// module key on Windows; the driver takes cmake'…
dylan-conway Sep 13, 2026
1b4bf94
Tests: native functions print on one line; builtin frames have no URL
dylan-conway Sep 13, 2026
58f2fc6
Layout tests: a cyclic array converts to "" here
dylan-conway Sep 13, 2026
d08ab25
Error messages from JSC's own builtins do not depend on the build
dylan-conway Sep 13, 2026
1105a38
JSTests: import attributes and cached string literals, as this fork h…
dylan-conway Sep 13, 2026
5ad4243
JSTests: skip the RegExp buffer boundaries tests until YARR has the f…
dylan-conway Sep 13, 2026
4f3944b
JSTests: say only what is known in the buffer boundaries TODO
dylan-conway Sep 13, 2026
62b5197
[JSC] WasmOperations: divide the frame offset as a signed value
dylan-conway Sep 13, 2026
634aa3d
[JSC] A parse-time SyntaxError keeps the location of the syntax error
dylan-conway Sep 13, 2026
f87de33
[JSC] addErrorInfo: what a host's error-info callback computed stands
dylan-conway Sep 13, 2026
64ed537
[JSC] The code cache key tells two sources apart by a 64-bit hash of …
dylan-conway Sep 13, 2026
a22fa7f
Revert "[JSC] The code cache key tells two sources apart by a 64-bit …
dylan-conway Sep 13, 2026
ebc1e0e
Tests: three fixes for the mode or the lane, not the engine
dylan-conway Sep 13, 2026
c3e1e28
regress-174463162.js skips the two modes that collect continuously
dylan-conway Sep 13, 2026
55c9315
regress-174463162.js: the comment does not say Bun
dylan-conway Sep 14, 2026
512c1ae
Tests: --asan, and wasm/regress/298930.js skips it
dylan-conway Sep 14, 2026
7493e96
module-loader-promise-then-tampered.js is skipped, with a TODO
dylan-conway Sep 14, 2026
05af488
wasm core simd_f32x4_cmp.wast.js is skipped on the asan lanes
dylan-conway Sep 14, 2026
fd5e735
CI: the asan lanes are not tested
dylan-conway Sep 14, 2026
a97e581
CI: only the Linux lto lanes are tested
dylan-conway Sep 14, 2026
f324c3c
regexp-unicode-code-unit-read-for-bmp-terms.js: two expectations foll…
dylan-conway Sep 14, 2026
b7bc14f
CI: nothing is published when a test fails
dylan-conway Sep 14, 2026
723d63e
class-subclassing-function.js and parse-line-comment.js are skipped, …
dylan-conway Sep 14, 2026
003d64b
Review: three more collect-continuously modes, the wasm log lines, Wi…
dylan-conway Sep 14, 2026
dd1ea5e
Review: the workflow's job graph shows test before release; --asan re…
dylan-conway Sep 14, 2026
56aff41
webkitdirs: Windows' native architecture comes from the registry
dylan-conway Sep 14, 2026
f49784f
shadow-realm-remote-function-copy-length-and-name.js skips the eager …
dylan-conway Sep 14, 2026
f66e3bc
[JSC] A direct tail call to a host function keeps its CodeBlock on th…
dylan-conway Sep 14, 2026
5b7eab1
CI: a failing test does not hold back the release
dylan-conway Sep 14, 2026
b6d2430
Merge main; the direct tail call fix is main's
dylan-conway Sep 14, 2026
7022a11
The asan lanes use bmalloc/libpas again
dylan-conway Sep 14, 2026
52ccc30
musl: the aarch64 sysroot has fortify-headers
dylan-conway Sep 14, 2026
4d198c6
musl: the aarch64 target reads the clang configuration the x86_64 one…
dylan-conway Sep 14, 2026
8f8667d
JSTests: a list of where this fork's tests differ from upstream's, an…
dylan-conway Sep 14, 2026
a5ca21e
CLAUDE.md points at JSTests/BUN-TEST-DIFFERENCES.md
dylan-conway Sep 14, 2026
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
298 changes: 298 additions & 0 deletions .github/scripts/lanes.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
#!/usr/bin/env node
// The lanes of bun-webkit: what is built, where, from which Dockerfile and with exactly which settings, and which lanes
// are tested. One lane is one <label>.tar.gz on the release. This file is the only place that says any of it, and the
// only way a lane is built, in CI (.github/workflows/ci.yml) and by hand:
//
// node .github/scripts/lanes.mjs list the lanes and their toolchain images
// node .github/scripts/lanes.mjs --json the same, in full
// node .github/scripts/lanes.mjs build <label> --output <dir> build a lane into <dir>, like CI does
// [--base-image <ref>] ... starting from a prebuilt toolchain image
// node .github/scripts/lanes.mjs image <name> --push build a toolchain image and push it to its ref
// node .github/scripts/lanes.mjs plan the outputs of the workflow's `plan` job
//
// `build` and `image` take --dry-run, which prints the docker command instead of running it.
//
// A lane is built by `docker buildx build` of its platform's Dockerfile. The Dockerfile's `base` stage is the
// toolchain (compilers, SDKs, sysroots) and takes no lane setting; the stages on top build ICU and WebKit from the
// build arguments below. To add, drop, change or test a lane, change `platforms` and nothing else.

import { spawnSync } from "node:child_process";
import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const root = join(dirname(fileURLToPath(import.meta.url)), "../..");
// Where the toolchain images are kept.
const REGISTRY = `ghcr.io/${(process.env.GITHUB_REPOSITORY_OWNER ?? "oven-sh").toLowerCase()}/bun-webkit-build-env`;

const X64 = "linux-x64-gh";
const ARM64 = "linux-arm64-gh";

// ThinLTO: the bitcode carries ThinLTO summaries, so the consumer's link gets parallel backends and cross-language
// importing instead of one giant serial full-LTO module. -fno-split-lto-unit keeps every module a pure summary module
// (consistent with rustc's bitcode, which never splits).
const LTO = "-flto=thin -fno-split-lto-unit -fwhole-program-vtables -fforce-emit-vtables";
// On Windows there is no -fwhole-program-vtables -fforce-emit-vtables: whole-program devirtualization drops vtable
// symbols that COFF associative COMDAT sections still name as their parent, and the LTO codegen aborts
// ("Associative COMDAT symbol '??_7...' does not exist").
const LTO_WINDOWS = "/clang:-flto=thin /clang:-fno-split-lto-unit";

const SANITIZERS = "address,undefined";

// The code generation floor. There is one per architecture: WebKit used to ship a haswell x64 build next to a nehalem
// "baseline" one, which meant every x64 consumer had to pick, and a consumer that picked wrong either raised its CPU
// requirement silently or gave up cross-language LTO because the matching variant did not exist. A consumer that wants
// a higher floor for its own code can still set one, it just does not get it inside JSC.
const NEHALEM = "-march=nehalem";
const ARMV8 = "-march=armv8-a+crc";

// The variant is the label's suffix: bun-webkit-linux-amd64 is "release", bun-webkit-linux-amd64-debug-asan is
// "debug-asan". The optimized variants that ship in bun use mimalloc, which bun links itself (USE_EXTERNAL_MIMALLOC).
const variants = {
"release": { buildType: "Release", mimalloc: true },
"lto": { buildType: "Release", mimalloc: true, lto: true },
"debug": { buildType: "Debug" },
"asan": { buildType: "Release", sanitizers: SANITIZERS },
"debug-asan": { buildType: "Debug", sanitizers: SANITIZERS },
};
const ALL = Object.keys(variants);
const NO_ASAN = ["release", "lto", "debug"];

// Each platform:
// label(arch) the label of the release variant; the other variants append -<variant>
// dockerfile builds the lane: `base` is the toolchain, the stages on top build ICU and WebKit
// native the lane runs on the machine that builds it, so it builds on a runner of its own architecture.
// Everything else is cross-compiled from linux x64.
// packageOS the "os" of the tarball's package.json
// lanes arch -> variants built for it
// args(arch, v) the Dockerfile's build arguments, on top of WEBKIT_RELEASE_TYPE, LTO_FLAG and USE_*_MIMALLOC
// image(arch) the name of the toolchain image, one per distinct `base` stage: per architecture where the
// Dockerfile runs natively or its `base` carries a per-architecture sysroot. See `images` below.
// imageInputs files the `base` stage copies in, besides the Dockerfile
// tested variants whose jsc shell the `test` job runs the JavaScriptCore tests with. Those have to be able to
// run on the runner that built them, and want assertions: a plain Release build compiles out $vm and
// the JIT disassembler (BUN_ENABLE_JSDOLLARVM / BUN_ENABLE_JIT_DISASSEMBLER default to ASSERT_ENABLED).
const platforms = [
{
name: "linux",
label: arch => `bun-webkit-linux-${arch}`,
dockerfile: "Dockerfile",
native: true,
packageOS: "linux",
lanes: { amd64: ALL, arm64: ALL },
tested: ["asan"],
image: arch => `linux-${arch}`,
args: (arch, v) => ({
RELEASE_FLAGS: "-O3 -DNDEBUG=1",
ENABLE_SANITIZERS: v.sanitizers ?? "",
// Explicit --target: Ubuntu's clang defaults to x86_64-pc-linux-gnu, while bun's own objects and its Rust code
// are <arch>-unknown-linux-gnu; with LTO, lld warns about the vendor mismatch once per JavaScriptCore object.
MARCH_FLAG:
arch === "arm64"
? `--target=aarch64-unknown-linux-gnu ${ARMV8} -mtune=ampere1`
: `--target=x86_64-unknown-linux-gnu ${NEHALEM}`,
}),
},
{
name: "linux-musl",
label: arch => `bun-webkit-linux-${arch}-musl`,
dockerfile: "Dockerfile.musl",
native: true,
packageOS: "linux",
lanes: { amd64: NO_ASAN, arm64: NO_ASAN },
buildType: v => (v.buildType === "Release" ? "MinSizeRel" : v.buildType),
image: arch => `linux-musl-${arch}`,
args: arch => ({ MARCH_FLAG: arch === "arm64" ? `${ARMV8} -mtune=ampere1` : NEHALEM }),
},
{
// clang --target + a pinned macOS SDK, linked with ld64.lld. mac-release.bash remains for building on a real Mac.
name: "macos",
label: arch => `bun-webkit-macos-${arch}`,
dockerfile: "Dockerfile.macos",
packageOS: "darwin",
// ASAN is arm64 only: the darwin sanitizer runtime (mirrored at the compiler-rt-darwin-* release tag, a Linux LLVM
// install doesn't ship it) is extracted from the official LLVM macOS release, which is published for arm64 only.
lanes: { arm64: ALL, amd64: NO_ASAN },
image: arch => `macos-${arch}`,
imageInputs: ["macos-cross/xmac.mjs"],
args: (arch, v, variant) => ({
MACOS_ARCH: arch === "arm64" ? "arm64" : "x86_64",
MACOS_DEPLOYMENT_TARGET: "13.0",
MARCH_FLAG: arch === "arm64" ? "-mcpu=apple-m1" : NEHALEM,
CPP_FLAGS: v.mimalloc ? "" : "-D_LIBCXX_ENABLE_ASSERTIONS=1",
ENABLE_SANITIZERS: v.sanitizers ?? "",
// Debug builds break the heap down by type, except under ASAN.
ENABLE_MALLOC_HEAP_BREAKDOWN: variant === "debug" ? "ON" : "OFF",
}),
},
{
// clang-cl --target + an xwin-downloaded MSVC CRT and Windows SDK + lld-link. windows-release.ps1 remains for
// building on a real Windows machine.
name: "windows",
label: arch => `bun-webkit-windows-${arch}`,
dockerfile: "Dockerfile.windows",
packageOS: "windows",
lanes: {
// ASAN is x64 only: LLVM ships no Windows ARM64 ASAN runtime. The sanitizer runtime (import lib, /MT runtime
// thunk, DLL) comes from the compiler-rt-windows-* release tag.
amd64: ["release", "lto", "debug", "asan"],
// No arm64 lto: LLVM 21's CodeView emitter has no register mapping for ARM64 NEON quad-register tuples
// ("LLVM ERROR: unknown codeview register Q22_Q23_Q24_Q25") and the LTO codegen allocates values into them.
arm64: ["release", "debug"],
},
lto: LTO_WINDOWS,
image: () => "windows",
args: (arch, v) => ({
WIN_ARCH: arch === "arm64" ? "arm64" : "x64",
WIN_TRIPLE_ARCH: arch === "arm64" ? "aarch64" : "x86_64",
// WebKit is built by clang-cl, ICU by clang's GNU driver.
MARCH_FLAG: `/clang:${arch === "arm64" ? ARMV8 : NEHALEM}`,
ICU_MARCH_FLAG: arch === "arm64" ? ARMV8 : NEHALEM,
ENABLE_SANITIZERS: v.sanitizers ?? "",
}),
},
{
// clang --target + a base.txz sysroot.
name: "freebsd",
label: arch => `bun-webkit-freebsd-${arch}`,
dockerfile: "Dockerfile.freebsd",
packageOS: "freebsd",
lanes: { amd64: NO_ASAN, arm64: NO_ASAN },
image: arch => `freebsd-${arch}`,
args: arch => ({
FREEBSD_ARCH: arch === "arm64" ? "aarch64" : "x86_64",
FREEBSD_VERSION: "14.3",
MARCH_FLAG: arch === "arm64" ? `${ARMV8} -mtune=ampere1` : NEHALEM,
}),
},
{
// The NDK, which only ships linux-x86_64 prebuilts.
name: "android",
label: arch => `bun-webkit-linux-${arch}-android`,
dockerfile: "Dockerfile.android",
packageOS: "android",
lanes: { arm64: NO_ASAN, amd64: NO_ASAN },
image: () => "android",
args: arch => ({
ANDROID_ARCH: arch === "arm64" ? "aarch64" : "x86_64",
ANDROID_API: "28",
MARCH_FLAG: arch === "arm64" ? `${ARMV8} -mtune=cortex-a78` : NEHALEM,
}),
},
];

// A toolchain image is tagged with a hash of what goes into it: the Dockerfile up to the end of its `base` stage and
// the files that stage copies in. Changing either makes a new tag, which the `image` job finds missing and builds;
// changing anything else (the ICU or WebKit stages, the sources) leaves it alone.
function imageRef(platform, arch) {
const dockerfile = readFileSync(join(root, platform.dockerfile), "utf8");
const base = /^FROM\s.*\sAS\s+base\s*$/im.exec(dockerfile);
if (!base) throw new Error(`${platform.dockerfile} has no \`base\` stage`);
const next = /^FROM\s/m.exec(dockerfile.slice(base.index + base[0].length));
const hash = createHash("sha256").update(next ? dockerfile.slice(0, base.index + base[0].length + next.index) : dockerfile);
for (const input of platform.imageInputs ?? []) hash.update(readFileSync(join(root, input)));
return `${REGISTRY}:${platform.image(arch)}-${hash.digest("hex").slice(0, 16)}`;
Comment thread
dylan-conway marked this conversation as resolved.
Resolved
}

const lanes = platforms.flatMap(platform =>
Object.entries(platform.lanes).flatMap(([arch, names]) =>
names.map(variant => {
const v = variants[variant];
const buildType = platform.buildType?.(v) ?? v.buildType;
return {
label: platform.label(arch) + (variant === "release" ? "" : `-${variant}`),
runner: platform.native && arch === "arm64" ? ARM64 : X64,
dockerfile: platform.dockerfile,
docker_platform: platform.native && arch === "arm64" ? "linux/arm64" : "linux/amd64",
package_os: platform.packageOS,
package_cpu: arch === "arm64" ? "arm64" : "x64",
test: platform.tested?.includes(variant) ?? false,
image: imageRef(platform, arch),
build_args: {
WEBKIT_RELEASE_TYPE: buildType,
LTO_FLAG: v.lto ? (platform.lto ?? LTO) : "",
USE_MIMALLOC: v.mimalloc ? "ON" : "OFF",
USE_EXTERNAL_MIMALLOC: v.mimalloc ? "ON" : "OFF",
...platform.args(arch, v, variant),
},
};
}),
),
);

const labels = lanes.map(lane => lane.label);
const duplicate = labels.find((label, i) => labels.indexOf(label) !== i);
if (duplicate) throw new Error(`two lanes are called ${duplicate}`);

// The toolchain images the lanes start from. One is built by the first lane that uses it: the `base` stage does not
// read the lane's build arguments, only the ones that say which toolchain it is (MACOS_ARCH, FREEBSD_ARCH, ...).
const images = [...new Map(lanes.toReversed().map(lane => [lane.image, lane])).values()].toReversed().map(lane => ({
name: lane.image.slice(REGISTRY.length + 1, lane.image.lastIndexOf("-")),
image: lane.image,
runner: lane.runner,
lane,
}));

function docker(lane, rest, dryRun) {
const argv = ["buildx", "build", "-f", lane.dockerfile, "--platform", lane.docker_platform, "--progress=plain"];
for (const [key, value] of Object.entries(lane.build_args)) argv.push("--build-arg", `${key}=${value}`);
argv.push(...rest, ".");
if (dryRun) return console.log(JSON.stringify(["docker", ...argv]));
console.error(`docker ${argv.map(arg => (/^[\w./:=,-]+$/.test(arg) ? arg : `'${arg}'`)).join(" ")}`);
const { status, error } = spawnSync("docker", argv, { cwd: root, stdio: "inherit" });
if (error) throw error;
process.exit(status ?? 1);
}

function option(args, name) {
const i = args.indexOf(name);
return i === -1 ? undefined : (args[i + 1] ?? fail(`${name} takes a value`));
}

function fail(message) {
console.error(message);
process.exit(2);
}

const [command, ...args] = process.argv.slice(2);
if (command === "build") {
const lane = lanes.find(lane => lane.label === args[0]) ?? fail(`no lane is called ${args[0]}; run this with no arguments for the list`);
const output = option(args, "--output") ?? fail("build takes --output <dir>");
const baseImage = option(args, "--base-image");
docker(
lane,
[
// In place of building the Dockerfile's `base` stage.
...(baseImage ? ["--build-context", `base=docker-image://${baseImage}`] : []),
"--target=artifact",
"--output",
`type=local,dest=${resolve(output)}`,
],
args.includes("--dry-run"),
);
} else if (command === "image") {
const image = images.find(image => image.name === args[0]) ?? fail(`no image is called ${args[0]}: ${images.map(image => image.name).join(", ")}`);
if (!args.includes("--push")) fail("image takes --push");
// --provenance=false: a plain image manifest, not an index with an attestation hanging off it.
docker(image.lane, ["--target=base", "--tag", image.image, "--provenance=false", "--push"], args.includes("--dry-run"));
} else if (command === "plan") {
const matrix = include => JSON.stringify({ include });
const build = ({ label, runner, image, package_os, package_cpu }) => ({ label, runner, image, package_os, package_cpu });
console.log(`build=${matrix(lanes.filter(lane => !lane.test).map(build))}`);
console.log(`build_tested=${matrix(lanes.filter(lane => lane.test).map(build))}`);
console.log(`test=${matrix(lanes.filter(lane => lane.test).map(({ label, runner }) => ({ label, runner })))}`);
console.log(`labels=${JSON.stringify(labels)}`);
console.log(`images=${matrix(images.map(({ name, image, runner }) => ({ name, image, runner })))}`);
} else if (command === "--json") {
console.log(JSON.stringify(lanes, null, 2));
} else if (command === undefined) {
for (const lane of lanes) {
console.log(`${lane.label.padEnd(42)} ${lane.runner.padEnd(15)} ${lane.dockerfile.padEnd(19)} ${lane.build_args.WEBKIT_RELEASE_TYPE}${lane.test ? " (tested)" : ""}`);
}
console.log(`${lanes.length} lanes`);
for (const { image, runner } of images) console.log(`${image} ${runner}`);
console.log(`${images.length} toolchain images`);
} else {
fail(`unknown command ${command}; see the top of ${fileURLToPath(import.meta.url)}`);
}
Loading
Loading