test: guard artifact runtime readiness
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import {
|
||||
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"));
|
||||
});
|
||||
Reference in New Issue
Block a user