Files
pikasTech-unidesk/scripts/src/cicd-pr-merge-auto-delivery-doc-contract.test.ts
T
2026-07-11 11:42:16 +02:00

103 lines
4.9 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
const root = resolve(import.meta.dir, "../..");
const skill = readFileSync(resolve(root, ".agents/skills/unidesk-cicd/SKILL.md"), "utf8");
const reference = readFileSync(
resolve(root, ".agents/skills/unidesk-cicd/references/gitea-pac.md"),
"utf8",
);
const platform = readFileSync(resolve(root, "docs/reference/platform-infra.md"), "utf8");
describe("PR 合并驱动的自动交付文档合同", () => {
test("权威文档声明唯一触发、完整自动链和故障修复边界", () => {
for (const document of [skill, reference, platform]) {
expect(document).toContain("GitHub PR merge");
expect(document).toMatch(/唯一.*触发/);
expect(document).toMatch(
/GitHub webhook[\s\S]*Gitea[\s\S]*immutable snapshot[\s\S]*Gitea webhook[\s\S]*(?:PaC|Pipelines-as-Code)[\s\S]*Tekton[\s\S]*GitOps\/Argo[\s\S]*(?:runtime|运行面)/,
);
expect(document).toMatch(/自动链.*修复|修复.*自动链/);
}
});
test("主代理、子代理和操作者不得在 PR 合并后补齐交付", () => {
for (const document of [skill, reference, platform]) {
expect(document).toContain("主代理");
expect(document).toContain("子代理");
expect(document).toMatch(
/apply[\s\S]*closeout[\s\S]*trigger[\s\S]*sync[\s\S]*flush/,
);
expect(document).toMatch(/不得|禁止/);
}
});
test("状态与单步入口只读,自动链不通时不得人工恢复", () => {
expect(skill).toContain(
"status/history/events/logs/debug-step 可用于定位,但不得改变交付状态",
);
expect(skill).toContain("`closeout` 只属于显式 compatibility diagnostics");
expect(skill).toContain("PaC migrated consumer 禁止执行 `trigger-current`");
expect(skill).not.toContain("需要保留的旧命令只能标为 debug/test/recovery");
expect(reference).toContain("`closeout` 只保留为可选的只读历史/诊断兼容入口");
expect(reference).toContain("禁止输出或执行人工 `REPAIR`");
expect(reference).not.toContain("run the row's `REPAIR` command");
expect(reference).not.toContain("manual recovery");
});
test("migrated consumer 默认观察与覆盖矩阵不再引导人工 closeout", () => {
const coverage = reference.slice(
reference.indexOf("## 覆盖矩阵"),
reference.indexOf("## 按需只读调查"),
);
const diagnosis = reference.slice(
reference.indexOf("## 按需只读调查"),
reference.indexOf("GitHub webhook delivery"),
);
expect(coverage).toContain("pipelines-as-code status");
expect(coverage).not.toContain("pipelines-as-code closeout");
expect(diagnosis).toContain("不是 PR 合并后的默认顺序、交付前置或“下一步”");
expect(diagnosis).not.toContain("pipelines-as-code closeout");
});
test("源码制品写入仅属于合并前,不得成为合并后触发器", () => {
expect(reference).toContain(
"`source-artifact plan|check|write` 只能在 source PR 合并前",
);
expect(reference).toContain("不是合并后的 CI/CD 触发、同步、恢复或补跑入口");
});
test("delivery authority 由两份 YAML 组合,unknown 与 migrated 都禁止 mutation", () => {
for (const document of [skill, reference, platform]) {
expect(document).toContain("config/platform-infra/gitea.yaml");
expect(document).toContain("config/platform-infra/pipelines-as-code.yaml");
expect(document).toMatch(/unknown[\s\S]*mutation=false|unknown[\s\S]*`mutation=false`/);
expect(document).toMatch(/legacy-(?:manual|cicd)|legacy\/manual/);
}
});
test("durable inbox 只证明 accepted,同 delivery refs proof 才能 committed", () => {
for (const document of [skill, reference, platform]) {
expect(document).toContain("202 Accepted");
expect(document).toContain("accepted");
expect(document).toContain("processing");
expect(document).toContain("committed");
expect(document).toContain("failed");
expect(document).toContain("deliveryId");
expect(document).toMatch(/fsync[\s\S]*atomic (?:rename|write)/);
expect(document).toMatch(/immutable snapshot[\s\S]*authority branch|authority branch[\s\S]*immutable snapshot/);
expect(document).toMatch(/重新读取 refs|refs proof/);
expect(document).toMatch(/不是.*(?:source|源码).*第二份真相|不是业务 source\/ref 的第二份真相/);
expect(document).not.toMatch(/只有 HTTP 200|返回 HTTP 200 后.*committed/);
}
});
test("可调整预算继续归属 YAML,长期规则不固化当前数值", () => {
expect(skill).toContain("wall-clock 目标及预算只由 owning YAML 声明");
expect(skill).not.toContain("低于 2 分钟");
expect(skill).not.toContain("120s 端到端预算");
});
});