636 lines
28 KiB
JavaScript
636 lines
28 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { execFile } from "node:child_process";
|
|
import { mkdtemp, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
import { promisify } from "node:util";
|
|
|
|
import { buildDesiredStatePlan } from "./src/deploy-desired-state-plan.mjs";
|
|
import { writeStructuredFile } from "./src/structured-config.mjs";
|
|
|
|
const execFileAsync = promisify(execFile);
|
|
|
|
async function git(repoRoot, args) {
|
|
const result = await execFileAsync("git", args, {
|
|
cwd: repoRoot,
|
|
maxBuffer: 1024 * 1024
|
|
});
|
|
return result.stdout.trim();
|
|
}
|
|
|
|
async function makeFixture({
|
|
serviceId = "hwlab-cloud-api",
|
|
commitId = "abc1234",
|
|
deployImageTag = commitId,
|
|
catalogCommitId = commitId,
|
|
catalogServiceCommitId = catalogCommitId,
|
|
catalogImageTag = catalogServiceCommitId.slice(0, 7),
|
|
deployEnvCommitId = commitId,
|
|
deployEnvImageTag = commitId,
|
|
deployEnvImage = null,
|
|
deployEnvMirrors = false,
|
|
deploySkillsCommitId = null,
|
|
deployCodeAgentProviderEnv = true,
|
|
deployDbEnv = true,
|
|
deployDbSslMode = "disable",
|
|
workloadTag = commitId,
|
|
workloadEnvCommitId = commitId,
|
|
workloadEnvImageTag = commitId,
|
|
workloadEnvImage = null,
|
|
workloadEnvMirrors = true,
|
|
workloadSkillsCommitId = null,
|
|
workloadCodeAgentProviderEnv = true,
|
|
workloadCodexHomeVolumeMounts = true,
|
|
workloadCodexHomeVolumes = true,
|
|
workloadWorkspaceVolumeMount = true,
|
|
workloadWorkspaceVolume = true,
|
|
workloadWorkspaceInitContainer = true,
|
|
workloadWorkspaceRecreateStrategy = true,
|
|
workloadWorkspacePvc = true,
|
|
workloadDbEnv = true,
|
|
workloadDbSslMode = "disable"
|
|
} = {}) {
|
|
const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-desired-state-"));
|
|
await mkdir(path.join(root, "deploy/k8s/base"), { recursive: true });
|
|
const image = `127.0.0.1:5000/hwlab/${serviceId}:${deployImageTag}`;
|
|
const catalogImage = `127.0.0.1:5000/hwlab/${serviceId}:${catalogImageTag}`;
|
|
const workloadImage = `127.0.0.1:5000/hwlab/${serviceId}:${workloadTag}`;
|
|
const providerBaseUrl = "http://127.0.0.1:49280/responses";
|
|
const providerNoProxy = "hyueapi.com,.hyueapi.com,hyui.com,.hyui.com,127.0.0.1,localhost,::1,api.minimaxi.com,.minimaxi.com";
|
|
const providerEnv =
|
|
serviceId === "hwlab-cloud-api" && deployCodeAgentProviderEnv
|
|
? {
|
|
HWLAB_CODE_AGENT_PROVIDER: "codex-stdio",
|
|
HWLAB_CODE_AGENT_MODEL: "gpt-5.5",
|
|
HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE: "deepseek",
|
|
HWLAB_CODE_AGENT_DEEPSEEK_MODEL: "deepseek-chat",
|
|
HWLAB_CODE_AGENT_DEEPSEEK_BASE_URL: "http://hwlab-deepseek-proxy.hwlab-dev.svc.cluster.local:4000/v1/responses",
|
|
HWLAB_CODE_AGENT_CODEX_API_MODEL: "gpt-5.5",
|
|
HWLAB_CODE_AGENT_CODEX_API_BASE_URL: providerBaseUrl,
|
|
HWLAB_CODE_AGENT_CODEX_API_UPSTREAM_BASE_URL: "https://hyueapi.com",
|
|
HWLAB_CODE_AGENT_CODEX_API_FORWARDER_PORT: "49280",
|
|
HWLAB_CODE_AGENT_OPENAI_BASE_URL: providerBaseUrl,
|
|
HWLAB_CODE_AGENT_WORKSPACE: "/workspace/hwlab",
|
|
HWLAB_CODE_AGENT_CODEX_WORKSPACE: "/workspace/hwlab",
|
|
CODEX_HOME: "/codex-home",
|
|
NO_PROXY: providerNoProxy,
|
|
no_proxy: providerNoProxy,
|
|
OPENAI_API_KEY: "secretRef:hwlab-code-agent-provider/openai-api-key"
|
|
}
|
|
: {};
|
|
const workloadProviderEnv =
|
|
serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv
|
|
? [
|
|
{ name: "HWLAB_CODE_AGENT_PROVIDER", value: "codex-stdio" },
|
|
{ name: "HWLAB_CODE_AGENT_MODEL", value: "gpt-5.5" },
|
|
{ name: "HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE", value: "deepseek" },
|
|
{ name: "HWLAB_CODE_AGENT_DEEPSEEK_MODEL", value: "deepseek-chat" },
|
|
{ name: "HWLAB_CODE_AGENT_DEEPSEEK_BASE_URL", value: "http://hwlab-deepseek-proxy.hwlab-dev.svc.cluster.local:4000/v1/responses" },
|
|
{ name: "HWLAB_CODE_AGENT_CODEX_API_MODEL", value: "gpt-5.5" },
|
|
{ name: "HWLAB_CODE_AGENT_CODEX_API_BASE_URL", value: providerBaseUrl },
|
|
{ name: "HWLAB_CODE_AGENT_CODEX_API_UPSTREAM_BASE_URL", value: "https://hyueapi.com" },
|
|
{ name: "HWLAB_CODE_AGENT_CODEX_API_FORWARDER_PORT", value: "49280" },
|
|
{ name: "HWLAB_CODE_AGENT_OPENAI_BASE_URL", value: providerBaseUrl },
|
|
{ name: "HWLAB_CODE_AGENT_WORKSPACE", value: "/workspace/hwlab" },
|
|
{ name: "HWLAB_CODE_AGENT_CODEX_WORKSPACE", value: "/workspace/hwlab" },
|
|
{ name: "CODEX_HOME", value: "/codex-home" },
|
|
{ name: "NO_PROXY", value: providerNoProxy },
|
|
{ name: "no_proxy", value: providerNoProxy },
|
|
{
|
|
name: "OPENAI_API_KEY",
|
|
valueFrom: {
|
|
secretKeyRef: {
|
|
name: "hwlab-code-agent-provider",
|
|
key: "openai-api-key"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
: [];
|
|
const dbEnv =
|
|
serviceId === "hwlab-cloud-api" && deployDbEnv
|
|
? {
|
|
HWLAB_CLOUD_DB_URL: "secretRef:hwlab-cloud-api-dev-db/database-url",
|
|
HWLAB_CLOUD_DB_SSL_MODE: deployDbSslMode
|
|
}
|
|
: {};
|
|
const workloadDbEntries =
|
|
serviceId === "hwlab-cloud-api" && workloadDbEnv
|
|
? [
|
|
{
|
|
name: "HWLAB_CLOUD_DB_URL",
|
|
valueFrom: {
|
|
secretKeyRef: {
|
|
name: "hwlab-cloud-api-dev-db",
|
|
key: "database-url"
|
|
}
|
|
}
|
|
},
|
|
{ name: "HWLAB_CLOUD_DB_SSL_MODE", value: workloadDbSslMode }
|
|
]
|
|
: [];
|
|
const deploy = {
|
|
manifestVersion: "v1",
|
|
environment: "dev",
|
|
services: [
|
|
{
|
|
serviceId,
|
|
namespace: "hwlab-dev",
|
|
healthPath: "/health/live",
|
|
profile: "dev",
|
|
replicas: 1,
|
|
env: {
|
|
...(deployEnvMirrors
|
|
? {
|
|
HWLAB_COMMIT_ID: deployEnvCommitId,
|
|
HWLAB_IMAGE: deployEnvImage ?? image,
|
|
HWLAB_IMAGE_TAG: deployEnvImageTag,
|
|
...(deploySkillsCommitId ? { HWLAB_SKILLS_COMMIT_ID: deploySkillsCommitId } : {})
|
|
}
|
|
: {}),
|
|
...dbEnv,
|
|
...providerEnv
|
|
}
|
|
}
|
|
]
|
|
};
|
|
const catalog = {
|
|
catalogVersion: "v1",
|
|
kind: "hwlab-artifact-catalog",
|
|
environment: "dev",
|
|
profile: "dev",
|
|
namespace: "hwlab-dev",
|
|
endpoint: "http://74.48.78.17:16667",
|
|
commitId: catalogCommitId,
|
|
artifactState: "contract-skeleton",
|
|
publish: {
|
|
ciPublished: false,
|
|
registryVerified: false,
|
|
provenance: "not_available_until_publish"
|
|
},
|
|
services: [
|
|
{
|
|
serviceId,
|
|
commitId: catalogServiceCommitId,
|
|
image: catalogImage,
|
|
imageTag: catalogImageTag,
|
|
digest: "not_published",
|
|
publishState: "skeleton-only",
|
|
artifactRequired: true
|
|
}
|
|
]
|
|
};
|
|
const workloads = {
|
|
apiVersion: "v1",
|
|
kind: "List",
|
|
items: [
|
|
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv && workloadWorkspacePvc
|
|
? [
|
|
{
|
|
apiVersion: "v1",
|
|
kind: "PersistentVolumeClaim",
|
|
metadata: {
|
|
name: "hwlab-code-agent-workspace",
|
|
namespace: "hwlab-dev",
|
|
labels: {
|
|
"hwlab.pikastech.local/service-id": "hwlab-code-agent-workspace"
|
|
}
|
|
},
|
|
spec: {
|
|
accessModes: ["ReadWriteOnce"],
|
|
resources: {
|
|
requests: {
|
|
storage: "8Gi"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
: []),
|
|
{
|
|
apiVersion: "apps/v1",
|
|
kind: "Deployment",
|
|
metadata: {
|
|
name: serviceId,
|
|
namespace: "hwlab-dev",
|
|
labels: {
|
|
"hwlab.pikastech.local/service-id": serviceId
|
|
}
|
|
},
|
|
spec: {
|
|
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv && workloadWorkspaceRecreateStrategy
|
|
? {
|
|
strategy: {
|
|
type: "Recreate"
|
|
}
|
|
}
|
|
: {}),
|
|
template: {
|
|
spec: {
|
|
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv && workloadWorkspaceInitContainer
|
|
? {
|
|
initContainers: [
|
|
{
|
|
name: "hwlab-code-agent-workspace-init",
|
|
image: workloadImage,
|
|
command: [
|
|
"sh",
|
|
"-ceu",
|
|
"target=/workspace/hwlab\nmarker=\"$target/.hwlab-workspace-initialized\"\nmkdir -p \"$target\"\nif [ ! -e \"$marker\" ]; then\n cp -a /app/. \"$target\"/\n printf '%s\\n' copied-from-image > \"$marker\"\nfi\n"
|
|
],
|
|
volumeMounts: [
|
|
{ name: "hwlab-code-agent-workspace", mountPath: "/workspace" }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
: {}),
|
|
containers: [
|
|
{
|
|
name: serviceId,
|
|
image: workloadImage,
|
|
env: workloadEnvMirrors
|
|
? [
|
|
{ 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 }] : []),
|
|
...workloadDbEntries,
|
|
...workloadProviderEnv
|
|
]
|
|
: [],
|
|
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv && (workloadWorkspaceVolumeMount || workloadCodexHomeVolumeMounts)
|
|
? {
|
|
volumeMounts: [
|
|
...(workloadWorkspaceVolumeMount
|
|
? [{ name: "hwlab-code-agent-workspace", mountPath: "/workspace" }]
|
|
: []),
|
|
...(workloadCodexHomeVolumeMounts
|
|
? [
|
|
{ name: "hwlab-code-agent-codex-home", mountPath: "/codex-home" },
|
|
{ name: "hwlab-code-agent-codex-config", mountPath: "/codex-home/config.toml", subPath: "config.toml", readOnly: true },
|
|
{ name: "hwlab-code-agent-codex-auth", mountPath: "/codex-home/auth.json", subPath: "auth.json", readOnly: true }
|
|
]
|
|
: [])
|
|
]
|
|
}
|
|
: {})
|
|
},
|
|
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv
|
|
? [
|
|
{
|
|
name: "hwlab-codex-api-forwarder",
|
|
image: workloadImage,
|
|
command: ["/usr/local/bin/bun", "run", "/app/cmd/hwlab-codex-api-responses-forwarder/main.ts"],
|
|
ports: [{ name: "codex-api", containerPort: 49280 }],
|
|
env: [
|
|
{ name: "HWLAB_CODE_AGENT_CODEX_API_FORWARDER_HOST", value: "127.0.0.1" },
|
|
{ name: "HWLAB_CODE_AGENT_CODEX_API_FORWARDER_PORT", value: "49280" },
|
|
{ name: "HWLAB_CODE_AGENT_CODEX_API_UPSTREAM_BASE_URL", value: "https://hyueapi.com" },
|
|
{ name: "NO_PROXY", value: providerNoProxy },
|
|
{ name: "no_proxy", value: providerNoProxy }
|
|
]
|
|
}
|
|
]
|
|
: [])
|
|
],
|
|
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv && (workloadWorkspaceVolume || workloadCodexHomeVolumes)
|
|
? {
|
|
volumes: [
|
|
...(workloadWorkspaceVolume
|
|
? [{ name: "hwlab-code-agent-workspace", persistentVolumeClaim: { claimName: "hwlab-code-agent-workspace" } }]
|
|
: []),
|
|
...(workloadCodexHomeVolumes
|
|
? [
|
|
{ name: "hwlab-code-agent-codex-home", emptyDir: {} },
|
|
{ name: "hwlab-code-agent-codex-config", configMap: { name: "hwlab-code-agent-codex-config", items: [{ key: "config.toml", path: "config.toml" }] } },
|
|
{ name: "hwlab-code-agent-codex-auth", secret: { secretName: "hwlab-code-agent-codex-auth", items: [{ key: "auth.json", path: "auth.json" }] } }
|
|
]
|
|
: [])
|
|
]
|
|
}
|
|
: {})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|
|
await writeStructuredFile(root, "deploy/deploy.yaml", deploy);
|
|
await writeFile(path.join(root, "deploy/artifact-catalog.dev.json"), `${JSON.stringify(catalog, null, 2)}\n`);
|
|
await writeFile(path.join(root, "deploy/k8s/base/workloads.yaml"), `${JSON.stringify(workloads, null, 2)}\n`);
|
|
return root;
|
|
}
|
|
|
|
test("passes internally consistent desired-state", async () => {
|
|
const repoRoot = await makeFixture();
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "pass");
|
|
assert.equal(plan.summary.desiredCommitId, "abc1234");
|
|
assert.equal(plan.summary.presentMirrorCount, 3);
|
|
assert.deepEqual(plan.diagnostics, []);
|
|
});
|
|
|
|
test("passes mixed desired-state when unchanged services reuse service-level artifact tags", async () => {
|
|
const repoRoot = await makeFixture({
|
|
commitId: "803ba22",
|
|
catalogCommitId: "803ba22",
|
|
catalogServiceCommitId: "6a84959",
|
|
catalogImageTag: "6a84959",
|
|
workloadTag: "6a84959",
|
|
workloadEnvCommitId: "6a84959",
|
|
workloadEnvImageTag: "6a84959"
|
|
});
|
|
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
|
|
assert.equal(plan.status, "pass");
|
|
assert.equal(plan.summary.desiredCommitId, "803ba22");
|
|
assert.equal(plan.services[0].deploy.artifactIdentity, "human-authored-config");
|
|
assert.equal(plan.services[0].catalog.commitId, "6a84959");
|
|
assert.deepEqual(plan.diagnostics, []);
|
|
});
|
|
|
|
test("passes when cloud-web relies on render-generated runtime identity mirrors", async () => {
|
|
const repoRoot = await makeFixture({ serviceId: "hwlab-cloud-web", workloadEnvMirrors: false });
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "pass");
|
|
assert.equal(plan.summary.presentMirrorCount, 0);
|
|
assert.deepEqual(plan.diagnostics, []);
|
|
});
|
|
|
|
test("passes when cloud-api preserves provider env and DEV egress contract", async () => {
|
|
const repoRoot = await makeFixture();
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "pass");
|
|
assert.equal(plan.cloudApiDb.ready, true);
|
|
assert.equal(plan.cloudApiDb.sslMode.expected, "disable");
|
|
assert.equal(plan.cloudApiDb.sslMode.deployMatches, true);
|
|
assert.equal(plan.cloudApiDb.sslMode.workloadMatches, true);
|
|
assert.equal(plan.codeAgentProvider.ready, true);
|
|
assert.equal(plan.codeAgentProvider.provider, "codex-stdio");
|
|
assert.equal(plan.codeAgentProvider.runtimeProvider, "openai-responses");
|
|
assert.equal(plan.codeAgentProvider.backend, "hwlab-cloud-api/codex-app-server-stdio");
|
|
assert.equal(plan.codeAgentProvider.secretRef.present, true);
|
|
assert.equal(plan.codeAgentProvider.egress.deployMatchesDevProxy, true);
|
|
assert.equal(plan.codeAgentProvider.codexHome.present, true);
|
|
assert.equal(plan.codeAgentProvider.codexHome.writableHomeMountPresent, true);
|
|
assert.equal(plan.codeAgentProvider.codexHome.emptyDirPresent, true);
|
|
assert.equal(plan.codeAgentProvider.codexHome.configMapPresent, true);
|
|
assert.equal(plan.codeAgentProvider.codexHome.authSecretPresent, true);
|
|
assert.equal(plan.codeAgentProvider.workspace.present, true);
|
|
assert.equal(plan.codeAgentProvider.workspace.writableMountPresent, true);
|
|
assert.equal(plan.codeAgentProvider.workspace.persistentVolumeClaimPresent, true);
|
|
assert.equal(plan.codeAgentProvider.workspace.initContainerPresent, true);
|
|
assert.equal(plan.codeAgentProvider.workspace.recreateStrategy, true);
|
|
assert.deepEqual(plan.diagnostics, []);
|
|
});
|
|
|
|
test("blocks when cloud-api CODEX_HOME mount is missing its writable emptyDir volume", async () => {
|
|
const repoRoot = await makeFixture({ workloadCodexHomeVolumes: false });
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
const diagnostic = plan.diagnostics.find((entry) => entry.code === "code_agent_provider_contract_mismatch");
|
|
|
|
assert.equal(plan.status, "blocked");
|
|
assert.equal(plan.codeAgentProvider.ready, false);
|
|
assert.equal(plan.codeAgentProvider.codexHome.present, false);
|
|
assert.equal(plan.codeAgentProvider.codexHome.writableHomeMountPresent, true);
|
|
assert.equal(plan.codeAgentProvider.codexHome.emptyDirPresent, false);
|
|
assert.ok(diagnostic);
|
|
assert.ok(diagnostic.actual.missingCodexHomeContract.includes("/codex-home must be backed by emptyDir"));
|
|
});
|
|
|
|
test("blocks when cloud-api Code Agent workspace is not backed by PVC", async () => {
|
|
const repoRoot = await makeFixture({ workloadWorkspaceVolume: false });
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
const diagnostic = plan.diagnostics.find((entry) => entry.code === "code_agent_provider_contract_mismatch");
|
|
|
|
assert.equal(plan.status, "blocked");
|
|
assert.equal(plan.codeAgentProvider.ready, false);
|
|
assert.equal(plan.codeAgentProvider.workspace.present, false);
|
|
assert.equal(plan.codeAgentProvider.workspace.writableMountPresent, true);
|
|
assert.equal(plan.codeAgentProvider.workspace.persistentVolumeClaimPresent, false);
|
|
assert.ok(diagnostic);
|
|
assert.ok(diagnostic.actual.missingWorkspaceContract.includes("hwlab-code-agent-workspace must use PVC hwlab-code-agent-workspace"));
|
|
});
|
|
|
|
test("blocks when cloud-api Code Agent workspace rollout strategy is not Recreate", async () => {
|
|
const repoRoot = await makeFixture({ workloadWorkspaceRecreateStrategy: false });
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
const diagnostic = plan.diagnostics.find((entry) => entry.code === "code_agent_provider_contract_mismatch");
|
|
|
|
assert.equal(plan.status, "blocked");
|
|
assert.equal(plan.codeAgentProvider.ready, false);
|
|
assert.equal(plan.codeAgentProvider.workspace.present, false);
|
|
assert.equal(plan.codeAgentProvider.workspace.recreateStrategy, false);
|
|
assert.ok(diagnostic);
|
|
assert.ok(diagnostic.actual.missingWorkspaceContract.includes("hwlab-cloud-api rollout strategy must be Recreate"));
|
|
});
|
|
|
|
test("blocks when cloud-api CODEX_HOME mount is read-only", async () => {
|
|
const repoRoot = await makeFixture();
|
|
const workloadsPath = path.join(repoRoot, "deploy/k8s/base/workloads.yaml");
|
|
const workloads = JSON.parse(await readFile(workloadsPath, "utf8"));
|
|
const deployment = workloads.items.find((entry) => entry.kind === "Deployment");
|
|
deployment.spec.template.spec.containers[0].volumeMounts.find((entry) =>
|
|
entry.name === "hwlab-code-agent-codex-home"
|
|
).readOnly = true;
|
|
await writeFile(workloadsPath, `${JSON.stringify(workloads, null, 2)}\n`);
|
|
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
const diagnostic = plan.diagnostics.find((entry) => entry.code === "code_agent_provider_contract_mismatch");
|
|
|
|
assert.equal(plan.status, "blocked");
|
|
assert.equal(plan.codeAgentProvider.ready, false);
|
|
assert.equal(plan.codeAgentProvider.codexHome.present, false);
|
|
assert.equal(plan.codeAgentProvider.codexHome.writableHomeMountPresent, false);
|
|
assert.equal(plan.codeAgentProvider.codexHome.emptyDirPresent, true);
|
|
assert.ok(diagnostic);
|
|
assert.ok(diagnostic.actual.missingCodexHomeContract.includes("/codex-home must be a writable volumeMount"));
|
|
});
|
|
|
|
test("blocks when cloud-api DB SSL mode drifts back to require", async () => {
|
|
const repoRoot = await makeFixture({
|
|
deployDbSslMode: "require",
|
|
workloadDbSslMode: "require"
|
|
});
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "blocked");
|
|
assert.equal(plan.cloudApiDb.ready, false);
|
|
assert.equal(plan.cloudApiDb.sslMode.expected, "disable");
|
|
assert.equal(plan.cloudApiDb.sslMode.deployMatches, false);
|
|
assert.equal(plan.cloudApiDb.sslMode.workloadMatches, false);
|
|
assert.ok(plan.diagnostics.some((diagnostic) => diagnostic.code === "cloud_api_db_contract_mismatch"));
|
|
});
|
|
|
|
test("blocks when generated runtime identity leaks into deploy.yaml", async () => {
|
|
const repoRoot = await makeFixture({
|
|
serviceId: "hwlab-cloud-web",
|
|
deployEnvMirrors: true,
|
|
workloadEnvMirrors: false
|
|
});
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "blocked");
|
|
assert.equal(plan.summary.blockers, 3);
|
|
assert.ok(plan.diagnostics.some((diagnostic) =>
|
|
diagnostic.code === "generated_artifact_identity" &&
|
|
diagnostic.path === "deploy/deploy.yaml.services.hwlab-cloud-web.env.HWLAB_COMMIT_ID"
|
|
));
|
|
assert.ok(plan.diagnostics.some((diagnostic) =>
|
|
diagnostic.code === "generated_artifact_identity" &&
|
|
diagnostic.path.endsWith(".env.HWLAB_IMAGE_TAG")
|
|
));
|
|
});
|
|
|
|
test("blocks when cloud-api provider env is missing from desired state", async () => {
|
|
const repoRoot = await makeFixture({ deployCodeAgentProviderEnv: false, workloadCodeAgentProviderEnv: false });
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "blocked");
|
|
assert.equal(plan.codeAgentProvider.ready, false);
|
|
assert.ok(plan.diagnostics.some((diagnostic) => diagnostic.code === "code_agent_provider_contract_mismatch"));
|
|
assert.ok(plan.diagnostics.some((diagnostic) => diagnostic.path === "deploy.codeAgentProvider"));
|
|
});
|
|
|
|
test("blocks when cloud-api workload points Code Agent directly at public OpenAI", async () => {
|
|
const repoRoot = await makeFixture();
|
|
const workloadsPath = path.join(repoRoot, "deploy/k8s/base/workloads.yaml");
|
|
const workloads = JSON.parse(await readFile(workloadsPath, "utf8"));
|
|
const deployment = workloads.items.find((entry) => entry.kind === "Deployment");
|
|
const env = deployment.spec.template.spec.containers[0].env;
|
|
env.find((entry) => entry.name === "HWLAB_CODE_AGENT_OPENAI_BASE_URL").value = "https://api.openai.com/v1/responses";
|
|
await writeFile(workloadsPath, `${JSON.stringify(workloads, null, 2)}\n`);
|
|
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "blocked");
|
|
assert.equal(plan.codeAgentProvider.egress.directPublicOpenAi, true);
|
|
assert.ok(plan.diagnostics.some((diagnostic) => diagnostic.code === "code_agent_provider_contract_mismatch"));
|
|
});
|
|
|
|
test("target tag review is read-only promotion_pending when current state is uniformly older", async () => {
|
|
const repoRoot = await makeFixture();
|
|
const plan = await buildDesiredStatePlan({ repoRoot, targetTag: "def5678" });
|
|
assert.equal(plan.status, "planned");
|
|
assert.equal(plan.target.convergence.state, "promotion_pending");
|
|
assert.equal(plan.summary.blockers, 0);
|
|
assert.equal(plan.services[0].promotion.deployImage, null);
|
|
assert.match(plan.services[0].promotion.catalogImage, /:def5678$/u);
|
|
});
|
|
|
|
test("target check blocks when current desired-state is uniformly older", async () => {
|
|
const repoRoot = await makeFixture();
|
|
const plan = await buildDesiredStatePlan({ repoRoot, targetTag: "def5678", requireTargetConvergence: true });
|
|
assert.equal(plan.status, "blocked");
|
|
assert.equal(plan.target.convergence.state, "target_mismatch");
|
|
assert.equal(plan.target.convergenceRequirement, "target-check");
|
|
assert.ok(plan.diagnostics.some((diagnostic) =>
|
|
diagnostic.code === "target_desired_state_mismatch" &&
|
|
diagnostic.message.includes("stale artifact catalog is not pinned")
|
|
));
|
|
});
|
|
|
|
test("target check accepts accepted first-parent main on the checked-out merge commit", async () => {
|
|
const repoRoot = await makeFixture();
|
|
await git(repoRoot, ["init", "-b", "main"]);
|
|
await git(repoRoot, ["config", "user.email", "test@example.invalid"]);
|
|
await git(repoRoot, ["config", "user.name", "HWLAB Test"]);
|
|
await git(repoRoot, ["add", "."]);
|
|
await git(repoRoot, ["commit", "-m", "base"]);
|
|
|
|
const acceptedMain = await git(repoRoot, ["rev-parse", "HEAD"]);
|
|
const acceptedTag = acceptedMain.slice(0, 7);
|
|
await git(repoRoot, ["checkout", "-b", "desired-state-refresh"]);
|
|
|
|
for (const relativePath of [
|
|
"deploy/deploy.yaml",
|
|
"deploy/artifact-catalog.dev.json",
|
|
"deploy/k8s/base/workloads.yaml"
|
|
]) {
|
|
const filePath = path.join(repoRoot, relativePath);
|
|
const raw = await readFile(filePath, "utf8");
|
|
await writeFile(filePath, raw.replaceAll("abc1234", acceptedTag));
|
|
}
|
|
await git(repoRoot, ["add", "."]);
|
|
await git(repoRoot, ["commit", "-m", "refresh desired-state"]);
|
|
await git(repoRoot, ["checkout", "main"]);
|
|
await git(repoRoot, ["merge", "--no-ff", "desired-state-refresh", "-m", "merge desired-state refresh"]);
|
|
|
|
const mergeCommit = await git(repoRoot, ["rev-parse", "HEAD"]);
|
|
const plan = await buildDesiredStatePlan({ repoRoot, targetRef: "HEAD", requireTargetConvergence: true });
|
|
|
|
assert.equal(plan.status, "pass");
|
|
assert.equal(plan.target.commitId, mergeCommit);
|
|
assert.equal(plan.target.acceptedCurrentMain.commitId, acceptedMain);
|
|
assert.equal(plan.target.comparisonCommitId, acceptedMain);
|
|
assert.equal(plan.target.comparisonTag, acceptedTag);
|
|
assert.equal(plan.target.convergence.state, "accepted_main_promoted");
|
|
assert.deepEqual(plan.diagnostics, []);
|
|
});
|
|
|
|
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("ignores generated workload mirror drift because render owns runtime identity", async () => {
|
|
const repoRoot = await makeFixture({ workloadEnvImageTag: "badcafe" });
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "pass");
|
|
assert.deepEqual(plan.diagnostics, []);
|
|
});
|
|
|
|
test("blocks on skills commit mirror leak in deploy.yaml", async () => {
|
|
const repoRoot = await makeFixture({ deployEnvMirrors: true, deploySkillsCommitId: "badcafe" });
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "blocked");
|
|
assert.ok(plan.diagnostics.some((diagnostic) =>
|
|
diagnostic.code === "generated_artifact_identity" &&
|
|
diagnostic.path.endsWith("HWLAB_SKILLS_COMMIT_ID")
|
|
));
|
|
});
|
|
|
|
test("ignores workload image drift because catalog is artifact truth", async () => {
|
|
const repoRoot = await makeFixture({ workloadTag: "badcafe" });
|
|
const plan = await buildDesiredStatePlan({ repoRoot });
|
|
assert.equal(plan.status, "pass");
|
|
assert.deepEqual(plan.diagnostics, []);
|
|
});
|
|
|
|
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");
|
|
assert.ok(plan.diagnostics.some((diagnostic) => diagnostic.code === "partial_target_drift"));
|
|
});
|