



















1+// Validate release publish approval tests cover the stdin/env CLI contract.
2+import { spawnSync } from "node:child_process";
3+import { describe, expect, it } from "vitest";
4+5+const SCRIPT_PATH = "scripts/validate-release-publish-approval.mjs";
6+7+function runApprovalScript(
8+run: Record<string, unknown>,
9+env: {
10+DIRECT_RELEASE_RECOVERY?: string;
11+EXPECTED_WORKFLOW_BRANCH?: string;
12+RELEASE_PUBLISH_RUN_ID?: string;
13+} = {},
14+) {
15+return spawnSync(process.execPath, [SCRIPT_PATH], {
16+cwd: process.cwd(),
17+encoding: "utf8",
18+env: {
19+ ...process.env,
20+DIRECT_RELEASE_RECOVERY: env.DIRECT_RELEASE_RECOVERY ?? "false",
21+EXPECTED_WORKFLOW_BRANCH: env.EXPECTED_WORKFLOW_BRANCH ?? "release/2026.6.21",
22+RELEASE_PUBLISH_RUN_ID: env.RELEASE_PUBLISH_RUN_ID ?? "123",
23+},
24+input: JSON.stringify(run),
25+});
26+}
27+28+function approvalRun(overrides: Record<string, unknown> = {}) {
29+return {
30+conclusion: null,
31+event: "workflow_dispatch",
32+headBranch: "release/2026.6.21",
33+status: "in_progress",
34+url: "https://github.com/openclaw/openclaw/actions/runs/123",
35+workflowName: "OpenClaw Release Publish",
36+ ...overrides,
37+};
38+}
39+40+describe("scripts/validate-release-publish-approval.mjs", () => {
41+it("accepts an in-progress release publish workflow run for approval", () => {
42+const result = runApprovalScript(approvalRun());
43+44+expect(result.status).toBe(0);
45+expect(result.stdout).toContain(
46+"Using release publish approval run 123: https://github.com/openclaw/openclaw/actions/runs/123",
47+);
48+expect(result.stderr).toBe("");
49+});
50+51+it("rejects approval runs from the wrong workflow branch", () => {
52+const result = runApprovalScript(approvalRun({ headBranch: "main" }));
53+54+expect(result.status).toBe(1);
55+expect(result.stderr).toContain(
56+"Referenced release publish run 123 must have headBranch=release/2026.6.21, got main.",
57+);
58+expect(result.stdout).toBe("");
59+});
60+61+it("rejects completed runs for normal approval handoff", () => {
62+const result = runApprovalScript(approvalRun({ conclusion: "success", status: "completed" }));
63+64+expect(result.status).toBe(1);
65+expect(result.stderr).toContain(
66+"Referenced release publish run 123 must still be in_progress, got completed.",
67+);
68+expect(result.stdout).toBe("");
69+});
70+71+it("accepts completed success or failure runs for direct recovery", () => {
72+for (const conclusion of ["success", "failure"]) {
73+const result = runApprovalScript(
74+approvalRun({ conclusion, status: "completed" }),
75+{ DIRECT_RELEASE_RECOVERY: "true" },
76+);
77+78+expect(result.status).toBe(0);
79+expect(result.stdout).toContain(
80+`Using completed release publish run 123 (${conclusion}) for direct recovery: https://github.com/openclaw/openclaw/actions/runs/123`,
81+);
82+expect(result.stderr).toBe("");
83+}
84+});
85+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。