fix: 统一 AgentRun 发布计划执行合同
This commit is contained in:
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user