fix: render sub2api apply output concisely

This commit is contained in:
Codex
2026-07-01 13:03:56 +00:00
parent ecbc6e4f93
commit c7c6832bec
+131 -2
View File
@@ -71,7 +71,11 @@ export async function runPlatformInfraCommand(config: UniDeskConfig, args: strin
const result = plan(parseTargetOptions(planArgs));
return planArgs.includes("--full") || planArgs.includes("--raw") ? result : renderSub2ApiPlan(result);
}
if (action === "apply") return await apply(config, parseApplyOptions(args.slice(2)));
if (action === "apply") {
const options = parseApplyOptions(args.slice(2));
const result = await apply(config, options);
return options.full || options.raw ? result : renderSub2ApiApply(result);
}
if (action === "status") {
const options = parseDisclosureOptions(args.slice(2));
const result = await status(config, options);
@@ -90,6 +94,8 @@ export interface ApplyOptions {
dryRun: boolean;
confirm: boolean;
wait: boolean;
full: boolean;
raw: boolean;
}
export interface DisclosureOptions {
@@ -207,6 +213,126 @@ function renderSub2ApiStatus(result: Record<string, unknown>): RenderedCliResult
return rendered(result, "platform-infra sub2api status", lines);
}
function renderSub2ApiApply(result: Record<string, unknown>): RenderedCliResult {
const target = record(result.target);
const remote = record(result.remote);
const policy = arrayRecords(result.policy);
const failedPolicy = policy.filter((item) => item.ok === false);
const mode = stringValue(result.mode);
const targetId = stringValue(target.id, stringValue(result.target));
const route = stringValue(target.route, stringValue(remote.route));
const namespace = stringValue(target.namespace, "-");
const status = result.ok === false ? "failed" : "ok";
const lines = [
"PLATFORM-INFRA SUB2API APPLY",
...table(["TARGET", "ROUTE", "NAMESPACE", "MODE", "STATUS"], [[targetId, route, namespace, mode, status]]),
"",
"POLICY",
failedPolicy.length === 0 ? "ok" : `failed=${failedPolicy.length}`,
];
if (mode === "policy-blocked") {
lines.push(
"",
"FAILED POLICY",
...(failedPolicy.length === 0 ? ["-"] : table(["NAME", "DETAIL"], failedPolicy.map((item) => [stringValue(item.name), stringValue(item.detail)]))),
"",
"NEXT",
` plan: bun scripts/cli.ts platform-infra sub2api plan --target ${targetId}`,
` full: bun scripts/cli.ts platform-infra sub2api apply --target ${targetId} --dry-run --full`,
);
return rendered(result, "platform-infra sub2api apply", lines);
}
if (mode === "async-job") {
const job = record(result.job);
const next = record(result.next);
lines.push(
"",
"JOB",
...table(["ID", "STATUS", "COMMAND"], [[stringValue(job.id), stringValue(job.status, "started"), stringValue(result.statusCommand)]]),
"",
"NEXT",
` status: ${stringValue(next.status, stringValue(result.statusCommand))}`,
` rollout: ${stringValue(next.rollout, `bun scripts/cli.ts platform-infra sub2api status --target ${targetId}`)}`,
` validate: ${stringValue(next.validate, `bun scripts/cli.ts platform-infra sub2api validate --target ${targetId}`)}`,
` full: bun scripts/cli.ts platform-infra sub2api apply --target ${targetId} --confirm --wait --full`,
);
return rendered(result, "platform-infra sub2api apply", lines);
}
lines.push(
"",
"REMOTE",
...renderApplyRemoteSummary(remote),
);
const pk01Exposure = record(result.pk01Exposure);
if (Object.keys(pk01Exposure).length > 0) {
lines.push(
"",
"PK01_EXPOSURE",
...table(["CHECK", "VALUE"], [
["ok", boolText(pk01Exposure.ok)],
["mode", stringValue(pk01Exposure.mode)],
["valuesPrinted", "false"],
]),
);
}
const next = record(result.next);
lines.push(
"",
"NEXT",
` status: ${stringValue(next.status, `bun scripts/cli.ts platform-infra sub2api status --target ${targetId}`)}`,
` validate: ${stringValue(next.validate, `bun scripts/cli.ts platform-infra sub2api validate --target ${targetId}`)}`,
` full: bun scripts/cli.ts platform-infra sub2api apply --target ${targetId} ${mode === "confirmed" ? "--confirm --wait" : "--dry-run"} --full`,
"Disclosure: default output is bounded; use --full or --raw for remote stdout/stderr details.",
);
return rendered(result, "platform-infra sub2api apply", lines);
}
function renderApplyRemoteSummary(remote: Record<string, unknown>): string[] {
const steps = record(remote.steps);
const stepRows = Object.entries(steps).map(([name, value]) => {
const step = record(value);
return [name, stringValue(step.exitCode), step.exitCode === 0 ? "ok" : "failed"];
});
for (const name of ["clientDryRun", "serverDryRun", "accountLocalProxySecretDryRun"]) {
const step = record(remote[name]);
if (step.exitCode !== undefined) stepRows.push([name, stringValue(step.exitCode), step.exitCode === 0 ? "ok" : "failed"]);
}
const ports = record(remote.ports);
const runtime = stringValue(remote.runtimeMode, record(remote.serverDryRun).exitCode !== undefined ? "k3s" : "-");
const rows = [
["ok", boolText(remote.ok), "runtime", runtime],
["target", stringValue(remote.target), "route", stringValue(remote.route)],
];
if (remote.namespace !== undefined) rows.push(["namespace", stringValue(remote.namespace), "existsBeforeDryRun", boolText(remote.namespaceExistsBeforeDryRun)]);
if (remote.image !== undefined || remote.projectName !== undefined) rows.push(["image", stringValue(remote.image), "project", stringValue(remote.projectName)]);
const lines = [
...table(["FIELD", "VALUE", "DETAIL", "VALUE"], rows),
];
if (Object.keys(ports).length > 0) {
lines.push(
"",
"PORTS",
...table(["NAME", "VALUE"], [
["app", stringValue(ports.app)],
["redis", stringValue(ports.redis)],
["observed", stringValue(ports.observed).replace(/\s+/gu, " ").trim()],
]),
);
}
lines.push(
"",
"STEPS",
...(stepRows.length === 0 ? ["-"] : table(["STEP", "EXIT", "STATUS"], stepRows)),
"valuesPrinted=false",
);
return lines;
}
function rendered(result: Record<string, unknown>, command: string, lines: string[]): RenderedCliResult {
return {
ok: result.ok !== false,
@@ -254,13 +380,16 @@ export function unsupported(args: string[]): Record<string, unknown> {
export function parseApplyOptions(args: string[]): ApplyOptions {
const target = parseTargetOptions(args);
validateOptions(args, new Set(["--dry-run", "--confirm", "--wait", "--target"]));
validateOptions(args, new Set(["--dry-run", "--confirm", "--wait", "--target", "--full", "--raw"]));
if (args.includes("--dry-run") && args.includes("--confirm")) throw new Error("apply accepts only one of --dry-run or --confirm");
const raw = args.includes("--raw");
return {
targetId: target.targetId,
dryRun: args.includes("--dry-run") || !args.includes("--confirm"),
confirm: args.includes("--confirm"),
wait: args.includes("--wait"),
full: raw || args.includes("--full"),
raw,
};
}