fix: pin code queue dev artifact to skills mount runtime
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { collectSkillAvailability, collectSkillSyncPreflight } from "../src/components/microservices/code-queue/src/skill-availability";
|
||||
import { codexPrPreflightQueryForTest } from "./src/code-queue";
|
||||
import { summarizeMicroserviceObservation } from "./src/microservices";
|
||||
@@ -20,6 +21,19 @@ function countOccurrences(haystack: string, needle: string): number {
|
||||
return haystack.split(needle).length - 1;
|
||||
}
|
||||
|
||||
function gitShowText(commit: string, path: string): string {
|
||||
const result = spawnSync("git", ["show", `${commit}:${path}`], {
|
||||
cwd: process.cwd(),
|
||||
encoding: "utf8",
|
||||
maxBuffer: 2 * 1024 * 1024,
|
||||
});
|
||||
assertCondition(result.status === 0, `git show should read ${path} at ${commit}`, {
|
||||
status: result.status,
|
||||
stderr: result.stderr.slice(-1000),
|
||||
});
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
function createSkillSet(root: string, skills: string[]): void {
|
||||
for (const skill of skills) {
|
||||
const dir = join(root, skill);
|
||||
@@ -30,6 +44,13 @@ function createSkillSet(root: string, skills: string[]): void {
|
||||
|
||||
const productionManifest = readFileSync("src/components/microservices/k3sctl-adapter/k3s/code-queue.k8s.yaml", "utf8");
|
||||
const devManifest = readFileSync("src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-code-queue.k8s.yaml", "utf8");
|
||||
const deployJson = JSON.parse(readFileSync("deploy.json", "utf8")) as {
|
||||
environments?: {
|
||||
dev?: {
|
||||
services?: Array<Record<string, unknown>>;
|
||||
};
|
||||
};
|
||||
};
|
||||
const runtimePreflight = readFileSync("src/components/microservices/code-queue/src/runtime-preflight.ts", "utf8");
|
||||
const indexSource = readFileSync("src/components/microservices/code-queue/src/index.ts", "utf8");
|
||||
const skillModule = readFileSync("src/components/microservices/code-queue/src/skill-availability.ts", "utf8");
|
||||
@@ -61,6 +82,31 @@ assertCondition(countOccurrences(productionManifest, "name: skills-dir") >= 6, "
|
||||
});
|
||||
assertCondition(devManifest.includes("path: /home/ubuntu/.agents/skills"), "dev manifest should keep the same hostPath source of truth");
|
||||
|
||||
const devCodeQueueDeploy = (deployJson.environments?.dev?.services ?? []).find((service) => service.id === "code-queue");
|
||||
assertCondition(devCodeQueueDeploy !== undefined, "deploy.json dev environment must include code-queue");
|
||||
const devCodeQueueCommit = String(devCodeQueueDeploy?.commitId ?? "");
|
||||
assertCondition(/^[0-9a-f]{40}$/u.test(devCodeQueueCommit), "deploy.json dev code-queue commit must be a full SHA", devCodeQueueDeploy);
|
||||
assertCondition(devCodeQueueCommit !== "0cf73d817f14032ad6038fd47ec402c87bf059bb", "deploy.json dev code-queue must not pin the pre-skills-mount source commit", devCodeQueueDeploy);
|
||||
assertCondition(asRecord(devCodeQueueDeploy?.artifact, "dev code-queue artifact").repository === "unidesk/code-queue", "deploy.json dev code-queue must own artifact repository", devCodeQueueDeploy);
|
||||
const devCodeQueueConsumer = asRecord(devCodeQueueDeploy?.consumer, "dev code-queue consumer");
|
||||
assertCondition(devCodeQueueConsumer.kind === "d601-k3s-managed", "deploy.json dev code-queue must use the D601 k3s artifact consumer", devCodeQueueConsumer);
|
||||
const devCodeQueueTarget = asRecord(devCodeQueueConsumer.target, "dev code-queue consumer target");
|
||||
assertCondition(devCodeQueueTarget.manifestRepoPath === "src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-code-queue.k8s.yaml", "deploy.json dev code-queue must point at the dev k3s manifest", devCodeQueueTarget);
|
||||
|
||||
const pinnedDevManifest = gitShowText(devCodeQueueCommit, "src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-code-queue.k8s.yaml");
|
||||
const pinnedRuntimePreflight = gitShowText(devCodeQueueCommit, "src/components/microservices/code-queue/src/runtime-preflight.ts");
|
||||
const pinnedIndexSource = gitShowText(devCodeQueueCommit, "src/components/microservices/code-queue/src/index.ts");
|
||||
assertCondition(countOccurrences(pinnedDevManifest, "path: /home/ubuntu/.agents/skills") === 3, "deploy.json dev code-queue commit must include source skills hostPath for scheduler/read/write", {
|
||||
commit: devCodeQueueCommit,
|
||||
});
|
||||
assertCondition(countOccurrences(pinnedDevManifest, "mountPath: /root/.agents/skills") === 3, "deploy.json dev code-queue commit must mount skills target for scheduler/read/write", {
|
||||
commit: devCodeQueueCommit,
|
||||
});
|
||||
assertCondition(!pinnedDevManifest.includes(forbiddenPathLiteral), "deploy.json dev code-queue commit must not include the misspelled skills path");
|
||||
assertCondition(pinnedRuntimePreflight.includes("skills.contractOk && ports.codex.ok"), "deploy.json dev code-queue commit runtime-preflight must require target projection contract");
|
||||
assertCondition(pinnedIndexSource.includes("skills.contractOk === true"), "deploy.json dev code-queue commit dev-ready must require target projection contract");
|
||||
assertCondition(pinnedIndexSource.includes("return config.skillsPath"), "deploy.json dev code-queue commit must keep runner UNIDESK_SKILLS_PATH on the configured target");
|
||||
|
||||
const available = collectSkillAvailability({
|
||||
source: "/home/ubuntu/.agents/skills",
|
||||
target: "/home/ubuntu/.agents/skills",
|
||||
@@ -400,6 +446,7 @@ process.stdout.write(`${JSON.stringify({
|
||||
ok: true,
|
||||
checks: [
|
||||
"production Code Queue mounts /home/ubuntu/.agents/skills read-only at /root/.agents/skills",
|
||||
"deploy.json dev Code Queue pins a commit whose manifest and runtime require the target skills projection",
|
||||
"skill availability report exposes source, target, requiredSkills, missingSkills, version fingerprint/mtime, degraded/blocker and valuesPrinted=false",
|
||||
"skills sync dry-run reports source, target, counts, version fingerprint/mtime, missing skills, permission failures, instructions and no-copy actions",
|
||||
"scheduler blocks runner startup with structured infra-blocked output when required skills are unavailable",
|
||||
|
||||
@@ -59,7 +59,7 @@ const plannedDeployJsonFields = [
|
||||
"runtime.requiredSecretKeys",
|
||||
];
|
||||
|
||||
const phaseTwoExecutorContractServices = new Set(["dev/decision-center", "dev/mdtodo"]);
|
||||
const phaseTwoExecutorContractServices = new Set(["dev/decision-center", "dev/mdtodo", "dev/code-queue"]);
|
||||
|
||||
function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
|
||||
if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
|
||||
|
||||
Reference in New Issue
Block a user