Files
pikasTech-HWLAB/scripts/artifact-runtime-readiness-guard.test.mjs
T

438 lines
14 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import {
buildCommanderReadinessSummary,
commitsMatch,
evaluateArtifactRuntimeReadiness,
normalizeCommit
} from "./src/artifact-runtime-readiness-guard.mjs";
const targetSha = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
const staleSha = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
const digest = "sha256:1111111111111111111111111111111111111111111111111111111111111111";
function artifactReport(sourceCommitId = targetSha, overrides = {}) {
return {
commitId: sourceCommitId.slice(0, 7),
artifactPublish: {
status: "published",
sourceCommitId,
serviceCount: 2,
requiredServiceCount: 2,
publishedCount: 2,
registryPrefix: "127.0.0.1:5000/hwlab",
services: [
{
serviceId: "hwlab-cloud-api",
artifactRequired: true,
status: "published",
imageTag: sourceCommitId.slice(0, 7),
digest
},
{
serviceId: "hwlab-cloud-web",
artifactRequired: true,
status: "published",
imageTag: sourceCommitId.slice(0, 7),
digest,
runtimeKind: "cloud-web",
distFreshness: { status: "pass" }
}
],
...overrides
}
};
}
function artifactCatalog(commitId = targetSha, {
ciPublished = true,
registryVerified = true,
serviceDigest = digest,
artifactState = "published"
} = {}) {
return {
artifactState,
commitId,
publish: {
ciPublished,
registryVerified
},
services: [
{
serviceId: "hwlab-cloud-api",
commitId,
artifactRequired: true,
publishState: serviceDigest === "not_published" ? "skeleton-only" : "published",
imageTag: commitId.slice(0, 7),
digest: serviceDigest
},
{
serviceId: "hwlab-cloud-web",
commitId,
artifactRequired: true,
publishState: serviceDigest === "not_published" ? "skeleton-only" : "published",
imageTag: commitId.slice(0, 7),
digest: serviceDigest
}
]
};
}
function desiredStatePlan(commitId = targetSha, state = "already_promoted", status = "pass") {
return {
status,
summary: {
desiredCommitId: commitId,
desiredImageTag: commitId.slice(0, 7),
diagnostics: status === "blocked" ? 1 : 0,
blockers: status === "blocked" ? 1 : 0
},
target: {
convergence: {
state,
comparableFields: 8,
matchingTargetFields: state === "already_promoted" ? 8 : 0,
pendingTargetFields: state === "already_promoted" ? 0 : 8
}
},
services: [
{
serviceId: "hwlab-cloud-web",
catalog: { commitId }
}
]
};
}
function liveRuntime(commitId = targetSha, { cloudWebCommitId = commitId, apiCommitId = commitId } = {}) {
return {
mode: "live-read-only-http",
api: {
status: "observed",
source: "health-live",
evidenceSource: "live-http",
endpoint: "http://74.48.78.17:16667/health/live",
serviceId: "hwlab-cloud-api",
environment: "dev",
healthStatus: "ok",
commitId: apiCommitId,
shortCommitId: apiCommitId.slice(0, 7),
commitSource: "runtime-env",
imageTag: apiCommitId.slice(0, 7),
observedAt: "2026-05-22T00:00:00.000Z"
},
cloudWeb: {
status: "observed",
source: "health-live",
evidenceSource: "live-http",
endpoint: "http://74.48.78.17:16666/health/live",
serviceId: "hwlab-cloud-web",
environment: "dev",
healthStatus: "ok",
artifactKind: "cloud-web",
commitId: cloudWebCommitId,
shortCommitId: cloudWebCommitId.slice(0, 7),
commitSource: "runtime-env",
imageTag: cloudWebCommitId.slice(0, 7),
observedAt: "2026-05-22T00:00:00.000Z"
}
};
}
function readiness(overrides = {}) {
return evaluateArtifactRuntimeReadiness({
artifactReport: artifactReport(overrides.artifactSource ?? targetSha, overrides.artifactReportOverrides),
artifactCatalog: artifactCatalog(overrides.catalogCommit ?? targetSha, overrides.catalogOptions ?? {}),
desiredStatePlan: overrides.desiredPlan ?? desiredStatePlan(overrides.desiredCommit ?? targetSha, overrides.desiredState ?? "already_promoted", overrides.desiredStatus ?? "pass"),
runtimeReport: null,
liveRuntime: overrides.live ?? liveRuntime(targetSha),
targetRef: "origin/main",
targetCommitId: overrides.targetCommit ?? targetSha
});
}
test("commit comparison accepts full and short lowercase SHA forms only", () => {
assert.equal(normalizeCommit("ABCDEF1"), "abcdef1");
assert.equal(normalizeCommit("not-a-sha"), "unknown");
assert.equal(commitsMatch(targetSha, targetSha.slice(0, 7)), true);
assert.equal(commitsMatch(targetSha, "unknown"), false);
});
test("readiness passes only when artifact, desired-state, API runtime, and Cloud Web runtime match target", () => {
const result = readiness();
assert.equal(result.ready, true);
assert.equal(result.canInferFromSourceLocalStatic, false);
assert.deepEqual(result.blockers, []);
});
test("stale local artifact report cannot imply latest-main readiness", () => {
const result = readiness({ targetCommit: staleSha });
assert.equal(result.ready, false);
assert.equal(result.canInferFromSourceLocalStatic, false);
assert.deepEqual(
result.blockers.map((item) => item.id),
[
"artifact-report-target-match",
"artifact-catalog-target-match",
"desired-state-target-match",
"api-runtime-target-match",
"cloud-web-runtime-target-match"
]
);
});
test("desired-state promotion pending blocks before apply", () => {
const result = readiness({
desiredCommit: staleSha,
desiredState: "promotion_pending",
desiredStatus: "planned"
});
assert.equal(result.ready, false);
assert.equal(result.desiredState.targetConvergence.state, "promotion_pending");
assert.ok(result.blockers.some((item) => item.id === "desired-state-target-match"));
});
test("unpublished catalog digests keep readiness blocked", () => {
const result = readiness({
catalogOptions: {
artifactState: "contract-skeleton",
ciPublished: false,
registryVerified: false,
serviceDigest: "not_published"
}
});
assert.equal(result.ready, false);
assert.equal(result.catalog.ciPublished, false);
assert.equal(result.catalog.registryVerified, false);
assert.deepEqual(
result.blockers.map((item) => item.id),
["artifact-catalog-published"]
);
});
test("Cloud Web served runtime identity must match artifact and target", () => {
const result = readiness({
live: liveRuntime(targetSha, { cloudWebCommitId: staleSha })
});
assert.equal(result.ready, false);
assert.ok(result.blockers.some((item) => item.id === "cloud-web-runtime-target-match"));
assert.ok(result.blockers.some((item) => item.id === "cloud-web-runtime-artifact-match"));
assert.equal(result.runtime.cloudWeb.effective.shortCommitId, staleSha.slice(0, 7));
});
test("Cloud Web publish report must retain build freshness evidence", () => {
const result = readiness({
artifactReportOverrides: {
services: [
{
serviceId: "hwlab-cloud-api",
artifactRequired: true,
status: "published",
imageTag: targetSha.slice(0, 7),
digest
},
{
serviceId: "hwlab-cloud-web",
artifactRequired: true,
status: "published",
imageTag: targetSha.slice(0, 7),
digest,
runtimeKind: "cloud-web"
}
]
}
});
assert.equal(result.ready, false);
assert.equal(result.artifact.cloudWeb.distFreshnessStatus, "missing");
assert.ok(result.blockers.some((item) => item.id === "cloud-web-published-build-freshness"));
});
test("compact commander summary exposes canPublish/canApply and dry-run devLiveClaim false", () => {
const result = readiness();
const summary = buildCommanderReadinessSummary({
readiness: result,
targetRef: "origin/main",
generatedFromCommit: targetSha,
explicitLive: false,
cloudWebDistFreshness: { status: "pass", mismatches: [] },
codeAgentTimeoutReadiness: {
status: "pass",
frontendTimeoutMs: 1800000,
backendTimeoutMs: 1200000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 1200000,
transportWaitsForBackend: true,
summary: "ready"
},
runtimeReport: {
runtimeIdentity: {
ready: true,
runtime: { durable: true, ready: true },
readiness: { ready: true, durability: { ready: true } }
}
}
});
assert.equal(summary.kind, "hwlab-dev-rollout-readiness");
assert.equal(summary.canPublish, true);
assert.equal(summary.canApply, true);
assert.equal(summary.devLiveClaim, false);
assert.deepEqual(summary.blockedReasons, []);
assert.equal(summary.currentSourceCommit.shortCommitId, targetSha.slice(0, 7));
});
test("compact summary blocks publish on stale Cloud Web source dist", () => {
const result = readiness();
const summary = buildCommanderReadinessSummary({
readiness: result,
targetRef: "origin/main",
generatedFromCommit: targetSha,
explicitLive: false,
cloudWebDistFreshness: { status: "blocked", mismatches: ["index.html"] },
codeAgentTimeoutReadiness: {
status: "pass",
frontendTimeoutMs: 1800000,
backendTimeoutMs: 1200000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 1200000,
transportWaitsForBackend: true,
summary: "ready"
},
runtimeReport: {
runtimeIdentity: {
ready: true,
runtime: { durable: true, ready: true },
readiness: { ready: true, durability: { ready: true } }
}
}
});
assert.equal(summary.canPublish, false);
assert.equal(summary.canApply, false);
assert.equal(summary.cloudWebBuildFreshness.status, "blocked");
assert.ok(summary.blockedReasons.some((item) => item.id === "cloud-web-build-freshness"));
assert.ok(summary.nextCommands.includes("bun run --cwd web/hwlab-cloud-web build"));
});
test("compact summary separates Code Agent timeout and durable runtime blockers from apply readiness", () => {
const result = readiness();
const summary = buildCommanderReadinessSummary({
readiness: result,
targetRef: "origin/main",
generatedFromCommit: targetSha,
explicitLive: false,
cloudWebDistFreshness: { status: "pass", mismatches: [] },
codeAgentTimeoutReadiness: {
status: "blocked",
frontendTimeoutMs: 4500,
backendTimeoutMs: 1200000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 1200000,
transportWaitsForBackend: false,
summary: "Code Agent browser timeout is too short."
},
runtimeReport: {
runtimeIdentity: {
ready: false,
runtime: {
durable: false,
ready: false,
blocker: "runtime_durable_adapter_query_blocked",
connection: { queryResult: "query_blocked" }
},
readiness: {
ready: false,
durability: {
ready: false,
blocker: "runtime_durable_adapter_query_blocked",
blockedLayer: "durability_query",
queryResult: "query_blocked"
}
},
blockerCodes: ["runtime_durable_adapter_query_blocked"]
}
}
});
assert.equal(summary.canPublish, false);
assert.equal(summary.canApply, false);
assert.equal(summary.codeAgentTimeoutReadiness.status, "blocked");
assert.equal(summary.runtimeDurableBlocker.classification, "runtime_durable_adapter_query_blocked");
assert.ok(summary.blockedReasons.some((item) => item.id === "code-agent-timeout-readiness"));
assert.ok(summary.blockedReasons.some((item) => item.id === "runtime-durable:runtime_durable_adapter_query_blocked"));
});
test("compact summary blocks publish when Code Agent transport timeout does not exceed backend timeout", () => {
const result = readiness();
const summary = buildCommanderReadinessSummary({
readiness: result,
targetRef: "origin/main",
generatedFromCommit: targetSha,
explicitLive: false,
cloudWebDistFreshness: { status: "pass", mismatches: [] },
codeAgentTimeoutReadiness: {
status: "blocked",
frontendTimeoutMs: 1200000,
backendTimeoutMs: 1200000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 1200000,
transportWaitsForBackend: false,
summary: "Code Agent timeout layering is unsafe."
},
runtimeReport: {
runtimeIdentity: {
ready: true,
runtime: { durable: true, ready: true },
readiness: { ready: true, durability: { ready: true } }
}
}
});
assert.equal(summary.canPublish, false);
assert.equal(summary.canApply, false);
assert.equal(summary.codeAgentTimeoutReadiness.transportWaitsForBackend, false);
assert.ok(summary.blockedReasons.some((item) => item.id === "code-agent-timeout-readiness"));
});
test("compact summary keeps provider-secret blockers out of publish but blocks apply", () => {
const result = readiness();
const summary = buildCommanderReadinessSummary({
readiness: result,
targetRef: "origin/main",
generatedFromCommit: targetSha,
explicitLive: false,
cloudWebDistFreshness: { status: "pass", mismatches: [] },
codeAgentTimeoutReadiness: {
status: "pass",
frontendTimeoutMs: 1800000,
backendTimeoutMs: 1200000,
requiredFrontendTimeoutMs: 35000,
requiredBackendTimeoutMs: 1200000,
transportWaitsForBackend: true,
summary: "ready"
},
edgeReport: {
blockers: [
{
scope: "code-agent-provider-secret",
classification: "provider_secret_missing",
summary: "Code Agent provider Secret is missing."
}
]
},
runtimeReport: {
runtimeIdentity: {
ready: true,
runtime: { durable: true, ready: true },
readiness: { ready: true, durability: { ready: true } }
}
}
});
assert.equal(summary.canPublish, true);
assert.equal(summary.canApply, false);
assert.equal(summary.codeAgentProviderReadiness.status, "blocked");
assert.ok(summary.blockedReasons.some((item) => item.id === "code-agent-provider:code-agent-provider-secret"));
});