91 lines
3.8 KiB
TypeScript
91 lines
3.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { spawnSync } from "node:child_process";
|
|
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
|
|
function taskByName(pipeline, name) {
|
|
const task = pipeline.spec.tasks.find((item) => item.name === name);
|
|
assert.ok(task, `missing task ${name}`);
|
|
return task;
|
|
}
|
|
|
|
test("v02 render follows TypeScript runtime checks and does not self-patch bootstrap RBAC", async () => {
|
|
const outDir = await mkdtemp(path.join(os.tmpdir(), "hwlab-v02-render-test-"));
|
|
try {
|
|
const render = spawnSync(process.execPath, [
|
|
"scripts/g14-gitops-render.mjs",
|
|
"--lane", "v02",
|
|
"--catalog-path", "deploy/artifact-catalog.v02.json",
|
|
"--image-tag-mode", "full",
|
|
"--source-branch", "v0.2",
|
|
"--gitops-branch", "v0.2-gitops",
|
|
"--out", outDir,
|
|
"--source-revision", "HEAD"
|
|
], { cwd: process.cwd(), encoding: "utf8" });
|
|
assert.equal(render.status, 0, render.stderr || render.stdout);
|
|
|
|
const pipeline = await readFile(path.join(outDir, "tekton-v02", "pipeline.yaml"), "utf8");
|
|
const pipelineJson = JSON.parse(pipeline);
|
|
assert.match(pipeline, /127\.0\.0\.1:5000\/hwlab\/hwlab-ci-node-tools:node22-alpine-bun-v1/u);
|
|
assert.match(pipeline, /node scripts\/run-bun\.mjs test cmd\/hwlab-codex-api-responses-forwarder\/main\.test\.ts/u);
|
|
assert.doesNotMatch(pipeline, /cmd\/hwlab-codex-api-responses-forwarder\/main\.mjs/u);
|
|
assert.match(pipeline, /process\.exitCode = 1/u);
|
|
assert.match(pipeline, /item\.spec\?\.template\?\.metadata\?\.labels\?\.\[\\"hwlab\.pikastech\.local\/source-commit\\"\]/u);
|
|
|
|
const removedServiceIds = [
|
|
"hwlab-router",
|
|
"hwlab-tunnel-client",
|
|
"hwlab-gateway-simu",
|
|
"hwlab-box-simu",
|
|
"hwlab-patch-panel"
|
|
];
|
|
for (const serviceId of removedServiceIds) {
|
|
assert.doesNotMatch(pipeline, new RegExp(`build-${serviceId}`, "u"));
|
|
}
|
|
|
|
const retainedServiceIds = [
|
|
"hwlab-cloud-api",
|
|
"hwlab-cloud-web",
|
|
"hwlab-agent-mgr",
|
|
"hwlab-agent-worker",
|
|
"hwlab-device-pod",
|
|
"hwlab-gateway",
|
|
"hwlab-edge-proxy",
|
|
"hwlab-cli",
|
|
"hwlab-agent-skills"
|
|
];
|
|
for (let index = 0; index < retainedServiceIds.length; index += 1) {
|
|
const serviceId = retainedServiceIds[index];
|
|
const task = taskByName(pipelineJson, `build-${serviceId}`);
|
|
const expectedRunAfter = index === 0 ? ["plan-artifacts"] : [`build-${retainedServiceIds[index - 1]}`];
|
|
assert.deepEqual(task.runAfter, expectedRunAfter);
|
|
}
|
|
|
|
const workloads = await readFile(path.join(outDir, "runtime-v02", "workloads.yaml"), "utf8");
|
|
const services = await readFile(path.join(outDir, "runtime-v02", "services.yaml"), "utf8");
|
|
for (const serviceId of removedServiceIds) {
|
|
assert.doesNotMatch(workloads, new RegExp(serviceId, "u"));
|
|
assert.doesNotMatch(services, new RegExp(serviceId, "u"));
|
|
}
|
|
|
|
assert.doesNotMatch(pipeline, /hwlab-gateway-simu-status/u);
|
|
assert.match(pipeline, /hwlab-cloud-api-status/u);
|
|
|
|
const application = await readFile(path.join(outDir, "argocd", "application-v02.yaml"), "utf8");
|
|
assert.match(application, /"prune": true/u);
|
|
|
|
for (const generatedFile of ["deepseek-proxy.yaml", "postgres.yaml", "g14-frpc.yaml"]) {
|
|
const content = await readFile(path.join(outDir, "runtime-v02", generatedFile), "utf8");
|
|
assert.match(content, /"hwlab\.pikastech\.local\/source-commit"/u);
|
|
}
|
|
|
|
const reconciler = await readFile(path.join(outDir, "tekton-v02", "control-plane-reconciler.yaml"), "utf8");
|
|
assert.match(reconciler, /cross-namespace-rbac-bootstrap-managed/u);
|
|
assert.match(reconciler, /HWLAB_RECONCILE_CROSS_NAMESPACE_RBAC/u);
|
|
} finally {
|
|
await rm(outDir, { recursive: true, force: true });
|
|
}
|
|
});
|