import { afterEach, expect, test } from "bun:test"; import { spawnSync } from "node:child_process"; import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; const roots: string[] = []; const script = resolve(import.meta.dir, "runtime-gitops-verify.mjs"); afterEach(() => { while (roots.length > 0) rmSync(roots.pop()!, { recursive: true, force: true }); }); test("accepts YAML-owned tool Secret and Kafka env on the cloud-api workload", () => { const root = mkdtempSync(join(tmpdir(), "runtime-gitops-verify-")); roots.push(root); mkdirSync(join(root, "runtime")); writeFileSync(join(root, "runtime", "cloud-api.yaml"), deploymentYaml({ ...toolSecretEnv(), ...kafkaEnv() })); writeFileSync(join(root, "overlay.json"), JSON.stringify({ runtimePath: "runtime", codeAgentRuntime: { enabled: true, toolSecretNames: toolSecretNames(), kafkaEventBridge: { enabled: true, ...kafkaValues() }, }, })); const result = spawnSync(process.execPath, [script], { cwd: root, env: { ...process.env, UNIDESK_RUNTIME_GITOPS_OVERLAY_FILE: join(root, "overlay.json") }, encoding: "utf8", }); expect(result.status).toBe(0); expect(result.stderr).toContain('"code-agent-runtime-tool-secret-env"'); expect(result.stderr).toContain('"code-agent-runtime-kafka-event-bridge-enabled"'); }); test("rejects missing YAML-owned Kafka env before GitOps publish", () => { const root = mkdtempSync(join(tmpdir(), "runtime-gitops-verify-")); roots.push(root); mkdirSync(join(root, "runtime")); writeFileSync(join(root, "runtime", "cloud-api.yaml"), deploymentYaml({ ...kafkaEnv(), HWLAB_KAFKA_CLIENT_ID: undefined })); writeFileSync(join(root, "overlay.json"), JSON.stringify({ runtimePath: "runtime", codeAgentRuntime: { enabled: true, kafkaEventBridge: { enabled: true, ...kafkaValues() } }, })); const result = spawnSync(process.execPath, [script], { cwd: root, env: { ...process.env, UNIDESK_RUNTIME_GITOPS_OVERLAY_FILE: join(root, "overlay.json") }, encoding: "utf8", }); expect(result.status).toBe(48); expect(result.stderr).toContain('"reason":"code-agent-runtime-kafka-env-invalid"'); expect(result.stderr).toContain('"name":"HWLAB_KAFKA_CLIENT_ID"'); }); function kafkaValues() { return { bootstrapServers: "kafka.platform-infra.svc.cluster.local:9092", stdioTopic: "agentrun.stdio.v1", agentRunEventTopic: "agentrun.event.v1", hwlabEventTopic: "hwlab.event.v1", clientId: "hwlab-production", }; } function toolSecretNames() { return { githubPr: "agentrun-release-tool-github-pr", unideskSsh: "agentrun-release-tool-unidesk-ssh", }; } function toolSecretEnv(): Record { const names = toolSecretNames(); return { HWLAB_CODE_AGENT_AGENTRUN_GITHUB_TOOL_SECRET_NAME: names.githubPr, HWLAB_CODE_AGENT_AGENTRUN_UNIDESK_SSH_TOOL_SECRET_NAME: names.unideskSsh, }; } function kafkaEnv(): Record { const kafka = kafkaValues(); return { HWLAB_KAFKA_BOOTSTRAP_SERVERS: kafka.bootstrapServers, HWLAB_KAFKA_STDIO_TOPIC: kafka.stdioTopic, HWLAB_KAFKA_AGENTRUN_EVENT_TOPIC: kafka.agentRunEventTopic, HWLAB_KAFKA_EVENT_TOPIC: kafka.hwlabEventTopic, HWLAB_KAFKA_CLIENT_ID: kafka.clientId, }; } function deploymentYaml(env: Record) { const entries = Object.entries(env) .filter((entry): entry is [string, string] => entry[1] !== undefined) .map(([name, value]) => ` - name: ${name}\n value: ${value}`) .join("\n"); return `apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: hwlab-cloud-api\n labels:\n app.kubernetes.io/name: hwlab-cloud-api\nspec:\n template:\n spec:\n containers:\n - name: hwlab-cloud-api\n env:\n${entries}\n`; }