feat: add yaml-first AgentRun lane ops

This commit is contained in:
Codex
2026-06-13 04:21:57 +00:00
parent 58d4b6c76f
commit 687310d83c
4 changed files with 928 additions and 4 deletions
+329 -4
View File
@@ -5,6 +5,13 @@ import type { RenderedCliResult } from "./output";
import { runSshCommandCapture, type SshCaptureResult } from "./ssh";
import { runRemoteSshCommandCapture } from "./remote";
import { startJob } from "./jobs";
import {
AGENTRUN_CONFIG_PATH,
agentRunLaneSummary,
agentRunPipelineRunName,
resolveAgentRunLaneTarget,
type AgentRunLaneSpec,
} from "./agentrun-lanes";
const g14SourceRoute = "G14:/root/agentrun-v01";
const g14K3sRoute = "G14:k3s";
@@ -56,6 +63,8 @@ export function agentRunHelp(): unknown {
"bun scripts/cli.ts agentrun apply -f - --dry-run",
"bun scripts/cli.ts agentrun send session/<sessionId> --aipod Artificer --prompt-stdin",
"bun scripts/cli.ts agentrun explain task",
"bun scripts/cli.ts agentrun control-plane plan --node D601 --lane v02",
"bun scripts/cli.ts agentrun control-plane status --node D601 --lane v02",
"bun scripts/cli.ts agentrun control-plane status",
"bun scripts/cli.ts agentrun control-plane status --full",
"bun scripts/cli.ts agentrun control-plane status --pipeline-run agentrun-v01-ci-<short-sha>",
@@ -92,6 +101,7 @@ export async function runAgentRunCommand(config: UniDeskConfig | null, args: str
}
if (config === null) throw new Error("agentrun control-plane and git-mirror commands require UniDesk config");
if (group === "control-plane") {
if (action === "plan") return await controlPlanePlan(config, parseStatusOptions(actionArgs));
if (action === "status") return await status(config, parseStatusOptions(actionArgs));
if (action === "expose") return await exposeAgentRun(config, parseConfirmOptions(actionArgs));
if (action === "trigger-current") return await triggerCurrent(config, parseTriggerOptions(actionArgs));
@@ -217,8 +227,10 @@ function agentRunHelpText(args: string[]): string {
return [
"Usage: bun scripts/cli.ts agentrun control-plane <action> [options]",
"",
"Actions: status, expose, trigger-current, refresh, cleanup-runs, cleanup-released-pvs",
"Actions: plan, status, expose, trigger-current, refresh, cleanup-runs, cleanup-released-pvs",
"Examples:",
" bun scripts/cli.ts agentrun control-plane plan --node D601 --lane v02",
" bun scripts/cli.ts agentrun control-plane status --node D601 --lane v02",
" bun scripts/cli.ts agentrun control-plane status",
" bun scripts/cli.ts agentrun control-plane status --pipeline-run agentrun-v01-ci-<short-sha>",
" bun scripts/cli.ts agentrun control-plane expose --dry-run",
@@ -1645,6 +1657,8 @@ interface DisclosureOptions {
}
interface StatusOptions extends DisclosureOptions {
node: string | null;
lane: string | null;
sourceCommit: string | null;
pipelineRun: string | null;
targetMode: "latest-source-head" | "source-commit" | "pipeline-run";
@@ -1656,7 +1670,14 @@ interface TimedValue<T> {
}
function parseDisclosureOptions(args: string[]): DisclosureOptions {
for (const arg of args) {
for (let index = 0; index < args.length; index += 1) {
const arg = args[index];
if (arg === "--node" || arg === "--lane") {
const value = args[index + 1];
if (value === undefined || value.startsWith("--")) throw new Error(`${arg} requires a value`);
index += 1;
continue;
}
if (arg !== "--full" && arg !== "--raw") throw new Error(`unsupported status option: ${arg}`);
}
const raw = args.includes("--raw");
@@ -1664,6 +1685,8 @@ function parseDisclosureOptions(args: string[]): DisclosureOptions {
}
function parseStatusOptions(args: string[]): StatusOptions {
let node: string | null = null;
let lane: string | null = null;
let sourceCommit: string | null = null;
let pipelineRun: string | null = null;
let full = false;
@@ -1679,6 +1702,20 @@ function parseStatusOptions(args: string[]): StatusOptions {
full = true;
continue;
}
if (arg === "--node") {
const value = args[index + 1];
if (value === undefined || value.startsWith("--")) throw new Error("--node requires a value");
node = value;
index += 1;
continue;
}
if (arg === "--lane") {
const value = args[index + 1];
if (value === undefined || value.startsWith("--")) throw new Error("--lane requires a value");
lane = value;
index += 1;
continue;
}
if (arg === "--source-commit") {
const value = args[index + 1];
if (value === undefined || value.startsWith("--")) throw new Error("--source-commit requires a value");
@@ -1690,7 +1727,7 @@ function parseStatusOptions(args: string[]): StatusOptions {
if (arg === "--pipeline-run") {
const value = args[index + 1];
if (value === undefined || value.startsWith("--")) throw new Error("--pipeline-run requires a value");
if (!isAgentRunPipelineRunName(value)) throw new Error("--pipeline-run must be an agentrun-v01-ci-<12+ hex> PipelineRun name");
if (!isAgentRunPipelineRunName(value)) throw new Error("--pipeline-run must be an agentrun-vNN-ci-<12+ hex> PipelineRun name");
pipelineRun = value;
index += 1;
continue;
@@ -1701,6 +1738,8 @@ function parseStatusOptions(args: string[]): StatusOptions {
return {
full,
raw,
node,
lane,
sourceCommit,
pipelineRun,
targetMode: pipelineRun !== null ? "pipeline-run" : sourceCommit !== null ? "source-commit" : "latest-source-head",
@@ -1779,7 +1818,42 @@ function positiveIntegerOption(args: string[], name: string, defaultValue: numbe
return Math.min(value, maxValue);
}
async function controlPlanePlan(_config: UniDeskConfig, options: StatusOptions): Promise<Record<string, unknown>> {
const target = resolveAgentRunLaneTarget(options);
const spec = target.spec;
return {
ok: true,
command: "agentrun control-plane plan",
mode: "yaml-declared-node-lane",
configPath: target.configPath,
target: agentRunLaneSummary(spec),
plannedChecks: [
"source-branch-exists",
"source-worktree-exists-and-clean",
"git-mirror-services-ready",
"ci-namespace-pipeline-serviceaccount",
"argo-application-alignment",
"runtime-namespace-manager-service",
"database-secretref-present",
"local-postgres-absent-when-external",
],
deploymentBoundary: {
mutation: false,
note: "plan/status are read-only. Long writes must use controlled AgentRun/Platform DB commands and this YAML target.",
},
next: {
status: `bun scripts/cli.ts agentrun control-plane status --node ${spec.nodeId} --lane ${spec.lane}`,
postgresStatus: spec.database.configRef ? `bun scripts/cli.ts platform-db postgres status --config ${spec.database.configRef}` : null,
postgresApply: spec.database.configRef ? `bun scripts/cli.ts platform-db postgres apply --config ${spec.database.configRef} --confirm` : null,
},
valuesPrinted: false,
};
}
async function status(config: UniDeskConfig, options: StatusOptions): Promise<Record<string, unknown>> {
if (options.node !== null || options.lane !== null) {
return await statusYamlLane(config, options, resolveAgentRunLaneTarget(options));
}
const sourceProbe = await timedStatusStage("source", () => capture(config, g14SourceRoute, ["script", "--", [
"cd /root/agentrun-v01",
"git fetch origin v0.1 >/dev/null 2>&1 || true",
@@ -1930,6 +2004,103 @@ async function status(config: UniDeskConfig, options: StatusOptions): Promise<Re
};
}
async function statusYamlLane(config: UniDeskConfig, options: StatusOptions, target: { configPath: string; spec: AgentRunLaneSpec }): Promise<Record<string, unknown>> {
const spec = target.spec;
const sourceProbe = await timedStatusStage("source", () => capture(config, `${spec.nodeRoute}:${spec.source.workspace}`, ["script", "--", yamlLaneSourceStatusScript(spec)]));
const sourcePayload = captureJsonPayload(sourceProbe.value);
const sourceCommit = options.sourceCommit
?? (options.pipelineRun !== null ? null : stringOrNull(sourcePayload.remoteBranchCommit) ?? stringOrNull(sourcePayload.localHead));
const pipelineRun = options.pipelineRun ?? (sourceCommit ? agentRunPipelineRunName(spec, sourceCommit) : null);
const [runtimeProbe, mirrorProbe] = await Promise.all([
timedStatusStage("runtime", () => capture(config, spec.nodeKubeRoute, ["script", "--", yamlLaneRuntimeStatusScript(spec, pipelineRun)])),
timedStatusStage("git-mirror", () => capture(config, spec.nodeKubeRoute, ["script", "--", yamlLaneGitMirrorStatusScript(spec)])),
]);
const runtimePayload = captureJsonPayload(runtimeProbe.value);
const mirrorPayload = captureJsonPayload(mirrorProbe.value);
const pipeline = record(runtimePayload.pipeline);
const argo = record(runtimePayload.argo);
const manager = record(runtimePayload.manager);
const database = record(runtimePayload.database);
const localPostgres = record(runtimePayload.localPostgres);
const blockers = [
...(sourcePayload.workspaceExists === true ? [] : ["source-worktree-missing"]),
...(sourcePayload.remoteBranchExists === true ? [] : ["source-branch-missing"]),
...(sourcePayload.workspaceClean === true || sourcePayload.workspaceExists !== true ? [] : ["source-worktree-dirty"]),
...(mirrorPayload.readReady === true ? [] : ["git-mirror-read-not-ready"]),
...(mirrorPayload.writeReady === true ? [] : ["git-mirror-write-not-ready"]),
...(mirrorPayload.cachePvcExists === true ? [] : ["git-mirror-cache-pvc-missing"]),
...(runtimePayload.ciNamespaceExists === true ? [] : ["ci-namespace-missing"]),
...(pipeline.exists === true ? [] : ["pipeline-missing"]),
...(runtimePayload.serviceAccountExists === true ? [] : ["ci-serviceaccount-missing"]),
...(argo.exists === true ? [] : ["argo-application-missing"]),
...(runtimePayload.runtimeNamespaceExists === true ? [] : ["runtime-namespace-missing"]),
...(manager.deploymentExists === true ? [] : ["manager-deployment-missing"]),
...(manager.serviceExists === true ? [] : ["manager-service-missing"]),
...(spec.database.mode === "external-postgres" && database.secretPresent !== true ? ["database-secret-missing"] : []),
...(spec.database.localPostgresExpectedAbsent && localPostgres.absent !== true ? ["local-postgres-present"] : []),
];
return {
ok: sourceProbe.value.exitCode === 0 && runtimeProbe.value.exitCode === 0 && mirrorProbe.value.exitCode === 0 && blockers.length === 0,
command: "agentrun control-plane status",
mode: "yaml-declared-node-lane",
configPath: target.configPath,
target: agentRunLaneSummary(spec),
summary: {
aligned: blockers.length === 0,
blockers,
sourceCommit,
expectedPipelineRun: pipelineRun,
source: {
workspaceExists: sourcePayload.workspaceExists ?? false,
workspaceClean: sourcePayload.workspaceClean ?? null,
localHead: sourcePayload.localHead ?? null,
remoteBranchExists: sourcePayload.remoteBranchExists ?? false,
remoteBranchCommit: sourcePayload.remoteBranchCommit ?? null,
},
gitMirror: {
readReady: mirrorPayload.readReady ?? false,
writeReady: mirrorPayload.writeReady ?? false,
cachePvcExists: mirrorPayload.cachePvcExists ?? false,
repositoryCount: Array.isArray(mirrorPayload.repositories) ? mirrorPayload.repositories.length : null,
},
ci: {
namespaceExists: runtimePayload.ciNamespaceExists ?? false,
serviceAccountExists: runtimePayload.serviceAccountExists ?? false,
pipeline,
pipelineRun: record(runtimePayload.pipelineRun),
},
argo,
runtime: {
namespaceExists: runtimePayload.runtimeNamespaceExists ?? false,
manager,
database,
localPostgres,
},
},
timings: {
sourceMs: sourceProbe.elapsedMs,
runtimeMs: runtimeProbe.elapsedMs,
gitMirrorMs: mirrorProbe.elapsedMs,
totalMs: sourceProbe.elapsedMs + Math.max(runtimeProbe.elapsedMs, mirrorProbe.elapsedMs),
},
source: sourcePayload,
runtime: runtimePayload,
gitMirror: mirrorPayload,
captures: {
source: compactCapture(sourceProbe.value, { full: options.full || options.raw || sourceProbe.value.exitCode !== 0 }),
runtime: compactCapture(runtimeProbe.value, { full: options.full || options.raw || runtimeProbe.value.exitCode !== 0 }),
gitMirror: compactCapture(mirrorProbe.value, { full: options.full || options.raw || mirrorProbe.value.exitCode !== 0 }),
},
next: {
plan: `bun scripts/cli.ts agentrun control-plane plan --node ${spec.nodeId} --lane ${spec.lane}`,
postgresStatus: spec.database.configRef ? `bun scripts/cli.ts platform-db postgres status --config ${spec.database.configRef}` : null,
postgresApply: spec.database.configRef ? `bun scripts/cli.ts platform-db postgres apply --config ${spec.database.configRef} --confirm` : null,
statusFull: `bun scripts/cli.ts agentrun control-plane status --node ${spec.nodeId} --lane ${spec.lane} --full`,
},
valuesPrinted: false,
};
}
async function exposeAgentRun(_config: UniDeskConfig, options: ConfirmOptions): Promise<Record<string, unknown>> {
const clientConfig = readAgentRunClientConfig();
const exposure = clientConfig.publicExposure;
@@ -2406,6 +2577,160 @@ function cleanupReleasedPvsScript(options: CleanupReleasedPvOptions): string {
].join("\n");
}
function yamlLaneSourceStatusScript(spec: AgentRunLaneSpec): string {
return [
"set +e",
`expected_workspace=${shQuote(spec.source.workspace)}`,
`source_branch=${shQuote(spec.source.branch)}`,
"workspace_exists=false",
"workspace_clean=null",
"local_head=null",
"branch=null",
"remote_url=null",
"remote_branch_exists=false",
"remote_branch_commit=null",
"status_short=''",
"if [ -d .git ] || git rev-parse --show-toplevel >/dev/null 2>&1; then",
" actual_workspace=$(pwd)",
" workspace_exists=true",
" branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)",
" remote_url=$(git remote get-url origin 2>/dev/null || true)",
" local_head=$(git rev-parse HEAD 2>/dev/null || true)",
" status_short=$(git status --short 2>/dev/null || true)",
" if [ -z \"$status_short\" ]; then workspace_clean=true; else workspace_clean=false; fi",
" git fetch origin \"$source_branch\" >/dev/null 2>&1 || true",
" remote_branch_commit=$(git rev-parse \"refs/remotes/origin/$source_branch\" 2>/dev/null || true)",
" if [ -n \"$remote_branch_commit\" ]; then remote_branch_exists=true; fi",
"else",
" actual_workspace=$(pwd)",
"fi",
"export expected_workspace source_branch workspace_exists workspace_clean local_head branch remote_url remote_branch_exists remote_branch_commit status_short actual_workspace",
"node <<'NODE'",
"function nullable(value) { return value && value !== 'null' ? value : null; }",
"function booleanValue(value) { if (value === 'true') return true; if (value === 'false') return false; return null; }",
"const env = process.env;",
"console.log(JSON.stringify({",
" ok: env.workspace_exists === 'true',",
" expectedWorkspace: env.expected_workspace,",
" actualWorkspace: env.actual_workspace || null,",
" workspaceExists: env.workspace_exists === 'true',",
" workspaceClean: booleanValue(env.workspace_clean),",
" branch: nullable(env.branch),",
" remoteUrl: nullable(env.remote_url),",
" localHead: nullable(env.local_head),",
" remoteBranch: env.source_branch,",
" remoteBranchExists: env.remote_branch_exists === 'true',",
" remoteBranchCommit: nullable(env.remote_branch_commit),",
" statusShort: nullable(env.status_short),",
" valuesPrinted: false",
"}));",
"NODE",
].join("\n");
}
function yamlLaneRuntimeStatusScript(spec: AgentRunLaneSpec, pipelineRun: string | null): string {
return [
"set +e",
`runtime_namespace=${shQuote(spec.runtime.namespace)}`,
`ci_namespace=${shQuote(spec.ci.namespace)}`,
`pipeline_name=${shQuote(spec.ci.pipeline)}`,
`pipeline_run=${pipelineRun === null ? "''" : shQuote(pipelineRun)}`,
`service_account=${shQuote(spec.ci.serviceAccountName)}`,
`argo_namespace=${shQuote(spec.gitops.argoNamespace)}`,
`argo_application=${shQuote(spec.gitops.argoApplication)}`,
`manager_deployment=${shQuote(spec.runtime.managerDeployment)}`,
`manager_service=${shQuote(spec.runtime.managerService)}`,
`database_secret=${shQuote(spec.database.secretRef.name)}`,
`database_key=${shQuote(spec.database.secretRef.key)}`,
"export runtime_namespace ci_namespace pipeline_name pipeline_run service_account argo_namespace argo_application manager_deployment manager_service database_secret database_key",
"tmp_dir=$(mktemp -d)",
"trap 'rm -rf \"$tmp_dir\"' EXIT",
"kubectl get ns \"$runtime_namespace\" -o json > \"$tmp_dir/runtime-ns.json\" 2>/dev/null",
"runtime_ns_exit=$?",
"kubectl get ns \"$ci_namespace\" -o json > \"$tmp_dir/ci-ns.json\" 2>/dev/null",
"ci_ns_exit=$?",
"kubectl -n \"$ci_namespace\" get pipeline \"$pipeline_name\" -o json > \"$tmp_dir/pipeline.json\" 2>/dev/null",
"pipeline_exit=$?",
"kubectl -n \"$ci_namespace\" get serviceaccount \"$service_account\" -o json > \"$tmp_dir/serviceaccount.json\" 2>/dev/null",
"sa_exit=$?",
"if [ -n \"$pipeline_run\" ]; then kubectl -n \"$ci_namespace\" get pipelinerun \"$pipeline_run\" -o json > \"$tmp_dir/pipelinerun.json\" 2>/dev/null; pr_exit=$?; else pr_exit=2; fi",
"kubectl -n \"$argo_namespace\" get application \"$argo_application\" -o json > \"$tmp_dir/argo.json\" 2>/dev/null",
"argo_exit=$?",
"kubectl -n \"$runtime_namespace\" get deploy \"$manager_deployment\" -o json > \"$tmp_dir/manager-deploy.json\" 2>/dev/null",
"manager_deploy_exit=$?",
"kubectl -n \"$runtime_namespace\" get svc \"$manager_service\" -o json > \"$tmp_dir/manager-svc.json\" 2>/dev/null",
"manager_svc_exit=$?",
"kubectl -n \"$runtime_namespace\" get secret \"$database_secret\" -o json > \"$tmp_dir/db-secret.json\" 2>/dev/null",
"db_secret_exit=$?",
"kubectl -n \"$runtime_namespace\" get deploy,sts,svc,secret -o name > \"$tmp_dir/runtime-names.txt\" 2>/dev/null",
"NODE_TMP=\"$tmp_dir\" RUNTIME_NS_EXIT=\"$runtime_ns_exit\" CI_NS_EXIT=\"$ci_ns_exit\" PIPELINE_EXIT=\"$pipeline_exit\" SERVICE_ACCOUNT_EXIT=\"$sa_exit\" PIPELINERUN_EXIT=\"$pr_exit\" ARGO_EXIT=\"$argo_exit\" MANAGER_DEPLOY_EXIT=\"$manager_deploy_exit\" MANAGER_SVC_EXIT=\"$manager_svc_exit\" DB_SECRET_EXIT=\"$db_secret_exit\" node <<'NODE'",
"const fs = require('node:fs');",
"const path = require('node:path');",
"const dir = process.env.NODE_TMP;",
"function readJson(name) { try { return JSON.parse(fs.readFileSync(path.join(dir, name), 'utf8')); } catch { return null; } }",
"function exists(exitName) { return process.env[exitName] === '0'; }",
"function condition(obj) { return obj?.status?.conditions?.[0] || null; }",
"function envValue(deploy, name) { return deploy?.spec?.template?.spec?.containers?.[0]?.env?.find((entry) => entry.name === name)?.value || null; }",
"const pipelineRun = readJson('pipelinerun.json');",
"const argo = readJson('argo.json');",
"const managerDeploy = readJson('manager-deploy.json');",
"const managerSvc = readJson('manager-svc.json');",
"const dbSecret = readJson('db-secret.json');",
"let names = ''; try { names = fs.readFileSync(path.join(dir, 'runtime-names.txt'), 'utf8'); } catch {}",
"const c = condition(pipelineRun);",
"console.log(JSON.stringify({",
" ok: exists('RUNTIME_NS_EXIT') && exists('CI_NS_EXIT'),",
" runtimeNamespaceExists: exists('RUNTIME_NS_EXIT'),",
" ciNamespaceExists: exists('CI_NS_EXIT'),",
" serviceAccountExists: exists('SERVICE_ACCOUNT_EXIT'),",
" pipeline: { exists: exists('PIPELINE_EXIT'), name: process.env.pipeline_name },",
" pipelineRun: { exists: exists('PIPELINERUN_EXIT'), name: process.env.pipeline_run || null, status: c?.status || null, reason: c?.reason || null, startTime: pipelineRun?.status?.startTime || null, completionTime: pipelineRun?.status?.completionTime || null },",
" argo: { exists: exists('ARGO_EXIT'), namespace: process.env.argo_namespace, application: process.env.argo_application, revision: argo?.status?.sync?.revision || null, syncStatus: argo?.status?.sync?.status || null, healthStatus: argo?.status?.health?.status || null },",
" manager: { deploymentExists: exists('MANAGER_DEPLOY_EXIT'), serviceExists: exists('MANAGER_SVC_EXIT'), deployment: process.env.manager_deployment, service: process.env.manager_service, image: managerDeploy?.spec?.template?.spec?.containers?.[0]?.image || null, sourceCommit: envValue(managerDeploy, 'AGENTRUN_SOURCE_COMMIT'), servicePorts: Array.isArray(managerSvc?.spec?.ports) ? managerSvc.spec.ports.map((port) => ({ name: port.name || null, port: port.port || null, targetPort: port.targetPort || null })) : [] },",
" database: { secretPresent: exists('DB_SECRET_EXIT'), secretName: process.env.database_secret, key: process.env.database_key, keyPresent: Boolean(dbSecret?.data && Object.prototype.hasOwnProperty.call(dbSecret.data, process.env.database_key || '')) , valuesPrinted: false },",
" localPostgres: { absent: !/postgres/i.test(names), matchingObjects: names.split(/\\r?\\n/).filter((line) => /postgres/i.test(line)).slice(0, 20) },",
" valuesPrinted: false",
"}));",
"NODE",
].join("\n");
}
function yamlLaneGitMirrorStatusScript(spec: AgentRunLaneSpec): string {
return [
"set +e",
`namespace=${shQuote(spec.gitMirror.namespace)}`,
`read_service=${shQuote(spec.gitMirror.readService)}`,
`write_service=${shQuote(spec.gitMirror.writeService)}`,
`cache_pvc=${shQuote(spec.gitMirror.cachePvc)}`,
`repositories_json=${shQuote(JSON.stringify(spec.gitMirror.repositories))}`,
"kubectl -n \"$namespace\" get svc \"$read_service\" -o json >/tmp/agentrun-gitmirror-read.json 2>/dev/null",
"read_exit=$?",
"kubectl -n \"$namespace\" get svc \"$write_service\" -o json >/tmp/agentrun-gitmirror-write.json 2>/dev/null",
"write_exit=$?",
"kubectl -n \"$namespace\" get pvc \"$cache_pvc\" -o json >/tmp/agentrun-gitmirror-cache.json 2>/dev/null",
"cache_exit=$?",
"kubectl -n \"$namespace\" get deploy,svc,pvc -o name > /tmp/agentrun-gitmirror-names.txt 2>/dev/null",
"NAMESPACE=\"$namespace\" READ_EXIT=\"$read_exit\" WRITE_EXIT=\"$write_exit\" CACHE_EXIT=\"$cache_exit\" REPOSITORIES_JSON=\"$repositories_json\" node <<'NODE'",
"const fs = require('node:fs');",
"const repositories = JSON.parse(process.env.REPOSITORIES_JSON || '[]');",
"let names = ''; try { names = fs.readFileSync('/tmp/agentrun-gitmirror-names.txt', 'utf8'); } catch {}",
"const readReady = process.env.READ_EXIT === '0';",
"const writeReady = process.env.WRITE_EXIT === '0';",
"const cachePvcExists = process.env.CACHE_EXIT === '0';",
"console.log(JSON.stringify({",
" ok: readReady && writeReady && cachePvcExists,",
" namespace: process.env.NAMESPACE,",
" readReady,",
" writeReady,",
" cachePvcExists,",
" resources: names.split(/\\r?\\n/).filter(Boolean).slice(0, 40),",
" repositories,",
" valuesPrinted: false",
"}));",
"NODE",
].join("\n");
}
function cleanupRunsPlanNodeScript(): string {
return String.raw`
const fs = require("node:fs");
@@ -4429,7 +4754,7 @@ function pipelineRunName(sourceCommit: string): string {
}
function isAgentRunPipelineRunName(value: string): boolean {
return /^agentrun-v01-ci-[0-9a-f]{12,40}(?:-[a-z0-9-]+)?$/u.test(value);
return /^agentrun-v[0-9]+-ci-[0-9a-f]{12,40}(?:-[a-z0-9-]+)?$/u.test(value);
}
function statusTargetArg(options: StatusOptions, target: Record<string, unknown>): string {