From c0bf7af7b66bc92bdd433e048b0bab3fcda7f71e Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 15 Jul 2026 17:37:19 +0200 Subject: [PATCH] =?UTF-8?q?Revert=20"feat:=20=E6=8E=A5=E5=85=A5=E5=85=B1?= =?UTF-8?q?=E4=BA=AB=E8=BE=B9=E7=BC=98=E5=8D=95=E9=93=BE=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E4=BA=A4=E4=BB=98"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1b423f2b9b178fc89dc6eef17b717c3294ea0c4b. --- .tekton/platform-infra-gitea-nc01-pac.yaml | 23 -- config/platform-infra/public-edge.yaml | 21 -- config/secrets-distribution.yaml | 20 -- .../pr-merge-driven-automatic-delivery.md | 2 +- ...ply-platform-infra-public-edge-archive.mjs | 64 ----- .../deliver-platform-infra-public-edge.mjs | 271 ------------------ ...deliver-platform-infra-public-edge.test.ts | 180 ------------ 7 files changed, 1 insertion(+), 580 deletions(-) delete mode 100644 scripts/native/cicd/apply-platform-infra-public-edge-archive.mjs delete mode 100644 scripts/native/cicd/deliver-platform-infra-public-edge.mjs delete mode 100644 scripts/native/cicd/deliver-platform-infra-public-edge.test.ts diff --git a/.tekton/platform-infra-gitea-nc01-pac.yaml b/.tekton/platform-infra-gitea-nc01-pac.yaml index 54c53ef1..aac6f5e0 100644 --- a/.tekton/platform-infra-gitea-nc01-pac.yaml +++ b/.tekton/platform-infra-gitea-nc01-pac.yaml @@ -54,26 +54,3 @@ spec: volumeMounts: - name: workspace mountPath: /workspace - - name: apply-public-edge - image: 127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1 - imagePullPolicy: IfNotPresent - workingDir: /workspace/source - env: - - name: SOURCE_COMMIT - value: "{{revision}}" - - name: UNIDESK_SSH_CLIENT_TOKEN - valueFrom: - secretKeyRef: - name: public-edge-trans - key: UNIDESK_SSH_CLIENT_TOKEN - script: | - #!/bin/sh - set -eu - test "$(git rev-parse HEAD)" = "$SOURCE_COMMIT" - exec bun scripts/native/cicd/deliver-platform-infra-public-edge.mjs \ - --source-root /workspace/source \ - --source-commit "$SOURCE_COMMIT" \ - --confirm - volumeMounts: - - name: workspace - mountPath: /workspace diff --git a/config/platform-infra/public-edge.yaml b/config/platform-infra/public-edge.yaml index 05436da7..098ce9e8 100644 --- a/config/platform-infra/public-edge.yaml +++ b/config/platform-infra/public-edge.yaml @@ -6,31 +6,10 @@ metadata: owner: platform-infra relatedIssues: - 2181 - - 2205 defaults: targetId: NC01 -delivery: - enabled: true - pipelineId: platform-infra-gitea-nc01 - sourceCommitEnvironment: SOURCE_COMMIT - transport: - hostCwd: /root - secretRef: - configRef: config/secrets-distribution.yaml - targetId: public-edge-delivery-nc01 - secretName: public-edge-trans - targetKey: UNIDESK_SSH_CLIENT_TOKEN - hostHelper: - archiveRoot: /root/unidesk/.state/public-edge-delivery - entrypoint: scripts/native/cicd/apply-platform-infra-public-edge-archive.mjs - sourcePaths: - - config - - scripts - - package.json - - bun.lock - targets: NC01: route: NC01 diff --git a/config/secrets-distribution.yaml b/config/secrets-distribution.yaml index b412f402..37a9a8b6 100644 --- a/config/secrets-distribution.yaml +++ b/config/secrets-distribution.yaml @@ -10,7 +10,6 @@ metadata: - 313 - 2256 - 1964 - - 2205 sources: root: /root/.unidesk/.state/secrets @@ -143,12 +142,6 @@ sources: - DATABASE_URL createIfMissing: enabled: false - - sourceRef: unidesk-host-k8s.env - type: env - requiredKeys: - - UNIDESK_SSH_CLIENT_TOKEN - createIfMissing: - enabled: false externalFiles: - sourceRef: ~/.unidesk/.env/pikaoa-admin-password.txt type: raw-file @@ -257,21 +250,8 @@ targets: namespace: pikaoa-test scope: pikaoa-test enabled: true - - id: public-edge-delivery-nc01 - route: NC01:k3s - namespace: devops-infra - scope: public-edge-delivery - enabled: true kubernetesSecrets: - - name: public-edge-trans - targetId: public-edge-delivery-nc01 - secretName: public-edge-trans - type: Opaque - data: - - sourceRef: unidesk-host-k8s.env - sourceKey: UNIDESK_SSH_CLIENT_TOKEN - targetKey: UNIDESK_SSH_CLIENT_TOKEN - name: pikaoa-runtime targetId: pikaoa-nc01 secretName: pikaoa-runtime diff --git a/docs/MDTODO/pr-merge-driven-automatic-delivery.md b/docs/MDTODO/pr-merge-driven-automatic-delivery.md index 2917ae04..25c7f8f0 100644 --- a/docs/MDTODO/pr-merge-driven-automatic-delivery.md +++ b/docs/MDTODO/pr-merge-driven-automatic-delivery.md @@ -150,7 +150,7 @@ #### R9.5.1 [in_progress] 重建 [UniDesk #2205](https://github.com/pikasTech/unidesk/issues/2205):从最新 master 以全新 worktree/session 实现 NC01 shared public-edge 的 merge 驱动自动交付,复用同一 renderer/apply 与 owning YAML/source commit;禁止复用旧 docker.sock 工件,禁止 Kubernetes 挂载 Docker socket/daemon、第二 edge/authority、人工交付、PK01和Vitest,合并后只由正常自动链收敛,完成任务后将详细报告写入[任务报告](./details/pr-merge-driven-automatic-delivery/R9.5.1_Task_Report.md)。 -##### R9.5.1.1 [completed] +##### R9.5.1.1 [in_progress] 重做 [UniDesk #2205](https://github.com/pikasTech/unidesk/issues/2205) 的单一 shared public-edge 自动交付链:仅允许 immutable PaC checkout → YAML SecretRef → 受控 trans → NC01 host-local 既有 public-edge renderer/apply;禁止 Argo PostSync、hostPath、Caddy Admin API 直写、Docker socket/daemon、第二 authority/fallback、PK01、Vitest和人工终态交付;必须使用最新 master 的全新 worktree 与全新 Artificer session,合并后只由自动 CI/CD 收敛,完成任务后将详细报告写入[任务报告](./details/pr-merge-driven-automatic-delivery/R9.5.1.1_Task_Report.md)。 ### R9.6 [completed] diff --git a/scripts/native/cicd/apply-platform-infra-public-edge-archive.mjs b/scripts/native/cicd/apply-platform-infra-public-edge-archive.mjs deleted file mode 100644 index e418130d..00000000 --- a/scripts/native/cicd/apply-platform-infra-public-edge-archive.mjs +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bun - -import { spawnSync } from "node:child_process"; -import { readFileSync, realpathSync } from "node:fs"; -import { dirname, isAbsolute, join, resolve } from "node:path"; - -const options = parseOptions(process.argv.slice(2)); -const sourceRoot = realpathSync(options.sourceRoot); -const markerPath = join(dirname(sourceRoot), ".unidesk-source-commit"); -const markerCommit = readFileSync(markerPath, "utf8").trim(); -if (markerCommit !== options.sourceCommit) fail("archive source commit marker 不匹配"); -const configPath = resolve(sourceRoot, options.config); -if (!configPath.startsWith(`${sourceRoot}/`)) fail("--config 必须位于 source archive 内"); - -const args = [ - "scripts/cli.ts", - "platform-infra", - "public-edge", - "apply", - "--config", - configPath, - "--target", - options.target, - "--confirm", -]; -const result = spawnSync("bun", args, { - cwd: sourceRoot, - env: { ...process.env, UNIDESK_TRANS_REPO_ROOT: sourceRoot }, - stdio: "inherit", - timeout: 120_000, -}); -if (result.status !== 0) process.exit(result.status ?? 1); - -function parseOptions(args) { - const values = new Map(); - let confirm = false; - for (let index = 0; index < args.length; index += 1) { - const arg = args[index]; - if (arg === "--confirm") { - confirm = true; - continue; - } - if (!["--source-root", "--source-commit", "--config", "--target"].includes(arg)) fail(`不支持的参数:${arg}`); - const value = args[index + 1]; - if (value === undefined || value.startsWith("--")) fail(`${arg} 需要参数`); - values.set(arg.slice(2), value); - index += 1; - } - const sourceRoot = values.get("source-root"); - const sourceCommit = values.get("source-commit"); - const config = values.get("config"); - const target = values.get("target"); - if (!confirm) fail("必须显式传入 --confirm"); - if (typeof sourceRoot !== "string" || !isAbsolute(sourceRoot)) fail("--source-root 必须是绝对路径"); - if (typeof sourceCommit !== "string" || !/^[0-9a-f]{40}$/u.test(sourceCommit)) fail("--source-commit 必须是 40 位 commit"); - if (typeof config !== "string" || isAbsolute(config)) fail("--config 必须是 archive 内相对路径"); - if (typeof target !== "string" || target.length === 0) fail("缺少 --target"); - return { sourceRoot, sourceCommit, config, target }; -} - -function fail(message) { - process.stderr.write(`${JSON.stringify({ ok: false, action: "platform-infra-public-edge-archive-apply", error: message })}\n`); - process.exit(1); -} diff --git a/scripts/native/cicd/deliver-platform-infra-public-edge.mjs b/scripts/native/cicd/deliver-platform-infra-public-edge.mjs deleted file mode 100644 index b98a1245..00000000 --- a/scripts/native/cicd/deliver-platform-infra-public-edge.mjs +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/env bun - -import { spawnSync } from "node:child_process"; -import { createHash } from "node:crypto"; -import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { isAbsolute, join, resolve } from "node:path"; - -const options = parseOptions(process.argv.slice(2)); -const sourceRoot = resolve(options.sourceRoot); -const configPath = resolve(sourceRoot, options.config); -const config = Bun.YAML.parse(readFileSync(configPath, "utf8")); -const plan = readPlan(config, sourceRoot, options.sourceCommit, configPath); -verifySourceCommit(sourceRoot, options.sourceCommit, plan.sourceCommitEnvironment); - -if (options.dryRun) { - process.stdout.write(`${JSON.stringify({ - ok: true, - action: "platform-infra-public-edge-delivery-plan", - mutation: false, - sourceCommit: options.sourceCommit, - ...plan.summary, - valuesPrinted: false, - }, null, 2)}\n`); - process.exit(0); -} - -const token = process.env[plan.secret.targetKey]?.trim() ?? ""; -if (token.length === 0) fail(`缺少 SecretRef 投影环境变量:${plan.secret.targetKey}`); - -const temporaryRoot = mkdtempSync(join(tmpdir(), "unidesk-public-edge-delivery-")); -try { - const archivePath = createArchive(sourceRoot, options.sourceCommit, plan.sourcePaths, temporaryRoot); - const archiveSha256 = sha256File(archivePath); - const route = `${plan.route}:${plan.hostCwd}`; - const remoteArchive = `${plan.archiveRoot}/incoming/public-edge-${options.sourceCommit}.tar.gz`; - const transPath = join(sourceRoot, "scripts/trans"); - const transEnv = { - ...process.env, - UNIDESK_TRANS_REPO_ROOT: sourceRoot, - }; - - runTrans(transPath, [route, "sh", "--", `umask 077; mkdir -p ${shellQuote(`${plan.archiveRoot}/incoming`)} ${shellQuote(`${plan.archiveRoot}/tmp`)}`], transEnv); - const upload = runTrans(transPath, [route, "upload", archivePath, remoteArchive], transEnv); - const remote = runTrans(transPath, [route, "sh"], transEnv, remoteApplyScript({ - archivePath: remoteArchive, - archiveRoot: plan.archiveRoot, - archiveSha256, - config: options.config, - entrypoint: plan.entrypoint, - sourceCommit: options.sourceCommit, - targetId: plan.targetId, - })); - const runtime = compactResult(remote); - if (runtime.ok === false || runtime.mutation !== true) fail("host-local public-edge apply 未返回 mutation=true"); - - process.stdout.write(`${JSON.stringify({ - ok: true, - action: "platform-infra-public-edge-delivery", - mutation: true, - sourceCommit: options.sourceCommit, - archive: { - sha256: `sha256:${archiveSha256}`, - sourcePaths: plan.sourcePaths, - remotePath: remoteArchive, - }, - transport: compactResult(upload), - runtime, - ...plan.summary, - valuesPrinted: false, - }, null, 2)}\n`); -} finally { - rmSync(temporaryRoot, { recursive: true, force: true }); -} - -function parseOptions(args) { - let sourceRoot = null; - let sourceCommit = null; - let config = "config/platform-infra/public-edge.yaml"; - let dryRun = false; - let confirm = false; - for (let index = 0; index < args.length; index += 1) { - const arg = args[index]; - if (arg === "--dry-run") dryRun = true; - else if (arg === "--confirm") confirm = true; - else if (arg === "--source-root" || arg === "--source-commit" || arg === "--config") { - const value = args[index + 1]; - if (value === undefined || value.startsWith("--")) fail(`${arg} 需要参数`); - if (arg === "--source-root") sourceRoot = value; - else if (arg === "--source-commit") sourceCommit = value; - else config = value; - index += 1; - } else fail(`不支持的参数:${arg}`); - } - if (sourceRoot === null) fail("缺少 --source-root"); - if (sourceCommit === null || !/^[0-9a-f]{40}$/u.test(sourceCommit)) fail("--source-commit 必须是 40 位小写十六进制 commit"); - if (dryRun === confirm) fail("必须且只能选择 --dry-run 或 --confirm"); - return { sourceRoot, sourceCommit, config, dryRun, confirm }; -} - -function readPlan(config, sourceRoot, sourceCommit, configPath) { - const delivery = record(config.delivery, "delivery"); - if (delivery.enabled !== true) fail("delivery.enabled 必须为 true"); - const defaults = record(config.defaults, "defaults"); - const targets = record(config.targets, "targets"); - const targetId = string(defaults.targetId, "defaults.targetId"); - const target = record(targets[targetId], `targets.${targetId}`); - const route = string(target.route, `targets.${targetId}.route`); - const transport = record(delivery.transport, "delivery.transport"); - const secret = record(transport.secretRef, "delivery.transport.secretRef"); - const hostHelper = record(delivery.hostHelper, "delivery.hostHelper"); - const sourcePaths = array(hostHelper.sourcePaths, "delivery.hostHelper.sourcePaths").map((value, index) => safeRelativePath(value, `delivery.hostHelper.sourcePaths[${index}]`)); - const entrypoint = safeRelativePath(hostHelper.entrypoint, "delivery.hostHelper.entrypoint"); - if (!sourcePaths.some((value) => entrypoint === value || entrypoint.startsWith(`${value}/`))) fail("hostHelper.entrypoint 必须包含在 sourcePaths 中"); - const configRelative = relativeWithin(sourceRoot, configPath); - if (!sourcePaths.some((value) => configRelative === value || configRelative.startsWith(`${value}/`))) fail("public-edge config 必须包含在 sourcePaths 中"); - const secretSummary = { - configRef: safeRelativePath(secret.configRef, "delivery.transport.secretRef.configRef"), - targetId: string(secret.targetId, "delivery.transport.secretRef.targetId"), - secretName: string(secret.secretName, "delivery.transport.secretRef.secretName"), - targetKey: string(secret.targetKey, "delivery.transport.secretRef.targetKey"), - }; - const secretBinding = readSecretBinding(sourceRoot, secretSummary); - const archiveRoot = absolutePath(hostHelper.archiveRoot, "delivery.hostHelper.archiveRoot"); - return { - sourceCommitEnvironment: string(delivery.sourceCommitEnvironment, "delivery.sourceCommitEnvironment"), - targetId, - route, - hostCwd: absolutePath(transport.hostCwd, "delivery.transport.hostCwd"), - archiveRoot, - entrypoint, - sourcePaths, - secret: secretSummary, - summary: { - pipelineId: string(delivery.pipelineId, "delivery.pipelineId"), - configRef: `${configRelative}#targets.${targetId}`, - target: { id: targetId, route }, - secretRef: { ...secretSummary, sourceRef: secretBinding.sourceRef, sourceKey: secretBinding.sourceKey }, - hostHelper: { archiveRoot, entrypoint, sourcePaths }, - sourceCommit, - }, - }; -} - -function readSecretBinding(sourceRoot, secret) { - const configPath = resolve(sourceRoot, secret.configRef); - const config = Bun.YAML.parse(readFileSync(configPath, "utf8")); - const targets = array(config.targets, `${secret.configRef}#targets`); - const target = targets.find((value) => record(value, "secret target").id === secret.targetId); - if (target === undefined || record(target, "secret target").enabled !== true) fail(`Secret target 未启用:${secret.targetId}`); - const bindings = array(config.kubernetesSecrets, `${secret.configRef}#kubernetesSecrets`); - const binding = bindings.find((value) => record(value, "secret binding").name === secret.secretName); - if (binding === undefined) fail(`Secret binding 不存在:${secret.secretName}`); - const bindingRecord = record(binding, `kubernetesSecrets.${secret.secretName}`); - if (bindingRecord.targetId !== secret.targetId || bindingRecord.secretName !== secret.secretName) fail(`Secret binding target 不匹配:${secret.secretName}`); - const data = array(bindingRecord.data, `kubernetesSecrets.${secret.secretName}.data`); - const item = data.find((value) => record(value, "secret data").targetKey === secret.targetKey); - if (item === undefined) fail(`Secret targetKey 不存在:${secret.targetKey}`); - const itemRecord = record(item, `kubernetesSecrets.${secret.secretName}.data.${secret.targetKey}`); - return { - sourceRef: string(itemRecord.sourceRef, `kubernetesSecrets.${secret.secretName}.data.sourceRef`), - sourceKey: string(itemRecord.sourceKey, `kubernetesSecrets.${secret.secretName}.data.sourceKey`), - }; -} - -function verifySourceCommit(sourceRoot, sourceCommit, environmentName) { - const environmentCommit = process.env[environmentName]?.trim() ?? ""; - if (environmentCommit !== sourceCommit) fail(`${environmentName} 与 --source-commit 不一致`); - const result = spawnSync("git", ["rev-parse", "HEAD"], { cwd: sourceRoot, encoding: "utf8" }); - if (result.status !== 0) fail(`无法读取 source checkout commit:${result.stderr || result.stdout}`); - if (result.stdout.trim() !== sourceCommit) fail("source checkout HEAD 与 --source-commit 不一致"); -} - -function createArchive(sourceRoot, sourceCommit, sourcePaths, temporaryRoot) { - const tarPath = join(temporaryRoot, "source.tar"); - const markerPath = join(temporaryRoot, ".unidesk-source-commit"); - writeFileSync(markerPath, `${sourceCommit}\n`, { mode: 0o600 }); - runChecked("git", ["archive", "--format=tar", "--prefix=source/", `--output=${tarPath}`, sourceCommit, "--", ...sourcePaths], sourceRoot); - runChecked("tar", ["--append", "--file", tarPath, "--directory", temporaryRoot, ".unidesk-source-commit"], sourceRoot); - runChecked("gzip", ["-n", tarPath], sourceRoot); - return `${tarPath}.gz`; -} - -function remoteApplyScript(input) { - return `set -eu -archive=${shellQuote(input.archivePath)} -archive_root=${shellQuote(input.archiveRoot)} -expected_sha=${shellQuote(input.archiveSha256)} -source_commit=${shellQuote(input.sourceCommit)} -entrypoint=${shellQuote(input.entrypoint)} -config=${shellQuote(input.config)} -target_id=${shellQuote(input.targetId)} -actual_sha="$(sha256sum "$archive" | awk '{print $1}')" -test "$actual_sha" = "$expected_sha" -tmp="$(mktemp -d "$archive_root/tmp/$source_commit.XXXXXX")" -cleanup() { rm -rf "$tmp"; rm -f "$archive"; } -trap cleanup EXIT HUP INT TERM -tar -xzf "$archive" -C "$tmp" -test "$(cat "$tmp/.unidesk-source-commit")" = "$source_commit" -test -f "$tmp/source/$entrypoint" -cd "$tmp/source" -bun "$entrypoint" --source-root "$tmp/source" --source-commit "$source_commit" --config "$config" --target "$target_id" --confirm -`; -} - -function runTrans(transPath, args, env, input) { - const result = spawnSync(transPath, args, { encoding: "utf8", env, input, timeout: 60_000, maxBuffer: 16 * 1024 * 1024 }); - if (result.status !== 0) fail(`trans ${args.slice(1, 3).join(" ")} 失败:${result.stderr || result.stdout}`); - return result; -} - -function runChecked(command, args, cwd) { - const result = spawnSync(command, args, { cwd, encoding: "utf8", timeout: 60_000, maxBuffer: 16 * 1024 * 1024 }); - if (result.status !== 0) fail(`${command} ${args.join(" ")} 失败:${result.stderr || result.stdout}`); -} - -function compactResult(result) { - const stdout = result.stdout.trim(); - if (stdout.length === 0) return { ok: true }; - try { - return JSON.parse(stdout); - } catch { - return { ok: true, stdout: stdout.slice(-2000) }; - } -} - -function sha256File(path) { - return createHash("sha256").update(readFileSync(path)).digest("hex"); -} - -function record(value, label) { - if (value === null || typeof value !== "object" || Array.isArray(value)) fail(`${label} 必须是对象`); - return value; -} - -function array(value, label) { - if (!Array.isArray(value) || value.length === 0) fail(`${label} 必须是非空数组`); - return value; -} - -function string(value, label) { - if (typeof value !== "string" || value.trim().length === 0) fail(`${label} 必须是非空字符串`); - return value.trim(); -} - -function absolutePath(value, label) { - const path = string(value, label); - if (!isAbsolute(path)) fail(`${label} 必须是绝对路径`); - return path.replace(/\/+$/u, "") || "/"; -} - -function safeRelativePath(value, label) { - const path = string(value, label); - if (isAbsolute(path) || !/^[A-Za-z0-9._/-]+$/u.test(path) || path.split("/").some((segment) => segment === ".." || segment === "")) fail(`${label} 必须是仓库内相对路径`); - return path; -} - -function relativeWithin(root, path) { - const prefix = `${root.replace(/\/+$/u, "")}/`; - if (!path.startsWith(prefix)) fail("--config 必须位于 --source-root 内"); - return path.slice(prefix.length); -} - -function shellQuote(value) { - return `'${String(value).replace(/'/gu, `'\\''`)}'`; -} - -function fail(message) { - process.stderr.write(`${JSON.stringify({ ok: false, action: "platform-infra-public-edge-delivery", error: message })}\n`); - process.exit(1); -} diff --git a/scripts/native/cicd/deliver-platform-infra-public-edge.test.ts b/scripts/native/cicd/deliver-platform-infra-public-edge.test.ts deleted file mode 100644 index a09d4218..00000000 --- a/scripts/native/cicd/deliver-platform-infra-public-edge.test.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { afterEach, describe, expect, test } from "bun:test"; -import { spawnSync } from "node:child_process"; -import { chmodSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { dirname, join } from "node:path"; - -import { rootPath } from "../../src/config"; - -const temporaryRoots: string[] = []; - -afterEach(() => { - for (const root of temporaryRoots.splice(0)) rmSync(root, { recursive: true, force: true }); -}); - -describe("platform-infra public-edge automatic delivery", () => { - test("renders a commit-pinned single-authority dry-run plan", () => { - const root = rootPath(); - const sourceCommit = gitHead(root); - const result = spawnSync("bun", [ - "scripts/native/cicd/deliver-platform-infra-public-edge.mjs", - "--source-root", root, - "--source-commit", sourceCommit, - "--dry-run", - ], { - cwd: root, - encoding: "utf8", - env: { ...process.env, SOURCE_COMMIT: sourceCommit }, - timeout: 30_000, - }); - expect(result.status, result.stderr).toBe(0); - expect(JSON.parse(result.stdout)).toMatchObject({ - ok: true, - action: "platform-infra-public-edge-delivery-plan", - mutation: false, - sourceCommit, - pipelineId: "platform-infra-gitea-nc01", - target: { id: "NC01", route: "NC01" }, - secretRef: { - configRef: "config/secrets-distribution.yaml", - targetId: "public-edge-delivery-nc01", - secretName: "public-edge-trans", - targetKey: "UNIDESK_SSH_CLIENT_TOKEN", - sourceRef: "unidesk-host-k8s.env", - sourceKey: "UNIDESK_SSH_CLIENT_TOKEN", - }, - hostHelper: { - entrypoint: "scripts/native/cicd/apply-platform-infra-public-edge-archive.mjs", - sourcePaths: ["config", "scripts", "package.json", "bun.lock"], - }, - valuesPrinted: false, - }); - }); - - test("PaC projects only the controlled trans secret and existing apply entrypoint", () => { - const pac = readFileSync(`${rootPath()}/.tekton/platform-infra-gitea-nc01-pac.yaml`, "utf8"); - expect(pac).toContain("name: apply-public-edge"); - expect(pac).toContain("name: public-edge-trans"); - expect(pac).toContain("key: UNIDESK_SSH_CLIENT_TOKEN"); - expect(pac).toContain("deliver-platform-infra-public-edge.mjs"); - expect(pac).toContain("--source-commit \"$SOURCE_COMMIT\""); - expect(pac).toContain("--confirm"); - expect(pac).not.toMatch(/PostSync|hostPath|docker\.sock|\/var\/run\/docker|127\.0\.0\.1:2019|caddy reload|docker exec/u); - }); - - test("Secret distribution owns the sourceRef and targetKey", () => { - const secrets = Bun.YAML.parse(readFileSync(`${rootPath()}/config/secrets-distribution.yaml`, "utf8")); - const binding = secrets.kubernetesSecrets.find((item: Record) => item.name === "public-edge-trans"); - expect(binding).toMatchObject({ - targetId: "public-edge-delivery-nc01", - secretName: "public-edge-trans", - data: [{ - sourceRef: "unidesk-host-k8s.env", - sourceKey: "UNIDESK_SSH_CLIENT_TOKEN", - targetKey: "UNIDESK_SSH_CLIENT_TOKEN", - }], - }); - }); - - test("confirm creates a commit archive and uses only controlled trans operations", () => { - const fixture = mkdtempSync(join(tmpdir(), "public-edge-delivery-fixture-")); - temporaryRoots.push(fixture); - write(fixture, "config/platform-infra/public-edge.yaml", Bun.YAML.stringify({ - defaults: { targetId: "NC01" }, - targets: { NC01: { route: "NC01" } }, - delivery: { - enabled: true, - pipelineId: "platform-infra-gitea-nc01", - sourceCommitEnvironment: "SOURCE_COMMIT", - transport: { - hostCwd: "/root", - secretRef: { - configRef: "config/secrets-distribution.yaml", - targetId: "public-edge-delivery-nc01", - secretName: "public-edge-trans", - targetKey: "UNIDESK_SSH_CLIENT_TOKEN", - }, - }, - hostHelper: { - archiveRoot: "/root/unidesk/.state/public-edge-delivery", - entrypoint: "scripts/native/cicd/apply-platform-infra-public-edge-archive.mjs", - sourcePaths: ["config", "scripts", "package.json", "bun.lock"], - }, - }, - })); - write(fixture, "config/secrets-distribution.yaml", Bun.YAML.stringify({ - targets: [{ id: "public-edge-delivery-nc01", enabled: true }], - kubernetesSecrets: [{ - name: "public-edge-trans", - targetId: "public-edge-delivery-nc01", - secretName: "public-edge-trans", - data: [{ - sourceRef: "unidesk-host-k8s.env", - sourceKey: "UNIDESK_SSH_CLIENT_TOKEN", - targetKey: "UNIDESK_SSH_CLIENT_TOKEN", - }], - }], - })); - write(fixture, "scripts/native/cicd/apply-platform-infra-public-edge-archive.mjs", "process.exit(0);\n"); - write(fixture, "scripts/trans", `#!/bin/sh -set -eu -if [ "$2" = "sh" ] && [ "\${3-}" != "--" ]; then - cat >/dev/null - printf '%s\\n' '{"ok":true,"mutation":true}' -else - printf '%s\\n' '{"ok":true}' -fi -`); - chmodSync(join(fixture, "scripts/trans"), 0o755); - write(fixture, "package.json", "{}\n"); - write(fixture, "bun.lock", ""); - git(["init", "-b", "master"], fixture); - git(["config", "user.name", "UniDesk Test"], fixture); - git(["config", "user.email", "unidesk-test@example.invalid"], fixture); - git(["add", "."], fixture); - git(["commit", "-m", "fixture"], fixture); - const sourceCommit = gitHead(fixture); - const result = spawnSync("bun", [ - "scripts/native/cicd/deliver-platform-infra-public-edge.mjs", - "--source-root", fixture, - "--source-commit", sourceCommit, - "--confirm", - ], { - cwd: rootPath(), - encoding: "utf8", - env: { - ...process.env, - SOURCE_COMMIT: sourceCommit, - UNIDESK_SSH_CLIENT_TOKEN: "fixture-token", - }, - timeout: 30_000, - }); - expect(result.status, result.stderr).toBe(0); - const output = JSON.parse(result.stdout); - expect(output).toMatchObject({ - ok: true, - action: "platform-infra-public-edge-delivery", - mutation: true, - sourceCommit, - runtime: { ok: true, mutation: true }, - }); - expect(output.archive.sha256).toMatch(/^sha256:[0-9a-f]{64}$/u); - }); -}); - -function gitHead(cwd: string): string { - const result = spawnSync("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" }); - if (result.status !== 0) throw new Error(result.stderr || result.stdout); - return result.stdout.trim(); -} - -function write(root: string, relativePath: string, content: string) { - const path = join(root, relativePath); - mkdirSync(dirname(path), { recursive: true }); - writeFileSync(path, content); -} - -function git(args: string[], cwd: string) { - const result = spawnSync("git", args, { cwd, encoding: "utf8" }); - if (result.status !== 0) throw new Error(result.stderr || result.stdout); -}