|
1 | 1 | import { spawnSync } from "node:child_process"; |
2 | | -import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; |
| 2 | +import { chmodSync, mkdirSync, mkdtempSync, rmSync, statSync, writeFileSync } from "node:fs"; |
3 | 3 | import { tmpdir } from "node:os"; |
4 | 4 | import path from "node:path"; |
5 | 5 | import { afterAll, beforeAll, describe, expect, it } from "vitest"; |
@@ -53,6 +53,12 @@ function writeFakeCrabbox(binDir: string, helpText: string): string { |
53 | 53 | " fi", |
54 | 54 | " done", |
55 | 55 | "fi", |
| 56 | + 'for arg in "$@"; do', |
| 57 | + ' if [ "$arg" = "--artifact-glob" ] || [ "$arg" = "-artifact-glob" ]; then', |
| 58 | + " mkdir -p .crabbox/runs/run_fake", |
| 59 | + ' printf "%s\\n" "fake artifact" > .crabbox/runs/run_fake/fake-artifacts.tgz', |
| 60 | + " fi", |
| 61 | + "done", |
56 | 62 | 'script_path=""', |
57 | 63 | 'previous_arg=""', |
58 | 64 | 'for arg in "$@"; do', |
@@ -91,6 +97,10 @@ function writeFakeCrabbox(binDir: string, helpText: string): string { |
91 | 97 | "const scriptIndex = args.findIndex((arg) => arg === '--script' || arg === '-script');", |
92 | 98 | "const scriptPath = scriptIndex >= 0 ? args[scriptIndex + 1] : '';", |
93 | 99 | "const scriptContent = scriptPath ? require('node:fs').readFileSync(scriptPath, 'utf8') : '';", |
| 100 | + "if (args.includes('--artifact-glob') || args.includes('-artifact-glob')) {", |
| 101 | + " require('node:fs').mkdirSync('.crabbox/runs/run_fake', { recursive: true });", |
| 102 | + " require('node:fs').writeFileSync('.crabbox/runs/run_fake/fake-artifacts.tgz', 'fake artifact\\n');", |
| 103 | + "}", |
94 | 104 | "console.log(JSON.stringify({ args, cwd: process.cwd(), scriptContent }));", |
95 | 105 | ].join("\n"); |
96 | 106 | writeFileSync(helperPath, `${helperScript}\n`, "utf8"); |
@@ -2234,6 +2244,40 @@ describe.concurrent("scripts/crabbox-wrapper", () => { |
2234 | 2244 | expect(output.args).toContain(`/tmp/proof=${path.join(repoRoot, ".artifacts/proof")}`); |
2235 | 2245 | }); |
2236 | 2246 |
|
| 2247 | + it("preserves artifact-glob downloads from temporary sparse-sync checkouts", () => { |
| 2248 | + const preservedDir = path.join(repoRoot, ".crabbox", "runs", "run_fake"); |
| 2249 | + rmSync(preservedDir, { recursive: true, force: true }); |
| 2250 | + |
| 2251 | + const result = runWrapper( |
| 2252 | + "provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n", |
| 2253 | + [ |
| 2254 | + "run", |
| 2255 | + "--provider", |
| 2256 | + "blacksmith-testbox", |
| 2257 | + "--blacksmith-ref", |
| 2258 | + "main", |
| 2259 | + "--artifact-glob", |
| 2260 | + ".artifacts/proof/**", |
| 2261 | + "--", |
| 2262 | + "echo ok", |
| 2263 | + ], |
| 2264 | + { |
| 2265 | + gitResponses: { |
| 2266 | + ["config\u0000--bool\u0000core.sparseCheckout"]: { stdout: "true\n" }, |
| 2267 | + ["status\u0000--porcelain=v1"]: { stdout: "" }, |
| 2268 | + }, |
| 2269 | + }, |
| 2270 | + ); |
| 2271 | + |
| 2272 | + const output = parseFakeCrabboxOutput(result); |
| 2273 | + expect(result.status).toBe(0); |
| 2274 | + expect(output.cwd).toContain("openclaw-crabbox-sync-"); |
| 2275 | + expect(result.stderr).toContain("syncing from temporary full checkout"); |
| 2276 | + expect(result.stderr).toContain("preserved"); |
| 2277 | + expect(statSync(path.join(preservedDir, "fake-artifacts.tgz")).isFile()).toBe(true); |
| 2278 | + rmSync(preservedDir, { recursive: true, force: true }); |
| 2279 | + }); |
| 2280 | + |
2237 | 2281 | it("uses the temporary full checkout for sparse sync-only runs", () => { |
2238 | 2282 | const result = runWrapper( |
2239 | 2283 | "provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n", |
|
0 commit comments