fix: gate deploy desired-state promotion drift

This commit is contained in:
Code Queue Review
2026-05-22 15:23:52 +00:00
parent c7de4745f4
commit e282b7c6e8
11 changed files with 329 additions and 175 deletions
+76 -14
View File
@@ -6,11 +6,26 @@ import test from "node:test";
import { buildDesiredStatePlan } from "./src/deploy-desired-state-plan.mjs";
async function makeFixture({ commitId = "abc1234", workloadTag = commitId, workloadEnvTag = commitId } = {}) {
async function makeFixture({
commitId = "abc1234",
catalogCommitId = commitId,
catalogServiceCommitId = catalogCommitId,
catalogImageTag = catalogServiceCommitId.slice(0, 7),
deployEnvCommitId = commitId,
deployEnvImageTag = commitId,
deployEnvImage = null,
deploySkillsCommitId = null,
workloadTag = commitId,
workloadEnvCommitId = commitId,
workloadEnvImageTag = commitId,
workloadEnvImage = null,
workloadSkillsCommitId = null
} = {}) {
const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-desired-state-"));
await mkdir(path.join(root, "deploy/k8s/base"), { recursive: true });
await mkdir(path.join(root, "reports/dev-gate"), { recursive: true });
const image = `127.0.0.1:5000/hwlab/hwlab-cloud-api:${commitId}`;
const catalogImage = `127.0.0.1:5000/hwlab/hwlab-cloud-api:${catalogImageTag}`;
const workloadImage = `127.0.0.1:5000/hwlab/hwlab-cloud-api:${workloadTag}`;
const deploy = {
manifestVersion: "v1",
@@ -25,9 +40,10 @@ async function makeFixture({ commitId = "abc1234", workloadTag = commitId, workl
profile: "dev",
replicas: 1,
env: {
HWLAB_COMMIT_ID: commitId,
HWLAB_IMAGE: image,
HWLAB_IMAGE_TAG: commitId
HWLAB_COMMIT_ID: deployEnvCommitId,
HWLAB_IMAGE: deployEnvImage ?? image,
HWLAB_IMAGE_TAG: deployEnvImageTag,
...(deploySkillsCommitId ? { HWLAB_SKILLS_COMMIT_ID: deploySkillsCommitId } : {})
}
}
]
@@ -39,7 +55,7 @@ async function makeFixture({ commitId = "abc1234", workloadTag = commitId, workl
profile: "dev",
namespace: "hwlab-dev",
endpoint: "http://74.48.78.17:16667",
commitId,
commitId: catalogCommitId,
artifactState: "contract-skeleton",
publish: {
ciPublished: false,
@@ -49,9 +65,9 @@ async function makeFixture({ commitId = "abc1234", workloadTag = commitId, workl
services: [
{
serviceId: "hwlab-cloud-api",
commitId,
image,
imageTag: commitId,
commitId: catalogServiceCommitId,
image: catalogImage,
imageTag: catalogImageTag,
digest: "not_published",
publishState: "skeleton-only",
artifactRequired: true
@@ -80,9 +96,10 @@ async function makeFixture({ commitId = "abc1234", workloadTag = commitId, workl
name: "hwlab-cloud-api",
image: workloadImage,
env: [
{ name: "HWLAB_COMMIT_ID", value: commitId },
{ name: "HWLAB_IMAGE", value: image },
{ name: "HWLAB_IMAGE_TAG", value: workloadEnvTag }
{ name: "HWLAB_COMMIT_ID", value: workloadEnvCommitId },
{ name: "HWLAB_IMAGE", value: workloadEnvImage ?? image },
{ name: "HWLAB_IMAGE_TAG", value: workloadEnvImageTag },
...(workloadSkillsCommitId ? [{ name: "HWLAB_SKILLS_COMMIT_ID", value: workloadSkillsCommitId }] : [])
]
}
]
@@ -116,8 +133,35 @@ test("target tag review is read-only promotion_pending when current state is uni
assert.match(plan.services[0].promotion.deployImage, /:def5678$/u);
});
test("promotion commit check blocks when current desired-state is uniformly older", async () => {
const repoRoot = await makeFixture();
const plan = await buildDesiredStatePlan({ repoRoot, promotionCommit: "def5678" });
assert.equal(plan.status, "blocked");
assert.equal(plan.target.convergence.state, "promotion_mismatch");
assert.ok(plan.diagnostics.some((diagnostic) => diagnostic.code === "promotion_commit_mismatch"));
});
test("promotion commit check passes when every desired-state field is converged", async () => {
const repoRoot = await makeFixture({ commitId: "def5678" });
const plan = await buildDesiredStatePlan({ repoRoot, promotionCommit: "def5678" });
assert.equal(plan.status, "pass");
assert.equal(plan.target.convergence.state, "already_promoted");
assert.deepEqual(plan.diagnostics, []);
});
test("promotion commit check blocks an explicit non-matching target tag", async () => {
const repoRoot = await makeFixture({ commitId: "def5678" });
const plan = await buildDesiredStatePlan({
repoRoot,
promotionCommit: "def5678",
targetTag: "abc1234"
});
assert.equal(plan.status, "blocked");
assert.ok(plan.diagnostics.some((diagnostic) => diagnostic.code === "promotion_tag_mismatch"));
});
test("blocks on mirror drift", async () => {
const repoRoot = await makeFixture({ workloadEnvTag: "badcafe" });
const repoRoot = await makeFixture({ workloadEnvImageTag: "badcafe" });
const plan = await buildDesiredStatePlan({ repoRoot });
assert.equal(plan.status, "blocked");
assert.equal(plan.summary.blockers, 1);
@@ -125,6 +169,16 @@ test("blocks on mirror drift", async () => {
assert.match(plan.diagnostics[0].path, /HWLAB_IMAGE_TAG/u);
});
test("blocks on skills commit mirror drift", async () => {
const repoRoot = await makeFixture({ deploySkillsCommitId: "badcafe" });
const plan = await buildDesiredStatePlan({ repoRoot });
assert.equal(plan.status, "blocked");
assert.ok(plan.diagnostics.some((diagnostic) =>
diagnostic.code === "mirror_mismatch" &&
diagnostic.path.endsWith("HWLAB_SKILLS_COMMIT_ID")
));
});
test("blocks on workload image drift", async () => {
const repoRoot = await makeFixture({ workloadTag: "badcafe" });
const plan = await buildDesiredStatePlan({ repoRoot });
@@ -133,8 +187,16 @@ test("blocks on workload image drift", async () => {
assert.ok(plan.diagnostics.some((diagnostic) => diagnostic.code === "image_mismatch"));
});
test("reports partial target drift as a blocker", async () => {
const repoRoot = await makeFixture({ workloadTag: "def5678", workloadEnvTag: "def5678" });
test("reports partial target drift when catalog top-level commit moves but services stay old", async () => {
const repoRoot = await makeFixture({ catalogCommitId: "def5678" });
const plan = await buildDesiredStatePlan({ repoRoot, targetTag: "def5678" });
assert.equal(plan.status, "blocked");
assert.equal(plan.target.convergence.state, "partial_drift");
assert.ok(plan.diagnostics.some((diagnostic) => diagnostic.code === "partial_target_drift"));
});
test("reports partial target drift as a blocker", async () => {
const repoRoot = await makeFixture({ workloadTag: "def5678", workloadEnvImageTag: "def5678" });
const plan = await buildDesiredStatePlan({ repoRoot, targetTag: "def5678" });
assert.equal(plan.status, "blocked");
assert.equal(plan.target.convergence.state, "partial_drift");