Harden sandbox gate across host platforms

- Retain representative Darwin kqueue coverage in the default gate.
- Schedule native runtime tests by host and make Linux clang invocations portable.
- Resolve canonical OCI manifest digests for direct and indexed images.
This commit is contained in:
Chris Tate
2026-07-28 17:48:17 -05:00
parent 61d399bb7a
commit 177d025452
14 changed files with 261 additions and 71 deletions
+31
View File
@@ -0,0 +1,31 @@
const IMAGE_MANIFEST_MEDIA_TYPES = new Set([
"application/vnd.oci.image.manifest.v1+json",
"application/vnd.docker.distribution.manifest.v2+json",
]);
/**
* Resolve the descriptor digest VCR reports for a linux/amd64 image.
*
* `docker buildx imagetools inspect --format "{{json .}}"` includes the
* canonical descriptor digest even when the tag points directly at a
* single-platform manifest. Raw manifest JSON does not: its `config.digest`
* names the image configuration blob, which is a different registry object.
*/
export function linuxAmd64ManifestDigest(inspection) {
const manifest = inspection?.manifest;
const platformManifest = manifest?.manifests?.find(
(candidate) =>
candidate.platform?.os === "linux" &&
candidate.platform?.architecture === "amd64",
);
if (typeof platformManifest?.digest === "string") return platformManifest.digest;
if (
IMAGE_MANIFEST_MEDIA_TYPES.has(manifest?.mediaType) &&
typeof manifest?.digest === "string"
) {
return manifest.digest;
}
throw new Error("could not find a linux/amd64 image manifest descriptor");
}
+16 -7
View File
@@ -3,6 +3,7 @@ import { readFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";
import { spawn } from "node:child_process";
import { sandboxImageConfig } from "./sandbox-config.mjs";
import { linuxAmd64ManifestDigest } from "./oci-manifest.mjs";
const root = fileURLToPath(new URL("../", import.meta.url));
const { project, reference: image, repository, tag, team } = sandboxImageConfig();
@@ -49,13 +50,21 @@ await run("docker", [
".",
]);
const rawManifest = JSON.parse(await run("docker", ["buildx", "imagetools", "inspect", image, "--raw"], { capture: true }));
const amd64Digest =
rawManifest.manifests?.find(
(manifest) => manifest.platform?.os === "linux" && manifest.platform?.architecture === "amd64",
)?.digest ?? rawManifest.config?.digest;
if (!amd64Digest) throw new Error(`could not find the linux/amd64 manifest for ${image}`);
const inspection = JSON.parse(
await run(
"docker",
["buildx", "imagetools", "inspect", image, "--format", "{{json .}}"],
{ capture: true },
),
);
let amd64Digest;
try {
amd64Digest = linuxAmd64ManifestDigest(inspection);
} catch (error) {
throw new Error(`could not find the linux/amd64 manifest for ${image}`, {
cause: error,
});
}
console.log("Waiting for VCR to prepare the image for Sandbox...");
const deadline = Date.now() + 5 * 60_000;
+15
View File
@@ -0,0 +1,15 @@
/**
* Choose where tests that exercise the native host toolchain run.
*
* Darwin and Linux have supported native clang paths, so those files should
* test the contributor's actual host. Other hosts keep the coverage in the
* Linux Sandboxes. Darwin alone adds the compact kqueue/Mach-O contracts.
*/
export function sandboxHostSchedule(platform, invariantFiles) {
const runsNative = platform === "darwin" || platform === "linux";
return {
darwinContracts: platform === "darwin",
localInvariantFiles: runsNative ? invariantFiles : [],
remoteInvariantFiles: runsNative ? [] : invariantFiles,
};
}
+101 -59
View File
@@ -8,6 +8,7 @@ import { pipeline } from "node:stream/promises";
import { parseArgs } from "node:util";
import { fileURLToPath } from "node:url";
import { sandboxImageConfig } from "./sandbox-config.mjs";
import { sandboxHostSchedule } from "./sandbox-platform.mjs";
import { filterExistingWorktreePaths } from "./worktree-files.mjs";
const root = fileURLToPath(new URL("../", import.meta.url));
@@ -59,6 +60,8 @@ const invariantRemoteFiles = [
"tests/harness/library-mode.test.ts",
"tests/harness/library-profile.test.ts",
"tests/harness/linux-differential.test.ts",
"tests/harness/oci-manifest.test.ts",
"tests/harness/sandbox-platform.test.ts",
"tests/harness/shard.test.ts",
"tests/harness/smoke.test.ts",
"tests/harness/surface-manifest.test.ts",
@@ -78,19 +81,32 @@ const hostInvariantFiles = [
"packages/runtime/test/tonumber.test.ts",
"packages/runtime/test/url.test.ts",
];
const hostSchedule = sandboxHostSchedule(process.platform, hostInvariantFiles);
const nativeHostInvariantFiles = hostSchedule.localInvariantFiles;
// The full portable behavior of these suites runs remotely. A compact
// host-native contract additionally pins the places Darwin can disagree:
// object/archive ABI, Mach-O size classes, linker diagnostics, and ucontext
// behavior under both ordinary and Apple-ASan builds.
// object/archive ABI, Mach-O size classes, linker diagnostics, ucontext,
// and the kqueue event-loop arms under both ordinary and Apple-ASan builds.
// Non-Darwin hosts retain the full portable remote suites without trying
// to execute these macOS-specific contracts locally.
const hostLaneContractFiles = [
"tests/harness/ffi.test.ts",
"tests/harness/island.test.ts",
"tests/harness/differential.test.ts",
"tests/harness/server.test.ts",
"tests/harness/dgram.test.ts",
"tests/harness/event-loop.test.ts",
];
const hostLaneContractPattern = [
"calls the manifest-bound archive across every v1 ABI class",
"a missing FFI symbol is an SC5004 diagnostic",
"deep island recursion on a fiber is a catchable RangeError",
"net-echo",
"udp-loopback-pair",
"1564-fs-watch.ts",
"1470-child-lifecycle.ts",
"read-all: chunked writes with delays, then EOF",
].join("|");
const hostInvariantContractFiles = [
"tests/harness/island.test.ts",
@@ -589,12 +605,15 @@ try {
"--passWithNoTests",
`--shard=${worker.shard}/${shardCount}`,
...caseShardedFiles.map((file) => `--exclude=${file}`),
...hostInvariantFiles.map((file) => `--exclude=${file}`),
...nativeHostInvariantFiles.map((file) => `--exclude=${file}`),
...localLaneFiles.map((file) => `--exclude=${file}`),
...localCaseShardedFiles.map((file) => `--exclude=${file}`),
...(worker.lane === onceLane
? []
: invariantRemoteFiles.map((file) => `--exclude=${file}`)),
: [
...invariantRemoteFiles,
...hostSchedule.remoteInvariantFiles,
].map((file) => `--exclude=${file}`)),
],
{
...sharedTestEnv,
@@ -614,65 +633,89 @@ try {
const local = values["remote-only"]
? Promise.resolve()
: (async () => {
const hostName =
process.platform === "darwin"
? "Darwin"
: process.platform === "linux"
? "Linux"
: process.platform;
const localWork = [
...(nativeHostInvariantFiles.length > 0
? [`${nativeHostInvariantFiles.length} ${hostName}-native files`]
: []),
...(hostSchedule.darwinContracts
? ["compact Darwin platform contracts"]
: []),
`${localLaneFiles.length + localCaseShardedFiles.length} external suites`,
];
console.log(
`\nBuilding and testing ${hostInvariantFiles.length} Darwin-native files, compact platform contracts, and ${localLaneFiles.length + localCaseShardedFiles.length} external suites locally...`,
`\nBuilding and testing ${localWork.join(", ")} locally...`,
);
await run("pnpm", ["build"], { label: "local build" });
const laneEnv = (lane) => ({
CI: "1",
...(lane === "san" ? { SCRIPTC_SAN: "1" } : {}),
});
const invariantHostTask =
run(
"pnpm",
[
"test",
...hostInvariantFiles,
],
{
env: {
...laneEnv(onceLane),
SCRIPTC_TEST_WORKERS: localTestWorkers,
},
label: `local ${onceLane} Darwin`,
},
);
const invariantContractTask = run(
"pnpm",
[
"test",
"--reporter=dot",
"-t",
hostInvariantContractPattern,
...hostInvariantContractFiles,
],
{
env: {
...laneEnv(onceLane),
SCRIPTC_TEST_WORKERS: localTestWorkers,
},
label: `local ${onceLane} Darwin contract`,
},
);
const laneContractTasks = lanes.map((lane) =>
run(
"pnpm",
[
"test",
"--reporter=dot",
"-t",
hostLaneContractPattern,
...hostLaneContractFiles,
],
{
env: {
...laneEnv(lane),
SCRIPTC_TEST_WORKERS: localTestWorkers,
},
label: `local ${lane} Darwin contract`,
},
),
);
const nativeHostTasks =
nativeHostInvariantFiles.length === 0
? []
: [
run(
"pnpm",
[
"test",
...nativeHostInvariantFiles,
],
{
env: {
...laneEnv(onceLane),
SCRIPTC_TEST_WORKERS: localTestWorkers,
},
label: `local ${onceLane} ${hostName}`,
},
),
];
const darwinContractTasks =
!hostSchedule.darwinContracts
? []
: [
run(
"pnpm",
[
"test",
"--reporter=dot",
"-t",
hostInvariantContractPattern,
...hostInvariantContractFiles,
],
{
env: {
...laneEnv(onceLane),
SCRIPTC_TEST_WORKERS: localTestWorkers,
},
label: `local ${onceLane} Darwin contract`,
},
),
...lanes.map((lane) =>
run(
"pnpm",
[
"test",
"--reporter=dot",
"-t",
hostLaneContractPattern,
...hostLaneContractFiles,
],
{
env: {
...laneEnv(lane),
SCRIPTC_TEST_WORKERS: localTestWorkers,
},
label: `local ${lane} Darwin contract`,
},
),
),
];
const laneFileTasks = lanes.map((lane) =>
run(
"pnpm",
@@ -707,9 +750,8 @@ try {
);
const results = await Promise.allSettled(
[
invariantHostTask,
invariantContractTask,
...laneContractTasks,
...nativeHostTasks,
...darwinContractTasks,
...laneFileTasks,
...caseTasks,
],