






















11// Docker E2E Helper Cli tests cover docker e2e helper cli script behavior.
22import { spawnSync } from "node:child_process";
3-import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3+import { chmodSync, existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
44import { tmpdir } from "node:os";
55import path from "node:path";
66import { describe, expect, it } from "vitest";
@@ -23,6 +23,15 @@ function runHelper(script: string, ...args: Array<string | Record<string, string
2323});
2424}
252526+function downloadedDir(stdout: string) {
27+const match = stdout.match(/^Downloaded: (.+)$/mu);
28+const dir = match?.[1];
29+if (!dir) {
30+throw new Error(`missing downloaded dir in stdout:\n${stdout}`);
31+}
32+return dir;
33+}
34+2635describe("Docker E2E helper CLIs", () => {
2736it("prints scheduler helper help without throwing a stack trace", () => {
2837const result = runHelper("scripts/docker-e2e.mjs", "--help");
@@ -379,4 +388,87 @@ describe("Docker E2E helper CLIs", () => {
379388rmSync(root, { force: true, recursive: true });
380389}
381390});
391+392+it("downloads GitHub run artifacts into distinct default directories", () => {
393+const root = mkdtempSync(`${tmpdir()}/openclaw-docker-e2e-rerun-gh-`);
394+const generatedDirs: string[] = [];
395+try {
396+const binDir = path.join(root, "bin");
397+const ghPath = path.join(binDir, "gh");
398+mkdirSync(binDir, { recursive: true });
399+writeFileSync(
400+ghPath,
401+[
402+"#!/usr/bin/env node",
403+"const fs = require('node:fs');",
404+"const path = require('node:path');",
405+"const args = process.argv.slice(2);",
406+"if (args[0] === 'run' && args[1] === 'view') {",
407+" console.log(JSON.stringify({",
408+" conclusion: 'failure',",
409+" databaseId: 12345,",
410+" headBranch: 'main',",
411+" headSha: 'abc123',",
412+" status: 'completed',",
413+" url: 'https://github.com/openclaw/openclaw/actions/runs/12345',",
414+" workflowName: 'OpenClaw Live and E2E Checks',",
415+" }));",
416+" process.exit(0);",
417+"}",
418+"if (args[0] === 'api') {",
419+" console.log(JSON.stringify([{ expired: false, name: 'docker-e2e-gateway-network' }]));",
420+" process.exit(0);",
421+"}",
422+"if (args[0] === 'run' && args[1] === 'download') {",
423+" const dir = args[args.indexOf('--dir') + 1];",
424+" fs.mkdirSync(path.join(dir, 'artifact'), { recursive: true });",
425+" fs.writeFileSync(path.join(dir, 'artifact', 'failures.json'), JSON.stringify({",
426+" lanes: [{ name: 'gateway-network', status: 1 }],",
427+" status: 'failed',",
428+" }));",
429+" process.exit(0);",
430+"}",
431+"console.error(`unexpected gh args: ${args.join(' ')}`);",
432+"process.exit(1);",
433+"",
434+].join("\n"),
435+"utf8",
436+);
437+chmodSync(ghPath, 0o755);
438+439+const env = {
440+PATH: `${binDir}${path.delimiter}${process.env.PATH ?? ""}`,
441+};
442+const first = runHelper(
443+"scripts/docker-e2e-rerun.mjs",
444+"12345",
445+"--repo",
446+"openclaw/openclaw",
447+env,
448+);
449+const second = runHelper(
450+"scripts/docker-e2e-rerun.mjs",
451+"12345",
452+"--repo",
453+"openclaw/openclaw",
454+env,
455+);
456+457+expect(first.status, first.stderr).toBe(0);
458+expect(second.status, second.stderr).toBe(0);
459+const firstDir = downloadedDir(first.stdout);
460+const secondDir = downloadedDir(second.stdout);
461+generatedDirs.push(firstDir, secondDir);
462+expect(firstDir).not.toBe(secondDir);
463+expect(path.basename(firstDir)).toMatch(/^openclaw-docker-e2e-rerun-12345-/u);
464+expect(path.basename(secondDir)).toMatch(/^openclaw-docker-e2e-rerun-12345-/u);
465+expect(existsSync(path.join(firstDir, "artifact", "failures.json"))).toBe(true);
466+expect(existsSync(path.join(secondDir, "artifact", "failures.json"))).toBe(true);
467+} finally {
468+for (const dir of generatedDirs) {
469+rmSync(dir, { force: true, recursive: true });
470+}
471+rmSync(root, { force: true, recursive: true });
472+}
473+});
382474});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。