fix: 校验 Code Agent Codex home 挂载契约

This commit is contained in:
Code Queue Review
2026-05-24 07:29:51 +00:00
parent 7a3727be95
commit a47c38ef22
3 changed files with 60 additions and 5 deletions
+16 -2
View File
@@ -98,6 +98,12 @@ export function inspectCodeAgentProviderManifestRefs({ deployEnv = {}, workloadE
if (deployEnv?.CODEX_HOME !== contract.codexHome.path || workloadInspection.codexHome.present !== true) {
missingCodexHomeContract.push(`CODEX_HOME must be ${contract.codexHome.path}`);
}
if (workloadInspection.codexHome.writableHomeMountPresent !== true) {
missingCodexHomeContract.push(`${contract.codexHome.path} must be a writable volumeMount`);
}
if (workloadInspection.codexHome.emptyDirPresent !== true) {
missingCodexHomeContract.push(`${contract.codexHome.path} must be backed by emptyDir`);
}
if (workloadInspection.codexHome.configMapPresent !== true) {
missingCodexHomeContract.push(`${contract.codexHome.configMapName}/${contract.codexHome.configKey}`);
}
@@ -424,6 +430,13 @@ function inspectCodexHomeWorkloadMounts(workloadEnv = {}) {
const volumeMounts = Array.isArray(workloadEnv.__volumeMounts) ? workloadEnv.__volumeMounts : [];
const volumes = Array.isArray(workloadEnv.__volumes) ? workloadEnv.__volumes : [];
const homeMount = volumeMounts.find((entry) => entry?.name === "hwlab-code-agent-codex-home" && entry?.mountPath === contract.codexHome.path);
const writableHomeMount = homeMount && homeMount.readOnly !== true;
const homeVolume = volumes.find((entry) =>
entry?.name === "hwlab-code-agent-codex-home" &&
entry?.emptyDir &&
typeof entry.emptyDir === "object" &&
!Array.isArray(entry.emptyDir)
);
const configMount = volumeMounts.find((entry) =>
entry?.name === "hwlab-code-agent-codex-config" &&
entry?.mountPath === `${contract.codexHome.path}/${contract.codexHome.configKey}` &&
@@ -448,8 +461,9 @@ function inspectCodexHomeWorkloadMounts(workloadEnv = {}) {
);
return {
path: contract.codexHome.path,
present: Boolean(homeMount),
writableHomeMountPresent: Boolean(homeMount),
present: Boolean(writableHomeMount && homeVolume),
writableHomeMountPresent: Boolean(writableHomeMount),
emptyDirPresent: Boolean(homeVolume),
configMapPresent: Boolean(configMount && configVolume),
authSecretPresent: Boolean(authMount && authVolume),
configMapName: contract.codexHome.configMapName,
+41 -2
View File
@@ -39,6 +39,8 @@ async function makeFixture({
workloadEnvMirrors = true,
workloadSkillsCommitId = null,
workloadCodeAgentProviderEnv = true,
workloadCodexHomeVolumeMounts = true,
workloadCodexHomeVolumes = true,
workloadDbEnv = true,
workloadDbSslMode = "disable"
} = {}) {
@@ -184,7 +186,7 @@ async function makeFixture({
...workloadProviderEnv
]
: [],
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv && workloadCodexHomeVolumeMounts
? {
volumeMounts: [
{ name: "hwlab-code-agent-codex-home", mountPath: "/codex-home" },
@@ -195,7 +197,7 @@ async function makeFixture({
: {})
}
],
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv
...(serviceId === "hwlab-cloud-api" && workloadCodeAgentProviderEnv && workloadCodexHomeVolumes
? {
volumes: [
{ name: "hwlab-code-agent-codex-home", emptyDir: {} },
@@ -248,11 +250,48 @@ test("passes when cloud-api preserves provider env and DEV egress contract", asy
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.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 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"));
workloads.items[0].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",
+3 -1
View File
@@ -304,7 +304,9 @@ function inspectCodeAgentProviderDesiredState(ctx, deployService, workloadRecord
deployMismatches: inspection.deployMismatches.map((entry) => entry.name),
workloadMismatches: inspection.workloadMismatches.map((entry) => entry.name),
missingSecretRefs: inspection.missingSecretRefs,
missingEgressContract: inspection.missingEgressContract
missingEgressContract: inspection.missingEgressContract,
missingCodexHomeContract: inspection.missingCodexHomeContract,
missingNoProxyContract: inspection.missingNoProxyContract
},
secretMaterialRead: false,
valuesRedacted: true