|
| 1 | +import assert from "node:assert/strict" |
| 2 | +import { access, mkdir, readFile, writeFile } from "node:fs/promises" |
| 3 | +import { join } from "node:path" |
| 4 | + |
| 5 | +import { createRuntime } from "../packages/runtime-core/src/index.js" |
| 6 | +import { createPlaygroundRuntimeBackend } from "../packages/runtime-playground/src/index.js" |
| 7 | +import type { PlaygroundCliModule } from "../packages/runtime-playground/src/playground-cli-runner.js" |
| 8 | +import { withTempDir } from "../scripts/test-kit.js" |
| 9 | + |
| 10 | +await withTempDir("wp-codebox-direct-mount-materialization-", async (root) => { |
| 11 | + const source = join(root, "source") |
| 12 | + const wordpressDirectory = join(root, "wordpress") |
| 13 | + await mkdir(source) |
| 14 | + await mkdir(wordpressDirectory) |
| 15 | + await writeFile(join(source, "fixture.txt"), "direct mount fixture") |
| 16 | + |
| 17 | + let directWrites = 0 |
| 18 | + let mountedHostPath = "" |
| 19 | + const cliModule: PlaygroundCliModule = { |
| 20 | + async runCLI(options) { |
| 21 | + const mount = options.mount.find((candidate) => candidate.vfsPath === "/workspace/fixture") |
| 22 | + assert.ok(mount) |
| 23 | + mountedHostPath = mount.hostPath |
| 24 | + assert.equal(await readFile(join(mount.hostPath, "fixture.txt"), "utf8"), "direct mount fixture") |
| 25 | + return { |
| 26 | + serverUrl: "http://127.0.0.1:9404", |
| 27 | + playground: { |
| 28 | + async run() { return { text: "" } }, |
| 29 | + async writeFile() { directWrites++ }, |
| 30 | + }, |
| 31 | + async [Symbol.asyncDispose]() {}, |
| 32 | + } |
| 33 | + }, |
| 34 | + } |
| 35 | + |
| 36 | + const runtime = await createRuntime({ |
| 37 | + backend: "wordpress-playground", |
| 38 | + artifactsDirectory: join(root, "artifacts"), |
| 39 | + environment: { |
| 40 | + kind: "wordpress", |
| 41 | + name: "direct-mount-materialization", |
| 42 | + version: "mounted-wordpress-source", |
| 43 | + phpVersion: "8.4", |
| 44 | + wordpressInstallMode: "do-not-attempt-installing", |
| 45 | + assets: { wordpressDirectory }, |
| 46 | + blueprint: {}, |
| 47 | + }, |
| 48 | + policy: { |
| 49 | + network: "deny", |
| 50 | + filesystem: "readonly-mounts", |
| 51 | + commands: [], |
| 52 | + secrets: "none", |
| 53 | + approvals: "never", |
| 54 | + }, |
| 55 | + }, createPlaygroundRuntimeBackend({ cliModule })) |
| 56 | + |
| 57 | + const mount = { type: "directory" as const, source, target: "/workspace/fixture", mode: "readonly" as const } |
| 58 | + try { |
| 59 | + await runtime.mount(mount) |
| 60 | + const result = await runtime.materializeStagedInputs?.([mount]) as { phaseResult?: { status?: string; metadata?: Record<string, unknown> } } |
| 61 | + assert.equal(directWrites, 0, "mounted files are not rewritten through the Playground API") |
| 62 | + assert.notEqual(mountedHostPath, source, "readonly isolation still uses a private staged source") |
| 63 | + assert.equal(result.phaseResult?.status, "completed") |
| 64 | + assert.deepEqual(result.phaseResult?.metadata, { |
| 65 | + materialized: 0, |
| 66 | + deleted: 0, |
| 67 | + skipped: 0, |
| 68 | + mounts: 1, |
| 69 | + transport: "direct-nodefs-mount", |
| 70 | + }) |
| 71 | + } finally { |
| 72 | + await runtime.destroy() |
| 73 | + } |
| 74 | + |
| 75 | + await assert.rejects(access(mountedHostPath), /ENOENT/, "readonly staging is removed with the runtime") |
| 76 | +}) |
| 77 | + |
| 78 | +console.log("Playground staged inputs use direct NODEFS mounts") |
0 commit comments