修复(08-08-production-deployment-execution): 校验候选 Compose 构建标识
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-08-08 20:44:30 +08:00
父节点 83af7544c4
当前提交 8b2ed5bb16
共修改 6 个文件,包含 91 行新增和 16 行删除
@@ -128,6 +128,8 @@ describe("deployment safety contract", () => {
expect(preflight).toContain("CANDIDATE_MIGRATIONS_CSV");
expect(preflight).toContain("PRISMA_STATUS_OUTPUT_MISSING");
expect(preflight).toContain("PRISMA_STATUS_OUTPUT_UNREADABLE");
expect(preflight).toContain("CANDIDATE_COMMIT_MISSING");
expect(preflight).not.toContain("rev-parse");
expect(preflight).toContain("redacted datasource line");
expect(preflight).toContain("PRODUCTION_PREFLIGHT_REPORT_NOT_FRESH");
expect(preflight.lastIndexOf("printStableRemoteSummary(stdout)")).toBeLessThan(
@@ -140,6 +142,7 @@ describe("deployment safety contract", () => {
expect(remote).toContain("PROD_MIGRATION_STATUS_UNKNOWN_PENDING");
expect(remote).toContain("logged_failure");
expect(remote).toContain("PROD_DATABASE_URL_HOST_NON_PRODUCTION_IDENTITY");
expect(remote).toContain("PROD_TARGET_BUILD_SHA_MISMATCH");
expect(remote).toContain('FROM "_prisma_migrations"');
expect(remote).toContain("rollbackWindow=OPEN");
expect(remote).not.toMatch(/\b(prisma migrate reset|prisma db push|prisma migrate resolve)\b/);
@@ -337,6 +340,8 @@ describe("deployment safety contract", () => {
expect(sshCommand).not.toContain("hyb_oa");
expect(sshCommand).toContain("EXPECTED_PRODUCTION_ORIGIN_SHA256");
expect(sshCommand).toContain("EXPECTED_PRODUCTION_DB_NAME_SHA256");
expect(sshCommand).toContain(`BUILD_SHA='${candidateCommit}'`);
expect(sshCommand).toContain(`VITE_BUILD_SHA='${candidateCommit.slice(0, 12)}'`);
});
it("bootstraps only an exact historical identity and a unique refresh probe", async () => {
@@ -494,7 +499,8 @@ describe("deployment safety contract", () => {
await chmod(path.join(fakeBin, "docker"), 0o700);
const hash = (value) => createHash("sha256").update(value, "utf8").digest("hex");
const runRemote = (mode, expectedPending = "") => execFileAsync("bash", [PRODUCTION_PREFLIGHT_REMOTE], {
const buildSha = "a".repeat(40);
const runRemote = (mode, expectedPending = "", buildOverrides = {}) => execFileAsync("bash", [PRODUCTION_PREFLIGHT_REMOTE], {
cwd: remoteDir,
env: {
...process.env,
@@ -508,8 +514,11 @@ describe("deployment safety contract", () => {
STORAGE_HOST_DIR: storageDir,
EXPECTED_PRODUCTION_ORIGIN_SHA256: hash("https://oa.example.com"),
EXPECTED_PRODUCTION_DB_NAME_SHA256: hash("production_db"),
BUILD_SHA: buildSha,
VITE_BUILD_SHA: buildSha.slice(0, 12),
CANDIDATE_MIGRATIONS_CSV: "20260807193000_contract_registry_termination_workspace,20260807193001_followup_migration",
EXPECTED_PENDING_MIGRATIONS_CSV: expectedPending,
...buildOverrides,
},
});
const result = await runRemote("happy");
@@ -524,6 +533,15 @@ describe("deployment safety contract", () => {
await expect(runRemote("logs")).rejects.toMatchObject({
stderr: expect.stringContaining("PROD_MIGRATION_FAILED_OR_ROLLED_BACK"),
});
await expect(runRemote("happy", "", { BUILD_SHA: "a".repeat(39) })).rejects.toMatchObject({
stderr: expect.stringContaining("PROD_TARGET_BUILD_SHA_INVALID"),
});
await expect(runRemote("happy", "", { VITE_BUILD_SHA: "a".repeat(7) })).rejects.toMatchObject({
stderr: expect.stringContaining("PROD_TARGET_VITE_BUILD_SHA_INVALID"),
});
await expect(runRemote("happy", "", { VITE_BUILD_SHA: "b".repeat(12) })).rejects.toMatchObject({
stderr: expect.stringContaining("PROD_TARGET_BUILD_SHA_MISMATCH"),
});
});
it("aggregates preflight checks and keeps the root helper self-contained", async () => {