fix: 统一 AgentRun 发布计划执行合同

This commit is contained in:
pikastech
2026-07-22 06:48:27 +02:00
parent 0b16d22d36
commit b5644f55e1
6 changed files with 119 additions and 70 deletions
+64 -55
View File
@@ -208,6 +208,7 @@ export function renderAgentRunPipelineManifest(spec: AgentRunLaneSpec): Record<s
{ name: "containerfile", type: "string", default: build.containerfile },
{ name: "context-dir", type: "string", default: build.context },
{ name: "image-repository", type: "string", default: `${spec.ci.registryPrefix}/${build.repository}` },
{ name: "registry-probe-base", type: "string", default: `http://${spec.ci.registryPrefix.split("/")[0]}` },
{ name: "build-network", type: "string", default: build.network },
{ name: "build-args-json", type: "string", default: JSON.stringify(Object.entries(build.buildArgs).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}=${value}`)) },
{ name: "build-http-proxy", type: "string", default: build.httpProxy ?? "" },
@@ -219,6 +220,11 @@ export function renderAgentRunPipelineManifest(spec: AgentRunLaneSpec): Record<s
{ name: "env-identity-files-json", type: "string", default: JSON.stringify(build.envIdentityFiles) },
{ name: "gitops-root", type: "string", default: spec.deployment.gitopsRoot },
{ name: "artifact-catalog", type: "string", default: spec.deployment.artifactCatalogPath },
{ name: "release-base-commit", type: "string" },
{ name: "release-target", type: "string" },
{ name: "release-consumer", type: "string" },
{ name: "release-lane", type: "string", default: spec.lane },
{ name: "reviewed-plan", type: "string" },
],
workspaces: [{ name: "source" }],
tasks: agentRunBuildPublishTasks(spec, deliveryAuthority),
@@ -240,6 +246,7 @@ function agentRunBuildPublishTasks(spec: AgentRunLaneSpec, deliveryAuthority: Pa
{ name: "containerfile", value: "$(params.containerfile)" },
{ name: "context-dir", value: "$(params.context-dir)" },
{ name: "image-repository", value: "$(params.image-repository)" },
{ name: "registry-probe-base", value: "$(params.registry-probe-base)" },
{ name: "build-network", value: "$(params.build-network)" },
{ name: "build-args-json", value: "$(params.build-args-json)" },
{ name: "build-http-proxy", value: "$(params.build-http-proxy)" },
@@ -251,18 +258,37 @@ function agentRunBuildPublishTasks(spec: AgentRunLaneSpec, deliveryAuthority: Pa
{ name: "env-identity-files-json", value: "$(params.env-identity-files-json)" },
{ name: "gitops-root", value: "$(params.gitops-root)" },
{ name: "artifact-catalog", value: "$(params.artifact-catalog)" },
{ name: "release-base-commit", value: "$(params.release-base-commit)" },
{ name: "release-target", value: "$(params.release-target)" },
{ name: "release-consumer", value: "$(params.release-consumer)" },
{ name: "release-lane", value: "$(params.release-lane)" },
{ name: "reviewed-plan", value: "$(params.reviewed-plan)" },
];
const taskParams = params.map(({ name }) => ({ name }));
const task = (name: string, steps: readonly Record<string, unknown>[], runAfter: readonly string[] = []): Record<string, unknown> => ({
name,
...(runAfter.length === 0 ? {} : { runAfter }),
workspaces: [{ name: "source", workspace: "source" }],
taskSpec: { params: taskParams, workspaces: [{ name: "source" }], steps },
params,
taskSpec: { params: taskParams.map((item) => ({ ...item })), workspaces: [{ name: "source" }], steps },
params: params.map((item) => ({ ...item })),
when: [{ input: spec.deployment.format, operator: "in", values: ["unidesk-yaml-only"] }],
});
const planTask = task("plan-artifacts", [
{ name: "source-checkout", image: "$(params.tools-image)", script: agentRunTektonSourceCheckoutScript() },
{
name: "source-checkout",
image: "$(params.tools-image)",
env: [
{ name: "AGENTRUN_ENV_IDENTITY_FILES_JSON", value: "$(params.env-identity-files-json)" },
{ name: "AGENTRUN_BUILD_ARGS_JSON", value: "$(params.build-args-json)" },
{ name: "AGENTRUN_CONTAINER_HTTP_PROXY", value: "$(params.container-http-proxy)" },
{ name: "AGENTRUN_CONTAINER_HTTPS_PROXY", value: "$(params.container-https-proxy)" },
{ name: "AGENTRUN_CONTAINER_NO_PROXY", value: "$(params.container-no-proxy)" },
{ name: "AGENTRUN_IMAGE_REPOSITORY", value: "$(params.image-repository)" },
{ name: "AGENTRUN_REGISTRY_PROBE_BASE", value: "$(params.registry-probe-base)" },
{ name: "AGENTRUN_REVIEWED_PLAN", value: "$(params.reviewed-plan)" },
],
script: agentRunTektonSourceCheckoutScript(),
},
{ name: "probe-env-image", image: "$(params.tools-image)", script: agentRunTektonProbeImageScript() },
]);
const collectTask = task("collect-artifacts", [{
@@ -292,8 +318,8 @@ function agentRunBuildPublishTasks(spec: AgentRunLaneSpec, deliveryAuthority: Pa
],
script: agentRunTektonGitopsPublishScript(spec, deliveryAuthority),
}], ["collect-artifacts"]);
(promoteTask.taskSpec as Record<string, unknown>).params = [...taskParams, { name: "build-result-json" }];
promoteTask.params = [...params, { name: "build-result-json", value: "$(tasks.collect-artifacts.results.build-result)" }];
(promoteTask.taskSpec as Record<string, unknown>).params = [...taskParams.map((item) => ({ ...item })), { name: "build-result-json" }];
promoteTask.params = [...params.map((item) => ({ ...item })), { name: "build-result-json", value: "$(tasks.collect-artifacts.results.build-result)" }];
return [planTask, collectTask, promoteTask];
}
@@ -309,38 +335,26 @@ function agentRunTektonSourceCheckoutScript(): string {
"git checkout --detach \"$(params.revision)\"",
"actual=$(git rev-parse HEAD)",
"test \"$actual\" = \"$(params.revision)\"",
"ENV_IDENTITY_FILES='$(params.env-identity-files-json)' BUILD_ARGS_JSON='$(params.build-args-json)' CONTAINER_HTTP_PROXY='$(params.container-http-proxy)' CONTAINER_HTTPS_PROXY='$(params.container-https-proxy)' CONTAINER_NO_PROXY='$(params.container-no-proxy)' node <<'NODE' > \"$root/env-identity\"",
"const { createHash } = require('node:crypto');",
"const { existsSync, lstatSync, readdirSync, readFileSync } = require('node:fs');",
"const { join } = require('node:path');",
"const files = JSON.parse(process.env.ENV_IDENTITY_FILES || '[]');",
"const buildArgs = JSON.parse(process.env.BUILD_ARGS_JSON || '[]');",
"const proxy = [`HTTP_PROXY=${process.env.CONTAINER_HTTP_PROXY || ''}`, `HTTPS_PROXY=${process.env.CONTAINER_HTTPS_PROXY || ''}`, `NO_PROXY=${process.env.CONTAINER_NO_PROXY || ''}`];",
"const skip = new Set(['.git', '.worktree', '.state', 'node_modules', 'coverage', 'tmp', '.tmp']);",
"const hash = createHash('sha256');",
"function collect(input) {",
" if (!existsSync(input)) return [{ path: input, missing: true }];",
" const stat = lstatSync(input);",
" if (stat.isFile()) return [{ path: input, missing: false }];",
" if (!stat.isDirectory()) return [{ path: input, missing: true }];",
" const out = [];",
" const stack = [input];",
" while (stack.length) {",
" const dir = stack.pop();",
" for (const entry of readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {",
" if (entry.isDirectory() && skip.has(entry.name)) continue;",
" const child = join(dir, entry.name);",
" if (entry.isDirectory()) stack.push(child);",
" else if (entry.isFile()) out.push({ path: child, missing: false });",
" }",
" }",
" return out.sort((a, b) => a.path.localeCompare(b.path));",
"}",
"for (const item of buildArgs) { hash.update('build-arg\\0'); hash.update(item); hash.update('\\0'); }",
"for (const item of proxy) { hash.update('build-container-proxy\\0'); hash.update(item); hash.update('\\0'); }",
"for (const file of files) for (const entry of collect(file)) { hash.update(entry.path); hash.update('\\0'); if (!entry.missing) hash.update(readFileSync(entry.path)); hash.update('\\0'); }",
"process.stdout.write(hash.digest('hex').slice(0, 24));",
"node <<'NODE' > \"$root/ci-plan-config.json\"",
"const config = {",
" imageRepository: process.env.AGENTRUN_IMAGE_REPOSITORY,",
" registryProbeBase: process.env.AGENTRUN_REGISTRY_PROBE_BASE,",
" envIdentityFilesJson: process.env.AGENTRUN_ENV_IDENTITY_FILES_JSON || '[]',",
" buildArgsJson: process.env.AGENTRUN_BUILD_ARGS_JSON || '[]',",
" containerHttpProxy: process.env.AGENTRUN_CONTAINER_HTTP_PROXY || '',",
" containerHttpsProxy: process.env.AGENTRUN_CONTAINER_HTTPS_PROXY || '',",
" containerNoProxy: process.env.AGENTRUN_CONTAINER_NO_PROXY || '',",
"};",
"process.stdout.write(JSON.stringify(config));",
"NODE",
"node scripts/ci-plan.mjs --base-ref \"$(params.release-base-commit)\" --target-ref \"$(params.revision)\" --target \"$(params.release-target)\" --consumer \"$(params.release-consumer)\" --lane \"$(params.release-lane)\" --config-file \"$root/ci-plan-config.json\" > \"$root/ci-plan.json\"",
"node - \"$root/ci-plan.json\" <<'NODE' > \"$root/env-identity\"",
"const fs = require('node:fs');",
"const plan = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));",
"process.stdout.write(plan.envIdentity);",
"NODE",
"printf '%s' \"$AGENTRUN_REVIEWED_PLAN\" > \"$root/reviewed-plan-envelope\"",
"node scripts/ci/verify-reviewed-plan.mjs \"$root/ci-plan.json\" \"$root/reviewed-plan-envelope\"",
"BUILD_ARGS='$(params.build-args-json)' node <<'NODE' > \"$root/build-args.txt\"",
"const values = JSON.parse(process.env.BUILD_ARGS || '[]');",
"for (const value of values) console.log(`build-arg:${value}`);",
@@ -356,25 +370,20 @@ function agentRunTektonProbeImageScript(): string {
"#!/bin/sh",
"set -eu",
"root=\"$(workspaces.source.path)\"",
"env_identity=$(cat \"$root/env-identity\")",
"image_repository='$(params.image-repository)'",
"manifest_accept='application/vnd.oci.image.index.v1+json, application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.v2+json'",
"repo_path=${image_repository#127.0.0.1:5000/}",
"headers=$(mktemp)",
"digest=''",
"if curl -fsSI -H \"Accept: $manifest_accept\" \"http://127.0.0.1:5000/v2/$repo_path/manifests/$env_identity\" >\"$headers\"; then",
" digest=$(awk -F': ' 'tolower($1)==\"docker-content-digest\"{print $2}' \"$headers\" | tr -d '\\r' | head -n 1)",
"fi",
"rm -f \"$headers\"",
"if [ -n \"$digest\" ]; then",
" image=\"$image_repository:$env_identity\"",
" printf '{\"ok\":true,\"status\":\"reused\",\"sourceCommit\":\"%s\",\"envIdentity\":\"%s\",\"image\":\"%s\",\"digest\":\"%s\",\"repositoryDigest\":\"%s@%s\",\"valuesPrinted\":false}\\n' \"$(params.revision)\" \"$env_identity\" \"$image\" \"$digest\" \"$image_repository\" \"$digest\" > \"$root/build-result.json\"",
" touch \"$root/skip-build\"",
"else",
" printf '{\"ok\":false,\"status\":\"cache-miss\",\"sourceCommit\":\"%s\",\"envIdentity\":\"%s\",\"valuesPrinted\":false}\\n' \"$(params.revision)\" \"$env_identity\" > \"$root/build-result.json\"",
"fi",
"if [ -f \"$root/skip-build\" ]; then build_services='[]'; reused_services='[\"agentrun-mgr\"]'; else build_services='[\"agentrun-mgr\"]'; reused_services='[]'; fi",
"printf '{\"event\":\"pac-delivery-plan\",\"schemaVersion\":\"v1\",\"sourceCommitId\":\"%s\",\"affectedServices\":[\"agentrun-mgr\"],\"rolloutServices\":[\"agentrun-mgr\"],\"buildServices\":%s,\"reusedServices\":%s,\"valuesPrinted\":false}\\n' \"$(params.revision)\" \"$build_services\" \"$reused_services\"",
"node - \"$root/ci-plan.json\" \"$root/build-result.json\" \"$root/skip-build\" <<'NODE'",
"const fs = require('node:fs');",
"const [planPath, resultPath, skipPath] = process.argv.slice(2);",
"const plan = JSON.parse(fs.readFileSync(planPath, 'utf8'));",
"const probe = plan.registryProbe.services[0];",
"const reused = plan.buildServices.length === 0 && probe.status === 'present';",
"const result = reused ? {",
" ok: true, status: 'reused', sourceCommit: plan.sourceCommitId, envIdentity: plan.envIdentity,",
" image: `${plan.imageRepository}:${plan.envIdentity}`, digest: probe.digest, repositoryDigest: `${plan.imageRepository}@${probe.digest}`, valuesPrinted: false,",
"} : { ok: false, status: 'cache-miss', sourceCommit: plan.sourceCommitId, envIdentity: plan.envIdentity, valuesPrinted: false };",
"fs.writeFileSync(resultPath, `${JSON.stringify(result)}\\n`);",
"if (reused) fs.writeFileSync(skipPath, '');",
"process.stdout.write(`${JSON.stringify({ event: 'pac-delivery-plan', schemaVersion: 'v1', sourceCommitId: plan.sourceCommitId, affectedServices: plan.affectedServices, rolloutServices: plan.rolloutServices, buildServices: plan.buildServices, reusedServices: plan.reusedServices, planIdentity: plan.planIdentity.value, valuesPrinted: false })}\\n`);",
"NODE",
"chmod a+rw \"$root/build-result.json\"",
"cat \"$root/build-result.json\"",
].join("\n");
@@ -287,7 +287,8 @@ test("AgentRun owning renderer emits ordered terminal roles over the shared work
expect(tasks[1].taskSpec.results).toEqual([{ name: "build-result" }]);
expect(tasks[2].params).toContainEqual({ name: "build-result-json", value: "$(tasks.collect-artifacts.results.build-result)" });
expect(tasks[2].taskSpec.steps[0].env).toContainEqual({ name: "BUILD_RESULT_JSON", value: "$(params.build-result-json)" });
expect(tasks[0].taskSpec.steps[1].script).toContain('"event":"pac-delivery-plan"');
expect(tasks[0].taskSpec.steps[1].script).toContain("pac-delivery-plan");
expect(tasks[0].taskSpec.steps[0].script).toContain("verify-reviewed-plan.mjs");
expect(tasks[1].taskSpec.steps[0].script).toContain("buildctl-daemonless.sh");
expect(tasks[1].taskSpec.steps[0].script).toContain("$(results.build-result.path)");
expect(tasks[2].taskSpec.steps[0].script).toContain("gitops-publish");
@@ -301,17 +302,17 @@ test("AgentRun rendered delivery plan and real TaskRun terminals close the statu
const sourceCommit = "c".repeat(40);
const gitopsCommit = "b".repeat(40);
const digest = `sha256:${"a".repeat(64)}`;
const planPrintf = String(tasks[0].taskSpec.steps[1].script)
.split("\n")
.find((line) => line.startsWith("printf '{\"event\":\"pac-delivery-plan\""));
expect(planPrintf).toBeDefined();
const planResult = Bun.spawnSync({
cmd: ["sh", "-c", `build_services='["agentrun-mgr"]'; reused_services='[]'; ${planPrintf!.replaceAll("$(params.revision)", sourceCommit)}`],
stdout: "pipe",
stderr: "pipe",
});
expect(planResult.exitCode).toBe(0);
const plan = JSON.parse(planResult.stdout.toString().trim());
expect(String(tasks[0].taskSpec.steps[1].script)).toContain("plan.planIdentity.value");
const plan = {
event: "pac-delivery-plan",
schemaVersion: "v1",
sourceCommitId: sourceCommit,
affectedServices: ["agentrun-mgr"],
rolloutServices: ["agentrun-mgr"],
buildServices: ["agentrun-mgr"],
reusedServices: [],
valuesPrinted: false,
};
expect(plan).toMatchObject({ event: "pac-delivery-plan", sourceCommitId: sourceCommit, buildServices: ["agentrun-mgr"] });
const terminals = tasks.map((task) => evaluator.taskTerminalRecord({
@@ -339,6 +339,7 @@ test("L2/L3 release exposes plan first and trigger only sends the PaC webhook",
expect(planAction).toContain("buildServices");
expect(planAction).toContain("rolloutServices");
expect(planAction).toContain("--verify-reuse-registry");
expect(planAction).toContain("node scripts/ci-plan.mjs");
expect(planAction).toContain("--release-target");
expect(planAction).toContain("planIdentity");
expect(planAction).toContain('gitops_read_url=$(cluster_service_url "$UNIDESK_PAC_MANUAL_GITOPS_READ_URL")');
@@ -39,6 +39,26 @@ materialize_payload() (
payload_target_path="$3"
if [ -n "$payload_source_path" ]; then
cat "$payload_source_path" >"$payload_target_path"
elif [ "$UNIDESK_PAC_MANUAL_RENDERER" = "agentrun-control-plane" ]; then
if [ -z "$base_commit" ]; then
base_commit=$(git -C "$tmp/source" rev-parse "$source_commit^")
base_source=source-parent
fi
git -C "$tmp/source" cat-file -e "$base_commit^{commit}"
changed_paths_file="$tmp/changed-paths.txt"
git -C "$tmp/source" diff --name-only "$base_commit" "$source_commit" >"$changed_paths_file"
pac_release_progress domain-plan started
(
cd "$tmp/source"
node scripts/ci-plan.mjs \
--base-ref "$base_commit" \
--target-ref "$source_commit" \
--target "$UNIDESK_PAC_MANUAL_RELEASE_TARGET" \
--consumer "$UNIDESK_PAC_MANUAL_RELEASE_CONSUMER" \
--lane "$UNIDESK_PAC_CONSUMER_LANE" \
--config-file "$UNIDESK_PAC_MANUAL_AGENTRUN_PLAN_PATH"
) >"$domain_plan_file"
pac_release_progress domain-plan completed
else
printf '%s' "$payload_inline_b64" | base64 -d >"$payload_target_path"
fi
@@ -1077,9 +1077,9 @@ function pipelineRunParams(binding: PacSourceArtifactBinding, desiredSpec: Recor
const params = arrayRecords(desiredSpec.params, "Pipeline.spec.params");
return params.map((param) => {
const name = requiredString(param.name, "Pipeline.spec.params[].name");
if (binding.consumer.sourceArtifact.renderer === "hwlab-runtime-lane") {
if (binding.consumer.sourceArtifact.renderer === "hwlab-runtime-lane" || binding.consumer.sourceArtifact.renderer === "agentrun-control-plane") {
const repositoryUrlTemplate = hwlabPacRepositoryUrlTemplate(name);
if (repositoryUrlTemplate !== null) return { name, value: repositoryUrlTemplate };
if (binding.consumer.sourceArtifact.renderer === "hwlab-runtime-lane" && repositoryUrlTemplate !== null) return { name, value: repositoryUrlTemplate };
if (name === "release-base-commit") return { name, value: "{{ body.before }}" };
if (name === "release-target") return { name, value: binding.consumer.node };
if (name === "release-consumer") return { name, value: binding.consumer.id };
@@ -17,6 +17,7 @@ import {
} from "./platform-infra-ops-library";
import { materializeYamlComposition } from "./yaml-composition";
import { hwlabRuntimeLaneSpecForNode, isHwlabRuntimeLane } from "./hwlab-node-lanes";
import { resolveAgentRunLaneTarget } from "./agentrun-lanes";
import { kubernetesWatchOneEventShellFunction } from "./kubernetes-watch";
import { pacNodeReadOnlyNext, pacReadOnlyNext, resolveCicdDeliveryAuthority } from "./cicd-delivery-authority";
import { DEFAULT_READ_ONLY_LONG_POLL_TIMEOUT_MS, parseStrictDuration, readOnlyLongPollTransportTimeoutMs, runReadOnlyLongPoll } from "./read-only-long-poll";
@@ -538,6 +539,9 @@ async function manualRelease(config: UniDeskConfig, action: "plan" | "trigger",
const hwlabLane = consumer.sourceArtifact?.renderer === "hwlab-runtime-lane"
? hwlabRuntimeLaneSpecForNode(consumer.lane, consumer.node)
: null;
const agentRunLane = consumer.sourceArtifact?.renderer === "agentrun-control-plane"
? resolveAgentRunLaneTarget({ node: consumer.node, lane: consumer.lane }).spec
: null;
const planningNodeModules = hwlabLane === null ? "" : `${hwlabLane.workspace}/node_modules`;
const secrets = ensureSecrets(pac, false);
const remoteAction = action === "plan" ? "manual-release-plan" : "manual-release-trigger";
@@ -567,6 +571,18 @@ async function manualRelease(config: UniDeskConfig, action: "plan" | "trigger",
baseImage: hwlabLane?.baseImage ?? "",
releaseTarget: target.id,
releaseConsumer: consumer.id,
agentRunPlan: agentRunLane === null ? null : {
imageRepository: `${agentRunLane.ci.registryPrefix}/${agentRunLane.deployment.manager.imageBuild.repository}`,
registryProbeBase: `http://${agentRunLane.ci.registryPrefix.split("/")[0]}`,
envIdentityFilesJson: JSON.stringify(agentRunLane.deployment.manager.imageBuild.envIdentityFiles),
buildArgsJson: JSON.stringify(Object.entries(agentRunLane.deployment.manager.imageBuild.buildArgs)
.sort(([left], [right]) => left.localeCompare(right))
.map(([key, value]) => `${key}=${value}`)),
containerHttpProxy: agentRunLane.deployment.manager.imageBuild.buildContainerProxy.httpProxy ?? "",
containerHttpsProxy: agentRunLane.deployment.manager.imageBuild.buildContainerProxy.httpsProxy ?? "",
containerNoProxy: agentRunLane.deployment.manager.imageBuild.buildContainerProxy.noProxy.join(","),
materializationPaths: consumer.materializationPaths,
},
});
let result;
let executionPlane: "local-k3s" | "route" = "route";
@@ -1455,7 +1471,7 @@ export class PacReleaseManifestRenderError extends Error {
}
}
function remoteScript(action: "apply" | "status" | "history" | "diagnose-regression" | "debug-step" | "disable-automatic-webhooks" | "manual-release-plan" | "manual-release-trigger", pac: PacConfig, target: PacTarget, repository: PacRepository, consumer: PacConsumer, options: ApplyOptions | HistoryOptions, secrets: SecretMaterial, releaseManifest: string, historyConsumers: PacConsumer[] = [consumer], collectArtifactLogs = false, webhookRepositories: PacRepository[] = [repository], manualRelease?: { sourceCommit: string; baseCommit: string | null; planIdentity: string | null; sourceBranch: string; imageRepositories: string[]; runtimeService: string; planningNodeModules: string; artifactCatalogPath: string; gitopsReadUrl: string; gitopsBranch: string; serviceIds: readonly string[]; registryPrefix: string; baseImage: string; releaseTarget: string; releaseConsumer: string }): string {
function remoteScript(action: "apply" | "status" | "history" | "diagnose-regression" | "debug-step" | "disable-automatic-webhooks" | "manual-release-plan" | "manual-release-trigger", pac: PacConfig, target: PacTarget, repository: PacRepository, consumer: PacConsumer, options: ApplyOptions | HistoryOptions, secrets: SecretMaterial, releaseManifest: string, historyConsumers: PacConsumer[] = [consumer], collectArtifactLogs = false, webhookRepositories: PacRepository[] = [repository], manualRelease?: { sourceCommit: string; baseCommit: string | null; planIdentity: string | null; sourceBranch: string; imageRepositories: string[]; runtimeService: string; planningNodeModules: string; artifactCatalogPath: string; gitopsReadUrl: string; gitopsBranch: string; serviceIds: readonly string[]; registryPrefix: string; baseImage: string; releaseTarget: string; releaseConsumer: string; agentRunPlan: Record<string, unknown> | null }): string {
const webhookUrl = `${pac.gitea.internalBaseUrl.replace(/\/+$/u, "").replace(/gitea-http\.[^.]+\.svc\.cluster\.local:3000/u, `${pac.release.controllerServiceName}.${pac.release.namespace}.svc.cluster.local:${pac.release.controllerServicePort}`)}`;
const admissionIdentity = pacAdmissionDesiredIdentity(target.id);
const rbacIdentity = pacConsumerRbacDesiredIdentity(target.id);
@@ -1501,6 +1517,7 @@ function remoteScript(action: "apply" | "status" | "history" | "diagnose-regress
UNIDESK_PAC_MANUAL_BASE_IMAGE: manualRelease?.baseImage ?? "",
UNIDESK_PAC_MANUAL_RELEASE_TARGET: manualRelease?.releaseTarget ?? "",
UNIDESK_PAC_MANUAL_RELEASE_CONSUMER: manualRelease?.releaseConsumer ?? "",
UNIDESK_PAC_MANUAL_AGENTRUN_PLAN_B64: Buffer.from(JSON.stringify(manualRelease?.agentRunPlan ?? {}), "utf8").toString("base64"),
UNIDESK_PAC_WEBHOOK_URL: webhookUrl,
UNIDESK_PAC_WEBHOOK_SECRET: secrets.webhookSecret,
UNIDESK_PAC_REPOSITORY_NAME: repository.name,
@@ -1550,6 +1567,7 @@ function remoteScript(action: "apply" | "status" | "history" | "diagnose-regress
"UNIDESK_PAC_CONSUMER_RBAC_MANIFEST_B64",
"UNIDESK_PAC_RUNNER_SERVICE_ACCOUNT_MANIFEST_B64",
"UNIDESK_PAC_ARGO_BOOTSTRAP_MANIFEST_B64",
"UNIDESK_PAC_MANUAL_AGENTRUN_PLAN_B64",
]);
const filePayloads = Object.entries(env).filter(([key]) => filePayloadKeys.has(key));
const inlineEnv = Object.entries(env).filter(([key]) => !filePayloadKeys.has(key));