Repository navigation
CI: one workflow, planned lanes, toolchain images, and the JavaScriptCore tests #645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
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 f32c715
CI: fail the run when JavaScriptCore tests fail
dylan-conway aa3b110
CI: generate the build lanes from one table in a plan job
dylan-conway 4dbee6f
CI: one workflow instead of build.yml, build-preview.yml and build-re…
dylan-conway c75e652
CI: main and pull requests share everything but the release name
dylan-conway 3085862
Cross-compile bun-webkit-windows-arm64-debug on Linux like every othe…
dylan-conway 5041c7a
CI: build each toolchain once and keep it as an image, instead of onc…
dylan-conway 8b177f0
CI: a toolchain image that cannot be built or pushed fails the run
dylan-conway c2792ed
One tool builds a lane; the six *-release.sh scripts are gone
dylan-conway 07d90c6
CI: a failure in one test does not keep the others from running
dylan-conway e55a912
CI: check out the web-platform-tests the wasm collection reads
dylan-conway 861eb53
Cross-compile the Linux arm64 lanes from x86_64, like every other target
dylan-conway 12745b7
CI: no image job unless a toolchain image is actually missing
dylan-conway 3e218d6
Nothing is downloaded or installed while a lane builds
dylan-conway fe982d1
CI: old toolchain images are deleted, after a grace period
dylan-conway 0048752
CI: no builds for fork pull requests; image tags cover their build ar…
dylan-conway 73b1e15
CI: plan creates the draft release; fix the linux and linux-musl imag…
dylan-conway ed7bdac
Fixes from a review of the CI rework
dylan-conway 63fc612
linux image: link ICU's host tools against the ICU being built
dylan-conway 42e4362
Call the glibc toolchain image linux-glibc
dylan-conway 81193de
Dockerfiles: remove what is dead now that every container is linux/amd64
dylan-conway 30b97c5
Remove build.ts, mac-release.bash and windows-release.ps1
dylan-conway 5d0f49b
One place says which ICU is built, and clang builds it everywhere
dylan-conway a0f500d
Linux arm64: cmake takes programs from the container, not the sysroot
dylan-conway 6981bd1
Test the Linux release lanes too
dylan-conway a06b052
Test the macOS arm64 and Windows x64/arm64 lanes too
dylan-conway f2a5705
Failing tests do not fail the run, for now
dylan-conway 25c5af0
Revert "Failing tests do not fail the run, for now"
dylan-conway 778535e
run-javascriptcore-tests: take --jsc-only on macOS and Windows too
dylan-conway ab82035
Review fixes: test job token, summary on an empty result, arch assert…
dylan-conway 041bf5d
JSCOnly on macOS: one listenForTimeZoneChangeNotifications() in libWTF.a
dylan-conway e04a875
Test job: a log that can be read
dylan-conway 98ac95f
Test job log: show what is known to be useful, not everything but the…
dylan-conway 345bd75
Test job: write jsc-failures.log when tests fail
dylan-conway 95acfba
Test the lto lanes instead of the release lanes
dylan-conway 6f36320
JSTests: expect this fork's ReferenceError text
dylan-conway ef516cb
JSTests: superclass-expression-strictness expects this fork's Referen…
dylan-conway 6ed4fb4
Test baselines: this fork's ReferenceError text
dylan-conway 34a4969
JSTests: module error messages of this fork; a test that tripped over…
dylan-conway dd6b762
jsc: $vm on global objects made by $vm.createGlobalObject() in releas…
dylan-conway a801de0
JSTests: compare the module errors' exact text
dylan-conway bbab5d5
JSTests: build the expected module URLs without a regular expression
dylan-conway 65b551e
JSTests: import-error.js without a helper function
dylan-conway faf7deb
JSTests: the expected module URLs written inline
dylan-conway 39caf5f
JSTests: one call to build each expected module URL
dylan-conway 9fbfdf3
JSTests: intl-datetimeformat-default-timezone-change checks each zone…
dylan-conway e05cdc4
JSTests: the ffi tests run without the executable allocation fuzzer
dylan-conway e2af30e
JSTests: out-of-memory-while-creating-undefined-variable-error expect…
dylan-conway c06f82e
Test job: the asan lanes skip the tests marked slow!
dylan-conway e9df1dc
CLAUDE.md: the asan test lanes pass --no-slow
dylan-conway 4b5bdb8
Test job: --no-slow only where --quick is not passed
dylan-conway 438e22f
CLAUDE.md: the local repro command passes --no-slow like the asan lanes
dylan-conway de06a46
JSTests: regress-151324.js expects this fork's ReferenceError text
dylan-conway 46650cc
The asan lanes are built with USE_SYSTEM_MALLOC
dylan-conway 1bd0367
The Windows asan lane keeps bmalloc/libpas
dylan-conway 41b551c
Test job: --no-testlibjsctools
dylan-conway 90df487
Test job: allow_user_segv_handler=1 in ASAN_OPTIONS
dylan-conway 4b0d518
Test job: tell the driver the architecture on Windows
dylan-conway 103ebca
Test job: the tarball's bin/ is on PATH on Windows
dylan-conway bbbdf37
jsc: open modules on Windows without the CRT's stat
dylan-conway bcdda91
jsc reads the repacked ICU data: the decompression hook, in jsc.cpp
dylan-conway 85372b8
jsc: resolve a file:// module key on Windows; the driver takes cmake'…
dylan-conway 1b4bf94
Tests: native functions print on one line; builtin frames have no URL
dylan-conway 58f2fc6
Layout tests: a cyclic array converts to "" here
dylan-conway d08ab25
Error messages from JSC's own builtins do not depend on the build
dylan-conway 1105a38
JSTests: import attributes and cached string literals, as this fork h…
dylan-conway 5ad4243
JSTests: skip the RegExp buffer boundaries tests until YARR has the f…
dylan-conway 4f3944b
JSTests: say only what is known in the buffer boundaries TODO
dylan-conway 62b5197
[JSC] WasmOperations: divide the frame offset as a signed value
dylan-conway 634aa3d
[JSC] A parse-time SyntaxError keeps the location of the syntax error
dylan-conway f87de33
[JSC] addErrorInfo: what a host's error-info callback computed stands
dylan-conway 64ed537
[JSC] The code cache key tells two sources apart by a 64-bit hash of …
dylan-conway a22fa7f
Revert "[JSC] The code cache key tells two sources apart by a 64-bit …
dylan-conway ebc1e0e
Tests: three fixes for the mode or the lane, not the engine
dylan-conway c3e1e28
regress-174463162.js skips the two modes that collect continuously
dylan-conway 55c9315
regress-174463162.js: the comment does not say Bun
dylan-conway 512c1ae
Tests: --asan, and wasm/regress/298930.js skips it
dylan-conway 7493e96
module-loader-promise-then-tampered.js is skipped, with a TODO
dylan-conway 05af488
wasm core simd_f32x4_cmp.wast.js is skipped on the asan lanes
dylan-conway fd5e735
CI: the asan lanes are not tested
dylan-conway a97e581
CI: only the Linux lto lanes are tested
dylan-conway f324c3c
regexp-unicode-code-unit-read-for-bmp-terms.js: two expectations foll…
dylan-conway b7bc14f
CI: nothing is published when a test fails
dylan-conway 723d63e
class-subclassing-function.js and parse-line-comment.js are skipped, …
dylan-conway 003d64b
Review: three more collect-continuously modes, the wasm log lines, Wi…
dylan-conway dd1ea5e
Review: the workflow's job graph shows test before release; --asan re…
dylan-conway 56aff41
webkitdirs: Windows' native architecture comes from the registry
dylan-conway f49784f
shadow-realm-remote-function-copy-length-and-name.js skips the eager …
dylan-conway f66e3bc
[JSC] A direct tail call to a host function keeps its CodeBlock on th…
dylan-conway 5b7eab1
CI: a failing test does not hold back the release
dylan-conway b6d2430
Merge main; the direct tail call fix is main's
dylan-conway 7022a11
The asan lanes use bmalloc/libpas again
dylan-conway 52ccc30
musl: the aarch64 sysroot has fortify-headers
dylan-conway 4d198c6
musl: the aarch64 target reads the clang configuration the x86_64 one…
dylan-conway 8f8667d
JSTests: a list of where this fork's tests differ from upstream's, an…
dylan-conway a5ca21e
CLAUDE.md points at JSTests/BUN-TEST-DIFFERENCES.md
dylan-conway File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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)}`; | ||
| } | ||
|
|
||
| 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)}`); | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.