|
| 1 | +import assert from "node:assert/strict" |
| 2 | +import { execFile } from "node:child_process" |
| 3 | +import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises" |
| 4 | +import { tmpdir } from "node:os" |
| 5 | +import { join } from "node:path" |
| 6 | +import { promisify } from "node:util" |
| 7 | +import { ArtifactBundleBuilder } from "../packages/runtime-playground/src/artifact-bundle-builder.js" |
| 8 | +import { captureMountedFiles, captureMountDiffs } from "../packages/runtime-playground/src/mounted-artifact-capture.js" |
| 9 | +import { applyRunnerWorkspacePatch } from "../packages/runtime-core/src/runner-workspace-apply.js" |
| 10 | + |
| 11 | +const execFileAsync = promisify(execFile) |
| 12 | +const root = await mkdtemp(join(tmpdir(), "wp-codebox-trusted-apply-integration-")) |
| 13 | +const artifactRoot = join(root, "artifacts") |
| 14 | +const trustedRoot = join(root, "trusted") |
| 15 | +const baseline = join(root, "baseline") |
| 16 | +const mounted = join(root, "mounted") |
| 17 | +const host = join(root, "host") |
| 18 | +const secretName = "CONFIGURED_SECRET" |
| 19 | +const previousChannel = process.env.WP_CODEBOX_TRUSTED_APPLY_ARTIFACT_ROOT |
| 20 | + |
| 21 | +try { |
| 22 | + for (const directory of [baseline, mounted, host, trustedRoot]) { |
| 23 | + await mkdir(directory, { recursive: true }) |
| 24 | + await writeFile(join(directory, "README.md"), `${secretName}\nbefore\n`) |
| 25 | + } |
| 26 | + await writeFile(join(mounted, "README.md"), `${secretName}\nafter\n`) |
| 27 | + await execFileAsync("git", ["init"], { cwd: host }) |
| 28 | + process.env.WP_CODEBOX_TRUSTED_APPLY_ARTIFACT_ROOT = trustedRoot |
| 29 | + |
| 30 | + const mounts = [{ source: mounted, target: "/workspace", mode: "readwrite", metadata: { baselineSource: baseline } }] |
| 31 | + await new ArtifactBundleBuilder({ |
| 32 | + artifactRoot, |
| 33 | + runtimeId: "trusted-apply-test", |
| 34 | + runtimeCreatedAt: new Date().toISOString(), |
| 35 | + spec: { environment: { blueprint: {} }, secretEnv: { [secretName]: "secret-value" } }, |
| 36 | + mounts, |
| 37 | + commands: [], observations: [], snapshots: [], events: [], |
| 38 | + info: async () => ({ id: "trusted-apply-test", backend: "playground", status: "ready", environment: { version: "latest" } }), |
| 39 | + previewInfo: async () => undefined, |
| 40 | + browserReviewSummary: () => undefined, |
| 41 | + browserArtifacts: () => [], |
| 42 | + captureMountedFiles: (filesDirectory, redactor) => captureMountedFiles(filesDirectory, mounts, redactor), |
| 43 | + captureMountDiffs: (filesDirectory, redactor) => captureMountDiffs(artifactRoot, filesDirectory, mounts, redactor), |
| 44 | + redactBrowserArtifacts: async () => {}, redactPluginCheckArtifacts: async () => {}, redactThemeCheckArtifacts: async () => {}, |
| 45 | + browserManifestFiles: () => [], pluginCheckArtifactPaths: () => [], themeCheckArtifactPaths: () => [], observationManifestFiles: () => [], pluginCheckManifestFiles: () => [], themeCheckManifestFiles: () => [], |
| 46 | + formatRuntimeLog: () => "", formatCommandsLog: () => "", recordArtifactsCollected: () => {}, |
| 47 | + } as any).build() |
| 48 | + |
| 49 | + const durablePatch = await readFile(join(artifactRoot, "files", "patch.diff"), "utf8") |
| 50 | + assert(!durablePatch.includes(secretName), "durable artifact redacts configured secret names") |
| 51 | + assert.match(durablePatch, /\[REDACTED:configured-secret-name\]/) |
| 52 | + await assert.rejects( |
| 53 | + applyRunnerWorkspacePatch({ |
| 54 | + artifactRoot, |
| 55 | + artifactRefs: [ |
| 56 | + { kind: "codebox-patch", path: "files/patch.diff" }, |
| 57 | + { kind: "codebox-changed-files", path: "files/changed-files.json" }, |
| 58 | + ], |
| 59 | + workspaceRoot: host, |
| 60 | + writablePaths: ["README.md"], |
| 61 | + }), |
| 62 | + /Host git apply failed/, |
| 63 | + "the durable redacted patch cannot apply where configured secret context is unchanged", |
| 64 | + ) |
| 65 | + const trustedPatch = await readFile(join(trustedRoot, "files", "patch.diff"), "utf8") |
| 66 | + assert.match(trustedPatch, new RegExp(secretName), "private apply bytes retain unchanged diff context") |
| 67 | + |
| 68 | + const applied = await applyRunnerWorkspacePatch({ |
| 69 | + artifactRoot: trustedRoot, |
| 70 | + artifactRefs: [ |
| 71 | + { kind: "codebox-patch", path: "files/patch.diff" }, |
| 72 | + { kind: "codebox-changed-files", path: "files/changed-files.json" }, |
| 73 | + ], |
| 74 | + workspaceRoot: host, |
| 75 | + writablePaths: ["README.md"], |
| 76 | + }) |
| 77 | + assert.equal(applied.status, "applied", "the host applies pre-redaction bytes") |
| 78 | + assert.equal(await readFile(join(host, "README.md"), "utf8"), `${secretName}\nafter\n`) |
| 79 | +} finally { |
| 80 | + if (previousChannel === undefined) delete process.env.WP_CODEBOX_TRUSTED_APPLY_ARTIFACT_ROOT |
| 81 | + else process.env.WP_CODEBOX_TRUSTED_APPLY_ARTIFACT_ROOT = previousChannel |
| 82 | + await rm(root, { recursive: true, force: true }) |
| 83 | +} |
| 84 | + |
| 85 | +console.log("trusted apply artifact channel integration ok") |
0 commit comments