Formalize Cloud Web DEV CD contract
Merge PR #152 after Code Queue rebase and validation. This lands the DEV Cloud Web publish/apply contract, dist freshness checks, artifact identity evidence, and read-only rollout observation. No PROD changes and no live deploy claim.
This commit is contained in:
@@ -585,13 +585,37 @@ async function validateReport(relativePath) {
|
||||
const serviceLabel = `${label}.artifactPublish.services[${index}]`;
|
||||
assertObject(service, serviceLabel);
|
||||
assertString(service.serviceId, `${serviceLabel}.serviceId`);
|
||||
if (Object.hasOwn(service, "sourceCommitId")) {
|
||||
assertString(service.sourceCommitId, `${serviceLabel}.sourceCommitId`);
|
||||
}
|
||||
assertString(service.status, `${serviceLabel}.status`);
|
||||
assertString(service.image, `${serviceLabel}.image`);
|
||||
assertString(service.imageTag, `${serviceLabel}.imageTag`);
|
||||
assertShaOrNotPublished(service.digest, `${serviceLabel}.digest`);
|
||||
assertString(service.implementationState, `${serviceLabel}.implementationState`);
|
||||
assertString(service.sourceState, `${serviceLabel}.sourceState`);
|
||||
assert.ok(
|
||||
artifactSourceStates.has(service.sourceState),
|
||||
`${serviceLabel}.sourceState must be source-present or intentionally-disabled`
|
||||
);
|
||||
if (Object.hasOwn(service, "distFreshness")) {
|
||||
assertObject(service.distFreshness, `${serviceLabel}.distFreshness`);
|
||||
assert.equal(service.distFreshness.status, "pass", `${serviceLabel}.distFreshness.status`);
|
||||
assert.equal(service.distFreshness.distPath, "web/hwlab-cloud-web/dist", `${serviceLabel}.distFreshness.distPath`);
|
||||
assert.equal(
|
||||
service.distFreshness.buildCommand,
|
||||
"node web/hwlab-cloud-web/scripts/build.mjs",
|
||||
`${serviceLabel}.distFreshness.buildCommand`
|
||||
);
|
||||
assert.equal(
|
||||
service.distFreshness.freshnessCommand,
|
||||
"node web/hwlab-cloud-web/scripts/build.mjs",
|
||||
`${serviceLabel}.distFreshness.freshnessCommand`
|
||||
);
|
||||
assertArray(service.distFreshness.files, `${serviceLabel}.distFreshness.files`);
|
||||
assertArray(service.distFreshness.mismatches, `${serviceLabel}.distFreshness.mismatches`);
|
||||
assert.equal(service.distFreshness.mismatches.length, 0, `${serviceLabel}.distFreshness.mismatches`);
|
||||
}
|
||||
if (service.sourceState === "intentionally-disabled") {
|
||||
assert.equal(service.entrypoint, null, `${serviceLabel}.entrypoint must be null when intentionally disabled`);
|
||||
}
|
||||
@@ -813,6 +837,48 @@ function assertDevDeployApplyReport(report, label) {
|
||||
assertString(replacement.reason, `${replacementLabel}.reason`);
|
||||
}
|
||||
|
||||
if (Object.hasOwn(plan, "cloudWebRollout")) {
|
||||
assertObject(plan.cloudWebRollout, `${label}.devDeployApply.cloudWebRollout`);
|
||||
for (const field of [
|
||||
"serviceId",
|
||||
"namespace",
|
||||
"status",
|
||||
"sourceCommitId",
|
||||
"image",
|
||||
"imageTag",
|
||||
"digest",
|
||||
"publishState",
|
||||
"rolloutRevision",
|
||||
"liveImage",
|
||||
"imageMatchesDesired",
|
||||
"verificationCommand",
|
||||
"readCommand"
|
||||
]) {
|
||||
assert.ok(Object.hasOwn(plan.cloudWebRollout, field), `${label}.devDeployApply.cloudWebRollout missing ${field}`);
|
||||
}
|
||||
assert.equal(plan.cloudWebRollout.serviceId, "hwlab-cloud-web", `${label}.devDeployApply.cloudWebRollout.serviceId`);
|
||||
assert.equal(plan.cloudWebRollout.namespace, "hwlab-dev", `${label}.devDeployApply.cloudWebRollout.namespace`);
|
||||
assert.ok(["observed", "blocked", "not_evaluated"].includes(plan.cloudWebRollout.status), `${label}.devDeployApply.cloudWebRollout.status`);
|
||||
assertString(plan.cloudWebRollout.sourceCommitId, `${label}.devDeployApply.cloudWebRollout.sourceCommitId`);
|
||||
assertString(plan.cloudWebRollout.image, `${label}.devDeployApply.cloudWebRollout.image`);
|
||||
assertString(plan.cloudWebRollout.imageTag, `${label}.devDeployApply.cloudWebRollout.imageTag`);
|
||||
assertShaOrNotPublished(plan.cloudWebRollout.digest, `${label}.devDeployApply.cloudWebRollout.digest`);
|
||||
if (plan.cloudWebRollout.rolloutRevision !== null) {
|
||||
assertString(plan.cloudWebRollout.rolloutRevision, `${label}.devDeployApply.cloudWebRollout.rolloutRevision`);
|
||||
}
|
||||
if (plan.cloudWebRollout.liveImage !== null) {
|
||||
assertString(plan.cloudWebRollout.liveImage, `${label}.devDeployApply.cloudWebRollout.liveImage`);
|
||||
}
|
||||
assert.equal(typeof plan.cloudWebRollout.imageMatchesDesired, "boolean", `${label}.devDeployApply.cloudWebRollout.imageMatchesDesired`);
|
||||
assert.match(plan.cloudWebRollout.verificationCommand, /rollout status deployment\/hwlab-cloud-web/u, `${label}.devDeployApply.cloudWebRollout.verificationCommand`);
|
||||
assert.match(plan.cloudWebRollout.verificationCommand, /^KUBECONFIG=\/etc\/rancher\/k3s\/k3s\.yaml kubectl /u, `${label}.devDeployApply.cloudWebRollout.verificationCommand`);
|
||||
assert.match(plan.cloudWebRollout.readCommand, /get deployment hwlab-cloud-web/u, `${label}.devDeployApply.cloudWebRollout.readCommand`);
|
||||
assert.match(plan.cloudWebRollout.readCommand, /^KUBECONFIG=\/etc\/rancher\/k3s\/k3s\.yaml kubectl /u, `${label}.devDeployApply.cloudWebRollout.readCommand`);
|
||||
if (plan.cloudWebRollout.status === "blocked") {
|
||||
assertString(plan.cloudWebRollout.blocker, `${label}.devDeployApply.cloudWebRollout.blocker`);
|
||||
}
|
||||
}
|
||||
|
||||
assertObject(plan.manualCommands, `${label}.devDeployApply.manualCommands`);
|
||||
assert.ok(["blocked", "ready"].includes(plan.manualCommands.status), `${label}.devDeployApply.manualCommands.status`);
|
||||
assertCommandList(plan.manualCommands.beforeHumanApproval, `${label}.devDeployApply.manualCommands.beforeHumanApproval`);
|
||||
|
||||
Reference in New Issue
Block a user