From d27f24cf3e15e9fc14eed473b581d43f4f39a877 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 13 Sep 2026 04:56:00 +0200 Subject: [PATCH] The bed resolves an artifact the way the builder would MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It pre-builds these images and stocks them, which is the lab standing in for the builder — so it must do what the builder does and replace the artifact with the reference the machine holds. Without it the unresolved field travels to the machine and the whole declaration is refused. --- test/integration/whole-mesh-full.test.ts | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/integration/whole-mesh-full.test.ts b/test/integration/whole-mesh-full.test.ts index b2d666c..65d9379 100644 --- a/test/integration/whole-mesh-full.test.ts +++ b/test/integration/whole-mesh-full.test.ts @@ -66,7 +66,7 @@ import { bootstrapBinaryPath, hostBinaryPath, placeBootstrap, BOOTSTRAP_PATH, HOST_PATH, } from "../../src/lifecycle/place.ts"; import { labIsUsable, destroyAll, substrateBundle, onTheMachine } from "./harness.ts"; -import type { HeldImage } from "../../src/pinning.ts"; +import { referenceFor, type HeldImage } from "../../src/pinning.ts"; const capability = await labIsUsable(); const binary = hostBinaryPath(); @@ -359,11 +359,29 @@ function bundleFor(images: HeldImage[]): string { function loadManifest(name: string): { manifest: string; broker: boolean } { const path = resolve(catalogDir, name, "module.json"); const m = JSON.parse(readFileSync(path, "utf8")) as { - resources?: { type: string; image?: string; ports?: string[] }[]; + resources?: { type: string; image?: string; artifact?: string; ports?: string[] }[]; }; const remap = REMAP[name] ?? {}; for (const r of m.resources ?? []) { if (r.type !== "container") continue; + // **A container naming an artifact is a module the mesh builds, and this bed does not build.** + // It pre-builds the same images on the workstation and stocks them, which is the lab standing + // in for the builder — so it does here what the builder does: replace the artifact with the + // reference the machine actually holds. Without this the unresolved field travels to the + // machine, whose declaration language has no such field, and the whole declaration is refused. + // + // The repository is `mesh-runtime-`, which is not a guess: it is what this repository's + // own `scripts/build-module-runtime.sh ` produces and what the scenarios stock by name. + if (typeof r.artifact === "string" && typeof r.image !== "string") { + const reference = referenceFor(held, `mesh-runtime-${name}`); + assert.ok(reference, + `${name} declares the "${r.artifact}" artifact and this scenario stocked no ` + + `mesh-runtime-${name}. The mesh would have to build it, and this bed does not build — ` + + `add it to the machine's images: in the scenario, or build it with ` + + `scripts/build-module-runtime.sh ${name}`); + r.image = reference; + delete r.artifact; + } if (typeof r.image === "string") r.image = pinned(r.image); if (Array.isArray(r.ports)) r.ports = r.ports.map((p) => remap[p] ?? p); }