fix: unblock v02 gitops ts reconciler

This commit is contained in:
Codex
2026-05-29 02:31:09 +08:00
parent 0402e6f937
commit a385c2ad0b
3 changed files with 48 additions and 0 deletions
+14
View File
@@ -1320,6 +1320,15 @@ function apiPath(item) {
return "/apis/" + encode(parts[0]) + "/" + encode(parts[1]) + "/namespaces/" + encode(ns) + "/" + plural + "/" + encode(name);
}
function reconcilePolicy(item) {
const ns = item.metadata?.namespace || namespace;
const crossNamespaceRbac = (item.kind === "Role" || item.kind === "RoleBinding") && ns !== namespace;
if (crossNamespaceRbac && process.env.HWLAB_RECONCILE_CROSS_NAMESPACE_RBAC !== "1") {
return { action: "skip", reason: "cross-namespace-rbac-bootstrap-managed", namespace: ns };
}
return { action: "apply", namespace: ns };
}
function request(method, path, body) {
const payload = body ? JSON.stringify(body) : "";
const headers = { Authorization: "Bearer " + token };
@@ -1344,6 +1353,11 @@ function request(method, path, body) {
const results = [];
for (const file of manifestFiles) {
for (const item of itemsFrom(file)) {
const policy = reconcilePolicy(item);
if (policy.action === "skip") {
results.push({ file, kind: item.kind, name: item.metadata?.name || null, namespace: policy.namespace, status: "skipped", reason: policy.reason });
continue;
}
const path = apiPath(item);
if (!path) {
results.push({ file, kind: item.kind, name: item.metadata?.name || null, status: "skipped-cluster-scoped" });
+33
View File
@@ -0,0 +1,33 @@
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";
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");
assert.match(pipeline, /bun test cmd\/hwlab-codex-api-responses-forwarder\/main\.test\.ts/u);
assert.doesNotMatch(pipeline, /cmd\/hwlab-codex-api-responses-forwarder\/main\.mjs/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 });
}
});
+1
View File
@@ -110,6 +110,7 @@ export const checkProfiles = Object.freeze({
{ id: "check-091-deploy-refresh-artifact-catalog-test", group: "deploy", command: ["node","--check","scripts/refresh-artifact-catalog.test.mjs"] },
{ id: "check-092-artifact-artifact-publish", group: "artifact", command: ["node","--check","scripts/artifact-publish.mjs"] },
{ id: "check-093-artifact-g14-artifact-publish", group: "artifact", command: ["node","--check","scripts/g14-artifact-publish.mjs"] },
{ id: "check-093a-artifact-g14-gitops-render-test", group: "artifact", command: ["node","scripts/run-bun.mjs","test","scripts/g14-gitops-render.test.ts"] },
{ id: "check-094-artifact-dev-runtime-base-image", group: "artifact", command: ["node","--check","scripts/dev-runtime-base-image.mjs"] },
{ id: "check-095-artifact-dev-artifact-services", group: "artifact", command: ["node","--check","scripts/src/dev-artifact-services.mjs"] },
{ id: "check-096-artifact-registry-capabilities", group: "artifact", command: ["node","--check","scripts/src/registry-capabilities.mjs"] },