fix: restore codex-api via pod-local forwarder

This commit is contained in:
Codex
2026-05-26 16:30:31 +08:00
parent c2344b2950
commit f1067bb51f
16 changed files with 846 additions and 69 deletions
+3 -3
View File
@@ -309,12 +309,12 @@ async function runLocalContractSmoke() {
logOk("providerStatus=401 blocks even when readiness fields look feasible");
const providerEnv = {
HWLAB_CODE_AGENT_OPENAI_BASE_URL: "http://172.26.26.227:17680/v1/responses",
HWLAB_CODE_AGENT_OPENAI_BASE_URL: "http://127.0.0.1:49280/responses",
OPENAI_API_KEY: "test-openai-key-material"
};
assert.equal(codexAppServerProviderBaseUrl(providerEnv), "http://172.26.26.227:17680/v1");
assert.equal(codexAppServerProviderBaseUrl(providerEnv), "http://127.0.0.1:49280");
const providerArgs = codexAppServerArgs(providerEnv).join(" ");
assert.match(providerArgs, /model_providers\.OpenAI\.base_url="http:\/\/172\.26\.26\.227:17680\/v1"/u);
assert.match(providerArgs, /model_providers\.OpenAI\.base_url="http:\/\/127\.0\.0\.1:49280"/u);
assert.match(providerArgs, /model_providers\.OpenAI\.name="OpenAI"/u);
assert.match(providerArgs, /model_providers\.OpenAI\.wire_api="responses"/u);
assert.match(providerArgs, /model_providers\.OpenAI\.requires_openai_auth=true/u);
+63 -7
View File
@@ -21,6 +21,7 @@ async function git(repoRoot, args) {
async function makeFixture({
serviceId = "hwlab-cloud-api",
commitId = "abc1234",
deployImageTag = commitId,
catalogCommitId = commitId,
catalogServiceCommitId = catalogCommitId,
catalogImageTag = catalogServiceCommitId.slice(0, 7),
@@ -46,19 +47,27 @@ async function makeFixture({
} = {}) {
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}:${commitId}`;
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://172.26.26.227:17680/v1/responses";
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,
CODEX_HOME: "/codex-home",
NO_PROXY: "hyueapi.com,.hyueapi.com,hyui.com,.hyui.com,127.0.0.1,localhost,::1,api.minimaxi.com,.minimaxi.com",
no_proxy: "hyueapi.com,.hyueapi.com,hyui.com,.hyui.com,127.0.0.1,localhost,::1,api.minimaxi.com,.minimaxi.com",
NO_PROXY: providerNoProxy,
no_proxy: providerNoProxy,
OPENAI_API_KEY: "secretRef:hwlab-code-agent-provider/openai-api-key"
}
: {};
@@ -67,10 +76,17 @@ async function makeFixture({
? [
{ 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: "CODEX_HOME", value: "/codex-home" },
{ name: "NO_PROXY", value: "hyueapi.com,.hyueapi.com,hyui.com,.hyui.com,127.0.0.1,localhost,::1,api.minimaxi.com,.minimaxi.com" },
{ name: "no_proxy", value: "hyueapi.com,.hyueapi.com,hyui.com,.hyui.com,127.0.0.1,localhost,::1,api.minimaxi.com,.minimaxi.com" },
{ name: "NO_PROXY", value: providerNoProxy },
{ name: "no_proxy", value: providerNoProxy },
{
name: "OPENAI_API_KEY",
valueFrom: {
@@ -195,7 +211,24 @@ async function makeFixture({
]
}
: {})
}
},
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv
? [
{
name: "hwlab-codex-api-forwarder",
image: workloadImage,
command: ["node", "/app/cmd/hwlab-codex-api-responses-forwarder/main.mjs"],
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 && workloadCodexHomeVolumes
? {
@@ -227,6 +260,29 @@ test("passes internally consistent desired-state", async () => {
assert.deepEqual(plan.diagnostics, []);
});
test("passes mixed desired-state when unchanged services reuse service-level artifact tags", async () => {
const repoRoot = await makeFixture({
commitId: "803ba22",
deployImageTag: "6a84959",
catalogCommitId: "803ba22",
catalogServiceCommitId: "6a84959",
catalogImageTag: "6a84959",
deployEnvCommitId: "6a84959",
deployEnvImageTag: "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.imageTag, "6a84959");
assert.equal(plan.services[0].catalog.commitId, "6a84959");
assert.deepEqual(plan.diagnostics, []);
});
test("passes when cloud-web owns runtime identity mirrors", async () => {
const repoRoot = await makeFixture({ serviceId: "hwlab-cloud-web" });
const plan = await buildDesiredStatePlan({ repoRoot });
+28 -4
View File
@@ -20,7 +20,7 @@ const defaultProdRuntimeEndpoint = process.env.HWLAB_G14_PROD_RUNTIME_ENDPOINT |
const defaultProdWebEndpoint = process.env.HWLAB_G14_PROD_WEB_ENDPOINT || "http://74.48.78.17:18666";
const defaultProxyUrl = process.env.HWLAB_G14_PROXY_URL || "http://127.0.0.1:10808";
const defaultAllProxyUrl = process.env.HWLAB_G14_ALL_PROXY_URL || "socks5h://127.0.0.1:10808";
const defaultNoProxy = process.env.HWLAB_G14_NO_PROXY || "127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,192.168.0.0/16,.svc,.cluster.local,kubernetes.default.svc,registry.hwlab-ci.svc,hwlab-registry.hwlab-ci.svc";
const defaultNoProxy = process.env.HWLAB_G14_NO_PROXY || "hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,192.168.0.0/16,.svc,.cluster.local,kubernetes.default.svc,registry.hwlab-ci.svc,hwlab-registry.hwlab-ci.svc";
const ciJsonRunnerImage = process.env.HWLAB_G14_CI_JSON_IMAGE || "mcr.microsoft.com/playwright@sha256:b0ab6f3cb99aa7803adbc14d9027ec1785fc6e433b97e134e0f8fe61683b6b53";
const ciToolsRunnerImage = process.env.HWLAB_G14_CI_TOOLS_IMAGE || "127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-v1";
const buildkitRunnerImage = process.env.HWLAB_G14_BUILDKIT_IMAGE || "moby/buildkit:rootless";
@@ -46,7 +46,9 @@ const moonBridgeSourceRef = process.env.HWLAB_G14_MOONBRIDGE_REF || "1b99888d3da
const moonBridgeImage = process.env.HWLAB_G14_MOONBRIDGE_IMAGE || `${defaultRegistryPrefix}/moonbridge:${moonBridgeSourceRef.slice(0, 12)}`;
const deepSeekProfileModel = process.env.HWLAB_G14_DEEPSEEK_PROFILE_MODEL || "deepseek-chat";
const codexApiProfileModel = process.env.HWLAB_G14_CODEX_API_PROFILE_MODEL || "gpt-5.5";
const codexApiProfileBaseUrl = process.env.HWLAB_G14_CODEX_API_PROFILE_BASE_URL || "http://172.26.26.227:17680/v1/responses";
const codexApiProfileBaseUrl = process.env.HWLAB_G14_CODEX_API_PROFILE_BASE_URL || "http://127.0.0.1:49280/responses";
const codexApiForwarderPort = process.env.HWLAB_G14_CODEX_API_FORWARDER_PORT || "49280";
const codexApiForwarderUpstreamBaseUrl = process.env.HWLAB_G14_CODEX_API_UPSTREAM_BASE_URL || "https://hyueapi.com";
const sourceCommitPattern = /^[a-f0-9]{7,40}$/u;
function proxyEnv() {
@@ -286,6 +288,26 @@ function deepSeekBaseUrl(namespace) {
return `http://hwlab-deepseek-proxy.${namespace}.svc.cluster.local:4000/v1/responses`;
}
function codeAgentNoProxy(namespace) {
return [
`${namespace}.svc.cluster.local`,
".svc",
".cluster.local",
"hyueapi.com",
".hyueapi.com",
"hyui.com",
".hyui.com",
"127.0.0.1",
"localhost",
"::1",
"10.0.0.0/8",
"10.42.0.0/16",
"10.43.0.0/16",
"api.minimaxi.com",
".minimaxi.com"
].join(",");
}
function namespaceScopedHost(value, namespace) {
if (typeof value !== "string") return value;
return value.replace(/\.hwlab-dev\.svc\.cluster\.local/gu, `.${namespace}.svc.cluster.local`);
@@ -380,8 +402,10 @@ function transformWorkloads({ workloads, deploy, source, registryPrefix, runtime
upsertEnv(container.env, "HWLAB_CODE_AGENT_DEEPSEEK_BASE_URL", deepSeekBaseUrl(namespace));
upsertEnv(container.env, "HWLAB_CODE_AGENT_CODEX_API_MODEL", codexApiProfileModel);
upsertEnv(container.env, "HWLAB_CODE_AGENT_CODEX_API_BASE_URL", codexApiProfileBaseUrl);
upsertEnv(container.env, "NO_PROXY", `${namespace}.svc.cluster.local,.svc,.cluster.local,127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,172.26.26.227,172.26.0.0/16`);
upsertEnv(container.env, "no_proxy", `${namespace}.svc.cluster.local,.svc,.cluster.local,127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,172.26.26.227,172.26.0.0/16`);
upsertEnv(container.env, "HWLAB_CODE_AGENT_CODEX_API_UPSTREAM_BASE_URL", codexApiForwarderUpstreamBaseUrl);
upsertEnv(container.env, "HWLAB_CODE_AGENT_CODEX_API_FORWARDER_PORT", codexApiForwarderPort);
upsertEnv(container.env, "NO_PROXY", codeAgentNoProxy(namespace));
upsertEnv(container.env, "no_proxy", codeAgentNoProxy(namespace));
}
if (serviceId === "hwlab-cloud-web") {
upsertEnv(container.env, "HWLAB_API_BASE_URL", `http://hwlab-cloud-api.${namespace}.svc.cluster.local:6667`);
+38 -2
View File
@@ -379,13 +379,20 @@ function validateCloudApiCodeAgentSource(ctx, env) {
const contract = DEV_CODE_AGENT_PROVIDER_CONTRACT;
expectEqual(ctx, env.HWLAB_CODE_AGENT_PROVIDER, contract.codeAgentProvider, "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_PROVIDER", "cloud API Code Agent provider");
expectEqual(ctx, env.HWLAB_CODE_AGENT_MODEL, contract.model, "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_MODEL", "cloud API Code Agent model");
expectEqual(ctx, env.HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE, contract.profiles.defaultProfile, "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE", "cloud API default provider profile");
expectEqual(ctx, env[contract.profiles.deepSeekModelEnv], "deepseek-chat", `$.services.hwlab-cloud-api.env.${contract.profiles.deepSeekModelEnv}`, "cloud API DeepSeek profile model");
expectEqual(ctx, env[contract.profiles.deepSeekBaseUrlEnv], contract.profiles.deepSeekBaseUrl, `$.services.hwlab-cloud-api.env.${contract.profiles.deepSeekBaseUrlEnv}`, "cloud API DeepSeek profile base URL");
expectEqual(ctx, env[contract.profiles.codexApiModelEnv], contract.model, `$.services.hwlab-cloud-api.env.${contract.profiles.codexApiModelEnv}`, "cloud API codex-api profile model");
expectEqual(ctx, env[contract.profiles.codexApiBaseUrlEnv], contract.egress.defaultBaseUrl, `$.services.hwlab-cloud-api.env.${contract.profiles.codexApiBaseUrlEnv}`, "cloud API codex-api profile base URL");
expectEqual(ctx, env[contract.forwarder.upstreamEnv], contract.forwarder.upstreamBaseUrl, `$.services.hwlab-cloud-api.env.${contract.forwarder.upstreamEnv}`, "cloud API codex-api upstream base URL");
expectEqual(ctx, env[contract.forwarder.portEnv], String(contract.forwarder.port), `$.services.hwlab-cloud-api.env.${contract.forwarder.portEnv}`, "cloud API codex-api forwarder port");
expectEqual(ctx, env.HWLAB_CODE_AGENT_TIMEOUT_MS, codeAgentBackendTimeoutMs, "$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_TIMEOUT_MS", "cloud API Code Agent hard timeout budget");
expectEqual(
ctx,
env.HWLAB_CODE_AGENT_OPENAI_BASE_URL,
contract.egress.defaultBaseUrl,
"$.services.hwlab-cloud-api.env.HWLAB_CODE_AGENT_OPENAI_BASE_URL",
"cloud API Code Agent DEV egress/proxy base URL"
"cloud API Code Agent pod-local Codex API forwarder base URL"
);
expectEqual(
ctx,
@@ -572,16 +579,24 @@ function validateCloudApiCodeAgentArtifacts(ctx, workloads) {
const secretRef = contract.secretRefs[0];
const container = mapByServiceId(listItems(workloads)).get("hwlab-cloud-api")?.spec?.template?.spec?.containers?.[0];
const env = new Map((container?.env ?? []).map((entry) => [entry.name, entry]));
const podContainers = mapByServiceId(listItems(workloads)).get("hwlab-cloud-api")?.spec?.template?.spec?.containers ?? [];
const volumes = mapByServiceId(listItems(workloads)).get("hwlab-cloud-api")?.spec?.template?.spec?.volumes ?? [];
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_PROVIDER")?.value, contract.codeAgentProvider, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_PROVIDER", "cloud API workload Code Agent provider");
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_MODEL")?.value, contract.model, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_MODEL", "cloud API workload Code Agent model");
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE")?.value, contract.profiles.defaultProfile, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE", "cloud API workload default provider profile");
expectEqual(ctx, env.get(contract.profiles.deepSeekModelEnv)?.value, "deepseek-chat", `deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.${contract.profiles.deepSeekModelEnv}`, "cloud API workload DeepSeek profile model");
expectEqual(ctx, env.get(contract.profiles.deepSeekBaseUrlEnv)?.value, contract.profiles.deepSeekBaseUrl, `deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.${contract.profiles.deepSeekBaseUrlEnv}`, "cloud API workload DeepSeek profile base URL");
expectEqual(ctx, env.get(contract.profiles.codexApiModelEnv)?.value, contract.model, `deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.${contract.profiles.codexApiModelEnv}`, "cloud API workload codex-api profile model");
expectEqual(ctx, env.get(contract.profiles.codexApiBaseUrlEnv)?.value, contract.egress.defaultBaseUrl, `deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.${contract.profiles.codexApiBaseUrlEnv}`, "cloud API workload codex-api profile base URL");
expectEqual(ctx, env.get(contract.forwarder.upstreamEnv)?.value, contract.forwarder.upstreamBaseUrl, `deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.${contract.forwarder.upstreamEnv}`, "cloud API workload codex-api upstream base URL");
expectEqual(ctx, env.get(contract.forwarder.portEnv)?.value, String(contract.forwarder.port), `deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.${contract.forwarder.portEnv}`, "cloud API workload codex-api forwarder port");
expectEqual(ctx, env.get("HWLAB_CODE_AGENT_TIMEOUT_MS")?.value, codeAgentBackendTimeoutMs, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_TIMEOUT_MS", "cloud API workload Code Agent hard timeout budget");
expectEqual(
ctx,
env.get("HWLAB_CODE_AGENT_OPENAI_BASE_URL")?.value,
contract.egress.defaultBaseUrl,
"deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.HWLAB_CODE_AGENT_OPENAI_BASE_URL",
"cloud API workload Code Agent DEV egress/proxy base URL"
"cloud API workload Code Agent pod-local Codex API forwarder base URL"
);
expectEqual(
ctx,
@@ -599,6 +614,7 @@ function validateCloudApiCodeAgentArtifacts(ctx, workloads) {
expectEqual(ctx, env.get("CODEX_HOME")?.value, "/codex-home", "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.CODEX_HOME", "cloud API workload CODEX_HOME contract");
expectNoProxyIncludes(ctx, env.get("NO_PROXY")?.value, contract.noProxyRequired, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.NO_PROXY");
expectNoProxyIncludes(ctx, env.get("no_proxy")?.value, contract.noProxyRequired, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.env.no_proxy");
validateCodexApiForwarderArtifacts(ctx, podContainers, contract);
validateCodexHomeMountArtifacts(ctx, container?.volumeMounts ?? [], volumes, contract);
expect(
ctx,
@@ -622,6 +638,26 @@ function expectNoProxyIncludes(ctx, value, required, path, label = "NO_PROXY con
}
}
function validateCodexApiForwarderArtifacts(ctx, containers, contract) {
const sidecar = (containers ?? []).find((entry) => entry.name === contract.forwarder.containerName);
expect(ctx, Boolean(sidecar), "codex_api_forwarder_missing", "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.containers.hwlab-codex-api-forwarder", "cloud API pod includes codex-api loopback forwarder sidecar");
if (!sidecar) return;
expect(ctx, JSON.stringify(sidecar.command) === JSON.stringify(contract.forwarder.command), "codex_api_forwarder_command_mismatch", "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.containers.hwlab-codex-api-forwarder.command", "codex-api forwarder command");
expect(
ctx,
(sidecar.ports ?? []).some((entry) => entry.name === contract.forwarder.portName && entry.containerPort === contract.forwarder.port),
"codex_api_forwarder_port_missing",
"deploy/k8s/base/workloads.yaml.hwlab-cloud-api.containers.hwlab-codex-api-forwarder.ports",
"codex-api forwarder exposes only a Pod-local container port"
);
const env = new Map((sidecar.env ?? []).map((entry) => [entry.name, entry.value]));
expectEqual(ctx, env.get(contract.forwarder.listenHostEnv), "127.0.0.1", `deploy/k8s/base/workloads.yaml.hwlab-cloud-api.containers.hwlab-codex-api-forwarder.env.${contract.forwarder.listenHostEnv}`, "codex-api forwarder loopback listen host env");
expectEqual(ctx, env.get(contract.forwarder.upstreamEnv), contract.forwarder.upstreamBaseUrl, `deploy/k8s/base/workloads.yaml.hwlab-cloud-api.containers.hwlab-codex-api-forwarder.env.${contract.forwarder.upstreamEnv}`, "codex-api forwarder upstream env");
expectEqual(ctx, env.get(contract.forwarder.portEnv), String(contract.forwarder.port), `deploy/k8s/base/workloads.yaml.hwlab-cloud-api.containers.hwlab-codex-api-forwarder.env.${contract.forwarder.portEnv}`, "codex-api forwarder port env");
expectNoProxyIncludes(ctx, env.get("NO_PROXY"), contract.noProxyRequired, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.containers.hwlab-codex-api-forwarder.env.NO_PROXY", "codex-api forwarder NO_PROXY contract");
expectNoProxyIncludes(ctx, env.get("no_proxy"), contract.noProxyRequired, "deploy/k8s/base/workloads.yaml.hwlab-cloud-api.containers.hwlab-codex-api-forwarder.env.no_proxy", "codex-api forwarder no_proxy contract");
}
function validateCodexHomeMountArtifacts(ctx, volumeMounts, volumes, contract) {
expect(
ctx,
+23 -17
View File
@@ -201,7 +201,7 @@ function recordObservation(ctx, observation) {
}
function expectedEnvValue(name, service, desiredCommitId) {
if (name === "HWLAB_COMMIT_ID" || name === "HWLAB_SKILLS_COMMIT_ID") return desiredCommitId;
if (name === "HWLAB_COMMIT_ID" || name === "HWLAB_SKILLS_COMMIT_ID") return service?.commitId ?? service?.imageTag ?? desiredCommitId;
if (name === "HWLAB_IMAGE") return service?.image ?? null;
if (name === "HWLAB_IMAGE_TAG") return service?.imageTag ?? null;
if (name === "HWLAB_IMAGE_DIGEST") return service?.digest ?? "not_published";
@@ -306,7 +306,8 @@ function inspectCodeAgentProviderDesiredState(ctx, deployService, workloadRecord
missingSecretRefs: inspection.missingSecretRefs,
missingEgressContract: inspection.missingEgressContract,
missingCodexHomeContract: inspection.missingCodexHomeContract,
missingNoProxyContract: inspection.missingNoProxyContract
missingNoProxyContract: inspection.missingNoProxyContract,
missingForwarderContract: inspection.missingForwarderContract
},
secretMaterialRead: false,
valuesRedacted: true
@@ -326,8 +327,8 @@ function inspectCodeAgentProviderDesiredState(ctx, deployService, workloadRecord
serviceId: "hwlab-cloud-api",
path: `${workloadsPath}.hwlab-cloud-api.env.HWLAB_CODE_AGENT_OPENAI_BASE_URL`,
field: "HWLAB_CODE_AGENT_OPENAI_BASE_URL",
kind: "egress-proxy",
value: inspection.egress.workloadMatchesDevProxy ? "dev-egress-proxy" : "missing_or_mismatched",
kind: "codex-api-forwarder",
value: inspection.egress.workloadMatchesDevProxy ? "pod-local-codex-api-forwarder" : "missing_or_mismatched",
expected: DEV_CODE_AGENT_PROVIDER_CONTRACT.egress.target
});
return inspection;
@@ -443,7 +444,8 @@ function indexWorkloads(workloads) {
env: {
...envListToObject(container?.env),
__volumeMounts: Array.isArray(container?.volumeMounts) ? container.volumeMounts : [],
__volumes: Array.isArray(item?.spec?.template?.spec?.volumes) ? item.spec.template.spec.volumes : []
__volumes: Array.isArray(item?.spec?.template?.spec?.volumes) ? item.spec.template.spec.volumes : [],
__podContainers: Array.isArray(item?.spec?.template?.spec?.containers) ? item.spec.template.spec.containers : []
},
path: `${workloadsPath}.${item?.kind ?? "Workload"}.${item?.metadata?.name ?? serviceId}.containers[${containerIndex}]`
};
@@ -796,10 +798,12 @@ export async function buildDesiredStatePlan(options = {}) {
const deployImage = parseImageRef(deployService?.image);
const catalogImage = parseImageRef(catalogService?.image);
const serviceImageTag = catalogService?.imageTag ?? deployImage.tag;
const serviceImageTag = catalogService?.imageTag ?? deployImage.tag ?? catalogImage.tag ?? desiredImageTag;
const serviceCommitId = catalogService?.commitId ?? serviceImageTag;
const expectedService = {
image: deployService?.image ?? catalogService?.image ?? null,
imageTag: desiredImageTag,
imageTag: serviceImageTag,
commitId: serviceCommitId,
digest: catalogService?.digest ?? "not_published"
};
@@ -816,8 +820,8 @@ export async function buildDesiredStatePlan(options = {}) {
});
if (!deployImage.valid) {
addMismatch(ctx, "invalid_image", `${deployPathBase}.image`, deployImage.reason, "tagged image ref", deployService.image, { serviceId });
} else if (deployImage.tag !== desiredImageTag) {
addMismatch(ctx, "image_tag_mismatch", `${deployPathBase}.image`, `${serviceId} deploy image tag must match deploy commit tag`, desiredImageTag, deployImage.tag, { serviceId });
} else if (deployImage.tag !== serviceImageTag) {
addMismatch(ctx, "image_tag_mismatch", `${deployPathBase}.image`, `${serviceId} deploy image tag must match service artifact tag`, serviceImageTag, deployImage.tag, { serviceId });
}
service.deploy = {
image: deployService.image,
@@ -843,7 +847,7 @@ export async function buildDesiredStatePlan(options = {}) {
field: "commitId",
kind: "commit",
value: catalogService.commitId,
expected: desiredCommitId
expected: serviceCommitId
});
recordObservation(ctx, {
source: "catalog",
@@ -861,16 +865,18 @@ export async function buildDesiredStatePlan(options = {}) {
field: "imageTag",
kind: "tag",
value: catalogService.imageTag,
expected: desiredImageTag
expected: serviceImageTag
});
if (!commitEquivalent(catalogService.commitId, desiredCommitId)) {
addMismatch(ctx, "commit_mismatch", `${catalogPathBase}.commitId`, `${serviceId} catalog service commitId must match deploy commitId`, desiredCommitId, catalogService.commitId, { serviceId });
if (!commitPattern.test(String(catalogService.commitId ?? ""))) {
addMismatch(ctx, "invalid_commit", `${catalogPathBase}.commitId`, `${serviceId} catalog service commitId must be a short or full lowercase Git SHA`, "7-40 lowercase hex", catalogService.commitId, { serviceId });
} else if (!commitEquivalent(catalogService.commitId, serviceImageTag)) {
addMismatch(ctx, "commit_mismatch", `${catalogPathBase}.commitId`, `${serviceId} catalog service commitId must match service artifact tag`, serviceImageTag, catalogService.commitId, { serviceId });
}
if (!catalogImage.valid) {
addMismatch(ctx, "invalid_image", `${catalogPathBase}.image`, catalogImage.reason, "tagged image ref", catalogService.image, { serviceId });
}
if (catalogService.imageTag !== desiredImageTag) {
addMismatch(ctx, "image_tag_mismatch", `${catalogPathBase}.imageTag`, `${serviceId} catalog imageTag must match deploy commit tag`, desiredImageTag, catalogService.imageTag, { serviceId });
if (catalogService.imageTag !== serviceImageTag) {
addMismatch(ctx, "image_tag_mismatch", `${catalogPathBase}.imageTag`, `${serviceId} catalog imageTag must match service artifact tag`, serviceImageTag, catalogService.imageTag, { serviceId });
}
if (catalogImage.valid && catalogImage.tag !== catalogService.imageTag) {
addMismatch(ctx, "image_tag_mismatch", `${catalogPathBase}.image`, `${serviceId} catalog image tag must match catalog imageTag`, catalogService.imageTag, catalogImage.tag, { serviceId });
@@ -901,8 +907,8 @@ export async function buildDesiredStatePlan(options = {}) {
});
if (!workloadImage.valid) {
addMismatch(ctx, "invalid_image", `${workload.path}.image`, workloadImage.reason, "tagged image ref", workload.image, { serviceId });
} else if (workloadImage.tag !== desiredImageTag) {
addMismatch(ctx, "image_tag_mismatch", `${workload.path}.image`, `${serviceId} workload image tag must match deploy commit tag`, desiredImageTag, workloadImage.tag, { serviceId });
} else if (workloadImage.tag !== serviceImageTag) {
addMismatch(ctx, "image_tag_mismatch", `${workload.path}.image`, `${serviceId} workload image tag must match service artifact tag`, serviceImageTag, workloadImage.tag, { serviceId });
}
if (deployService?.image && workload.image !== deployService.image) {
addMismatch(ctx, "image_mismatch", `${workload.path}.image`, `${serviceId} workload image must match deploy image`, deployService.image, workload.image, { serviceId });
+1
View File
@@ -41,6 +41,7 @@ export const DEFAULT_GITOPS_ONLY_PATHS = Object.freeze([
const serviceSpecificPaths = Object.freeze({
"hwlab-cloud-api": [
"cmd/hwlab-cloud-api/",
"cmd/hwlab-codex-api-responses-forwarder/",
"cmd/hwlab-deepseek-responses-bridge/",
"internal/cloud/",
"internal/db/",
+47 -4
View File
@@ -77,6 +77,16 @@ function assertUnique(name, values) {
assert.equal(new Set(values).size, values.length, `${name} must be unique`);
}
function imageTagFromReference(image) {
if (typeof image !== "string" || image.length === 0) return null;
const digestIndex = image.indexOf("@");
const withoutDigest = digestIndex >= 0 ? image.slice(0, digestIndex) : image;
const slashIndex = withoutDigest.lastIndexOf("/");
const colonIndex = withoutDigest.lastIndexOf(":");
if (colonIndex <= slashIndex) return null;
return withoutDigest.slice(colonIndex + 1) || null;
}
function assertCommonSchema(commonSchema) {
const schemaServiceIds = commonSchema.$defs.serviceId.enum;
assert.deepEqual(schemaServiceIds, SERVICE_IDS, "common service ids must match runtime constants");
@@ -165,6 +175,7 @@ const cloudApiContainer = cloudApiWorkload?.spec?.template?.spec?.containers?.fi
const cloudApiWorkloadEnv = getWorkloadEnv(k8sWorkloads, "hwlab-cloud-api");
cloudApiWorkloadEnv.__volumeMounts = cloudApiContainer?.volumeMounts ?? [];
cloudApiWorkloadEnv.__volumes = cloudApiWorkload?.spec?.template?.spec?.volumes ?? [];
cloudApiWorkloadEnv.__podContainers = cloudApiWorkload?.spec?.template?.spec?.containers ?? [];
const patchPanelWorkloadEnv = getWorkloadEnv(k8sWorkloads, "hwlab-patch-panel");
assert.equal(deployManifest.health.path, "/health/live", "deploy health source path");
assert.equal(deployManifest.publicEndpoints.frontend.url, "http://74.48.78.17:16666", "deploy frontend endpoint");
@@ -176,9 +187,10 @@ assert.ok(
"deploy edge proxy k3s mapping"
);
assert.equal(cloudApi.healthPath, "/health/live", "cloud-api health path");
assert.equal(cloudApi.env.HWLAB_COMMIT_ID, deployManifest.commitId, "cloud-api health commit evidence");
const cloudApiImageTag = imageTagFromReference(cloudApi.image) ?? deployManifest.commitId.slice(0, 7);
assert.equal(cloudApi.env.HWLAB_COMMIT_ID, cloudApiImageTag, "cloud-api health commit evidence");
assert.equal(cloudApi.env.HWLAB_IMAGE, cloudApi.image, "cloud-api health image evidence");
assert.equal(cloudApi.env.HWLAB_IMAGE_TAG, deployManifest.commitId.slice(0, 7), "cloud-api health image tag evidence");
assert.equal(cloudApi.env.HWLAB_IMAGE_TAG, cloudApiImageTag, "cloud-api health image tag evidence");
assert.equal(cloudApi.env.HWLAB_CLOUD_DB_URL, "secretRef:hwlab-cloud-api-dev-db/database-url", "cloud-api DB URL must be a Secret reference placeholder");
assert.equal(
cloudApi.env.HWLAB_CLOUD_DB_SSL_MODE,
@@ -206,10 +218,17 @@ assert.equal(cloudApiWorkloadEnv.HWLAB_CLOUD_DB_PORT, undefined, "cloud-api work
assertCloudApiDbOptionalAlias(k8sServices);
assert.equal(cloudApi.env.HWLAB_CODE_AGENT_PROVIDER, DEV_CODE_AGENT_PROVIDER_CONTRACT.codeAgentProvider, "cloud-api Code Agent provider");
assert.equal(cloudApi.env.HWLAB_CODE_AGENT_MODEL, DEV_CODE_AGENT_PROVIDER_CONTRACT.model, "cloud-api Code Agent model");
assert.equal(cloudApi.env.HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE, DEV_CODE_AGENT_PROVIDER_CONTRACT.profiles.defaultProfile, "cloud-api default provider profile");
assert.equal(cloudApi.env[DEV_CODE_AGENT_PROVIDER_CONTRACT.profiles.deepSeekModelEnv], "deepseek-chat", "cloud-api DeepSeek profile model");
assert.equal(cloudApi.env[DEV_CODE_AGENT_PROVIDER_CONTRACT.profiles.deepSeekBaseUrlEnv], DEV_CODE_AGENT_PROVIDER_CONTRACT.profiles.deepSeekBaseUrl, "cloud-api DeepSeek profile base URL");
assert.equal(cloudApi.env[DEV_CODE_AGENT_PROVIDER_CONTRACT.profiles.codexApiModelEnv], DEV_CODE_AGENT_PROVIDER_CONTRACT.model, "cloud-api codex-api profile model");
assert.equal(cloudApi.env[DEV_CODE_AGENT_PROVIDER_CONTRACT.profiles.codexApiBaseUrlEnv], DEV_CODE_AGENT_PROVIDER_CONTRACT.egress.defaultBaseUrl, "cloud-api codex-api profile base URL");
assert.equal(cloudApi.env[DEV_CODE_AGENT_PROVIDER_CONTRACT.forwarder.upstreamEnv], DEV_CODE_AGENT_PROVIDER_CONTRACT.forwarder.upstreamBaseUrl, "cloud-api codex-api upstream base URL");
assert.equal(cloudApi.env[DEV_CODE_AGENT_PROVIDER_CONTRACT.forwarder.portEnv], String(DEV_CODE_AGENT_PROVIDER_CONTRACT.forwarder.port), "cloud-api codex-api forwarder port");
assert.equal(
cloudApi.env.HWLAB_CODE_AGENT_OPENAI_BASE_URL,
DEV_CODE_AGENT_PROVIDER_CONTRACT.egress.defaultBaseUrl,
"cloud-api Code Agent OpenAI base URL must use DEV egress/proxy"
"cloud-api Code Agent OpenAI base URL must use pod-local Codex API forwarder"
);
assert.equal(
cloudApi.env[HWLAB_M3_IO_API_BASE_URL_ENV],
@@ -278,10 +297,17 @@ function assertCodeAgentProviderWorkloadContract(env) {
const apiKey = env[secretRef.env]?.valueFrom?.secretKeyRef;
assert.equal(env.HWLAB_CODE_AGENT_PROVIDER?.value, contract.codeAgentProvider, "cloud-api workload Code Agent provider");
assert.equal(env.HWLAB_CODE_AGENT_MODEL?.value, contract.model, "cloud-api workload Code Agent model");
assert.equal(env.HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE?.value, contract.profiles.defaultProfile, "cloud-api workload default provider profile");
assert.equal(env[contract.profiles.deepSeekModelEnv]?.value, "deepseek-chat", "cloud-api workload DeepSeek profile model");
assert.equal(env[contract.profiles.deepSeekBaseUrlEnv]?.value, contract.profiles.deepSeekBaseUrl, "cloud-api workload DeepSeek profile base URL");
assert.equal(env[contract.profiles.codexApiModelEnv]?.value, contract.model, "cloud-api workload codex-api profile model");
assert.equal(env[contract.profiles.codexApiBaseUrlEnv]?.value, contract.egress.defaultBaseUrl, "cloud-api workload codex-api profile base URL must use pod-local forwarder");
assert.equal(env[contract.forwarder.upstreamEnv]?.value, contract.forwarder.upstreamBaseUrl, "cloud-api workload codex-api upstream must direct-connect to hyueapi");
assert.equal(env[contract.forwarder.portEnv]?.value, String(contract.forwarder.port), "cloud-api workload codex-api forwarder port");
assert.equal(
env.HWLAB_CODE_AGENT_OPENAI_BASE_URL?.value,
contract.egress.defaultBaseUrl,
"cloud-api workload Code Agent OpenAI base URL must use DEV egress/proxy"
"cloud-api workload Code Agent OpenAI base URL must use pod-local Codex API forwarder"
);
assert.equal(
env[HWLAB_M3_IO_API_BASE_URL_ENV]?.value,
@@ -298,6 +324,7 @@ function assertCodeAgentProviderWorkloadContract(env) {
assertNoProxyIncludes(env.NO_PROXY?.value, contract.noProxyRequired, "cloud-api workload NO_PROXY contract");
assertNoProxyIncludes(env.no_proxy?.value, contract.noProxyRequired, "cloud-api workload no_proxy contract");
assertCodexHomeMountContract(env, contract);
assertCodexApiForwarderContract(env, contract);
assert.notEqual(
env.HWLAB_CODE_AGENT_OPENAI_BASE_URL?.value,
contract.egress.forbiddenDirectBaseUrl,
@@ -317,6 +344,22 @@ function assertNoProxyIncludes(value, required, label) {
}
}
function assertCodexApiForwarderContract(env, contract) {
const sidecar = (env.__podContainers ?? []).find((entry) => entry.name === contract.forwarder.containerName);
assert.ok(sidecar, "cloud-api pod includes codex-api loopback forwarder sidecar");
assert.deepEqual(sidecar.command, contract.forwarder.command, "codex-api forwarder command");
assert.ok(
(sidecar.ports ?? []).some((entry) => entry.name === contract.forwarder.portName && entry.containerPort === contract.forwarder.port),
"codex-api forwarder exposes only Pod-local container port"
);
const sidecarEnv = Object.fromEntries((sidecar.env ?? []).map((entry) => [entry.name, entry.value]));
assert.equal(sidecarEnv[contract.forwarder.listenHostEnv], "127.0.0.1", "codex-api forwarder loopback listen host env");
assert.equal(sidecarEnv[contract.forwarder.upstreamEnv], contract.forwarder.upstreamBaseUrl, "codex-api forwarder upstream env");
assert.equal(sidecarEnv[contract.forwarder.portEnv], String(contract.forwarder.port), "codex-api forwarder port env");
assertNoProxyIncludes(sidecarEnv.NO_PROXY, contract.noProxyRequired, "codex-api forwarder NO_PROXY contract");
assertNoProxyIncludes(sidecarEnv.no_proxy, contract.noProxyRequired, "codex-api forwarder no_proxy contract");
}
function assertCodexHomeMountContract(env, contract) {
const volumeMounts = env.__volumeMounts ?? [];
const volumes = env.__volumes ?? [];