fix: smooth hwlab pr and rollout visibility
This commit is contained in:
+55
-51
@@ -414,6 +414,31 @@ function compactCommandResult(result: CommandJsonResult): Record<string, unknown
|
||||
};
|
||||
}
|
||||
|
||||
function compactControlPlaneRefresh(value: Record<string, unknown>): Record<string, unknown> {
|
||||
return {
|
||||
ok: value.ok === true,
|
||||
phase: value.phase ?? null,
|
||||
sourceCommit: value.sourceCommit ?? null,
|
||||
renderDir: value.renderDir ?? null,
|
||||
applyOk: nested(value, ["apply", "ok"]) ?? null,
|
||||
cleanupOk: nested(value, ["cleanupObsoleteCronJobs", "ok"]) ?? null,
|
||||
applyStdout: tailText(nested(value, ["apply", "stdout"]), 1200),
|
||||
degradedReason: value.degradedReason ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
function compactTriggerCommandResult(value: Record<string, unknown> | null): Record<string, unknown> | null {
|
||||
if (value === null) return null;
|
||||
return {
|
||||
ok: value.ok ?? null,
|
||||
exitCode: value.exitCode ?? null,
|
||||
stdout: tailText(value.stdout, 1200),
|
||||
stderr: tailText(value.stderr, 1200),
|
||||
stdoutBytes: value.stdoutBytes ?? null,
|
||||
stderrBytes: value.stderrBytes ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
function isCommandSuccess(result: CommandJsonResult): boolean {
|
||||
if (!result.ok) return false;
|
||||
const topOk = record(result.parsed).ok;
|
||||
@@ -477,14 +502,6 @@ function getV02Head(): string | null {
|
||||
return match?.[0] ?? null;
|
||||
}
|
||||
|
||||
function getV02CachedHead(): string | null {
|
||||
const result = v02WorkspaceScript("git rev-parse origin/v0.2", 30_000);
|
||||
if (!isCommandSuccess(result)) return null;
|
||||
const output = String(nested(result.parsed, ["data", "stdout"]) ?? result.stdout).trim();
|
||||
const match = /[0-9a-f]{40}/iu.exec(output);
|
||||
return match?.[0] ?? null;
|
||||
}
|
||||
|
||||
function v02PipelineRunName(sourceCommit: string): string {
|
||||
return `${V02_PIPELINERUN_PREFIX}-${shortSha(sourceCommit)}`;
|
||||
}
|
||||
@@ -539,31 +556,6 @@ function secondsBetween(start: unknown, end: unknown): number | null {
|
||||
return Math.round((endMs - startMs) / 1000);
|
||||
}
|
||||
|
||||
function pipelineRunStatusRow(item: unknown, nowMs: number): Record<string, unknown> {
|
||||
const root = record(item);
|
||||
const metadata = record(root.metadata);
|
||||
const status = record(root.status);
|
||||
const labels = record(metadata.labels);
|
||||
const conditions = Array.isArray(status.conditions) ? status.conditions : [];
|
||||
const condition = record(conditions[0]);
|
||||
const startTime = status.startTime ?? null;
|
||||
const completionTime = status.completionTime ?? null;
|
||||
const startMs = timestampMs(startTime);
|
||||
const conditionStatus = typeof condition.status === "string" ? condition.status : null;
|
||||
return {
|
||||
name: metadata.name ?? null,
|
||||
sourceCommit: labels["hwlab.pikastech.local/source-commit"] ?? null,
|
||||
status: conditionStatus,
|
||||
reason: condition.reason ?? null,
|
||||
createdAt: metadata.creationTimestamp ?? null,
|
||||
startTime,
|
||||
completionTime,
|
||||
durationSeconds: secondsBetween(startTime, completionTime),
|
||||
elapsedSeconds: startMs === null || completionTime !== null ? null : Math.max(0, Math.round((nowMs - startMs) / 1000)),
|
||||
active: completionTime === null && conditionStatus !== "True" && conditionStatus !== "False",
|
||||
};
|
||||
}
|
||||
|
||||
function pipelineRunStatusRowFromLine(line: string, nowMs: number): Record<string, unknown> | null {
|
||||
const [
|
||||
name = "",
|
||||
@@ -592,8 +584,7 @@ function pipelineRunStatusRowFromLine(line: string, nowMs: number): Record<strin
|
||||
};
|
||||
}
|
||||
|
||||
function parsePipelineRunRows(text: string, limit: number): Record<string, unknown> {
|
||||
const nowMs = Date.now();
|
||||
function parsePipelineRunRows(text: string, limit: number, nowMs = Date.now()): Record<string, unknown> {
|
||||
const rows = text
|
||||
.split(/\r?\n/u)
|
||||
.map((line) => pipelineRunStatusRowFromLine(line.trim(), nowMs))
|
||||
@@ -698,9 +689,15 @@ function shellSectionOk(section: ShellSection | undefined): boolean {
|
||||
return section?.exitCode === 0;
|
||||
}
|
||||
|
||||
function v02ControlPlaneStatusBundle(pipelineRun: string | null): CommandJsonResult {
|
||||
function v02ControlPlaneStatusBundle(sourceCommit: string | null | undefined): CommandJsonResult {
|
||||
const sourceCommitLine = sourceCommit === undefined
|
||||
? `source_commit=$(git -C ${shellQuote(V02_WORKSPACE)} rev-parse origin/v0.2 2>/dev/null || true)`
|
||||
: `source_commit=${shellQuote(sourceCommit ?? "")}`;
|
||||
const script = [
|
||||
"set +e",
|
||||
sourceCommitLine,
|
||||
"pipeline_run=",
|
||||
`if [ -n "$source_commit" ]; then pipeline_run="${V02_PIPELINERUN_PREFIX}-$(printf '%s' "$source_commit" | cut -c1-12)"; fi`,
|
||||
"section() {",
|
||||
" name=\"$1\"",
|
||||
" shift",
|
||||
@@ -709,18 +706,18 @@ function v02ControlPlaneStatusBundle(pipelineRun: string | null): CommandJsonRes
|
||||
" code=$?",
|
||||
" printf '\\n__UNIDESK_SECTION_END__ %s exit=%s\\n' \"$name\" \"$code\"",
|
||||
"}",
|
||||
"section sourceCommit printf '%s\\n' \"$source_commit\"",
|
||||
"section queryNow date -u +%Y-%m-%dT%H:%M:%SZ",
|
||||
`section controlPlane kubectl get pipeline,role,rolebinding,serviceaccount -n ${shellQuote(CI_NAMESPACE)} -l hwlab.pikastech.local/gitops-target=v02 -o name`,
|
||||
`section obsoleteCronJobs kubectl get cronjob -n ${shellQuote(CI_NAMESPACE)} ${shellQuote(V02_POLLER)} ${shellQuote(V02_RECONCILER)} --ignore-not-found -o name`,
|
||||
`section argo kubectl get application -n ${shellQuote(ARGO_NAMESPACE)} ${shellQuote(V02_APP)} -o 'jsonpath={.spec.source.targetRevision}{"\\n"}{.spec.source.path}{"\\n"}{.status.sync.revision}{"\\n"}{.status.sync.status}{"\\n"}{.status.health.status}{"\\n"}'`,
|
||||
pipelineRun === null
|
||||
? "section pipelineRun sh -c 'true'"
|
||||
: `section pipelineRun kubectl get pipelinerun -n ${shellQuote(CI_NAMESPACE)} ${shellQuote(pipelineRun)} -o 'jsonpath={.status.conditions[0].status}{"\\n"}{.status.conditions[0].reason}{"\\n"}{.status.conditions[0].message}{"\\n"}'`,
|
||||
`if [ -n "$pipeline_run" ]; then section pipelineRun kubectl get pipelinerun -n ${shellQuote(CI_NAMESPACE)} "$pipeline_run" -o 'jsonpath={.status.conditions[0].status}{"\\n"}{.status.conditions[0].reason}{"\\n"}{.status.conditions[0].message}{"\\n"}'; else section pipelineRun sh -c 'true'; fi`,
|
||||
`section recentPipelineRuns kubectl get pipelinerun -n ${shellQuote(CI_NAMESPACE)} -l hwlab.pikastech.local/gitops-target=v02 -o ${shellQuote(pipelineRunRowsJsonPath())}`,
|
||||
].join("\n");
|
||||
return g14K3s(["script", "--", script], 60_000);
|
||||
}
|
||||
|
||||
function listV02PipelineRunsCompactFromText(text: string, commandOk: boolean, command: string[] | string, exitCode: number | null, stderr: string, limit = 8): Record<string, unknown> {
|
||||
function listV02PipelineRunsCompactFromText(text: string, commandOk: boolean, command: string[] | string, exitCode: number | null, stderr: string, limit = 8, nowMs = Date.now()): Record<string, unknown> {
|
||||
if (!commandOk) {
|
||||
return {
|
||||
ok: false,
|
||||
@@ -731,7 +728,7 @@ function listV02PipelineRunsCompactFromText(text: string, commandOk: boolean, co
|
||||
activeItems: [],
|
||||
};
|
||||
}
|
||||
return parsePipelineRunRows(text, limit);
|
||||
return parsePipelineRunRows(text, limit, nowMs);
|
||||
}
|
||||
|
||||
function pipelinePrefixesForLane(lane: "v02" | "g14" | "all"): string[] {
|
||||
@@ -1177,10 +1174,12 @@ function deleteV02PipelineRun(pipelineRun: string): CommandJsonResult {
|
||||
return g14K3s(["kubectl", "delete", "pipelinerun", "-n", CI_NAMESPACE, pipelineRun, "--ignore-not-found=true"], 60_000);
|
||||
}
|
||||
|
||||
function v02ControlPlaneStatus(sourceCommit: string | null = getV02CachedHead()): Record<string, unknown> {
|
||||
const pipelineRun = sourceCommit === null ? null : v02PipelineRunName(sourceCommit);
|
||||
const bundle = v02ControlPlaneStatusBundle(pipelineRun);
|
||||
function v02ControlPlaneStatus(sourceCommitInput?: string | null): Record<string, unknown> {
|
||||
const bundle = v02ControlPlaneStatusBundle(sourceCommitInput);
|
||||
const sections = parseShellSections(statusText(bundle));
|
||||
const sourceCommit = stringOrNull(sections.sourceCommit?.stdout) ?? null;
|
||||
const pipelineRun = sourceCommit === null ? null : v02PipelineRunName(sourceCommit);
|
||||
const queryNowMs = timestampMs(sections.queryNow?.stdout) ?? Date.now();
|
||||
const controlPlane = sections.controlPlane;
|
||||
const obsoleteCronJobs = sections.obsoleteCronJobs;
|
||||
const argo = sections.argo;
|
||||
@@ -1191,6 +1190,8 @@ function v02ControlPlaneStatus(sourceCommit: string | null = getV02CachedHead())
|
||||
"kubectl get pipelinerun -n hwlab-ci -l hwlab.pikastech.local/gitops-target=v02 -o jsonpath=<summary-fields>",
|
||||
sections.recentPipelineRuns?.exitCode ?? null,
|
||||
bundle.stderr,
|
||||
8,
|
||||
queryNowMs,
|
||||
);
|
||||
const activePipelineRuns = Array.isArray(recentPipelineRuns.activeItems) ? recentPipelineRuns.activeItems : [];
|
||||
const [targetRevision = "", path = "", syncRevision = "", syncStatus = "", health = ""] = String(argo?.stdout ?? "").split(/\r?\n/u);
|
||||
@@ -1252,12 +1253,12 @@ function v02ControlPlaneStatus(sourceCommit: string | null = getV02CachedHead())
|
||||
function runV02ControlPlane(options: G14ControlPlaneOptions): Record<string, unknown> {
|
||||
if (options.action === "cleanup-runs") return runControlPlaneCleanup(options);
|
||||
if (options.action === "cleanup-released-pvs") return runControlPlaneReleasedPvCleanup(options);
|
||||
const sourceCommit = options.action === "status" ? getV02CachedHead() : getV02Head();
|
||||
const sourceCommit = options.action === "status" ? undefined : getV02Head();
|
||||
if (sourceCommit === null) {
|
||||
return { ok: false, command: `hwlab g14 control-plane ${options.action} --lane v02`, degradedReason: "v02-head-unresolved", workspace: V02_WORKSPACE };
|
||||
}
|
||||
if (options.action === "runtime-migration") return runV02RuntimeMigration(options, sourceCommit);
|
||||
if (options.action === "status") return v02ControlPlaneStatus(sourceCommit);
|
||||
if (options.action === "status") return v02ControlPlaneStatus();
|
||||
if (options.action === "apply") {
|
||||
const render = runV02RenderToTemp(sourceCommit);
|
||||
if (!isCommandSuccess(render)) {
|
||||
@@ -1370,11 +1371,14 @@ function runV02ControlPlane(options: G14ControlPlaneOptions): Record<string, unk
|
||||
sourceCommit,
|
||||
pipelineRun: v02PipelineRunName(sourceCommit),
|
||||
before,
|
||||
controlPlaneRefresh,
|
||||
controlPlaneRefresh: compactControlPlaneRefresh(controlPlaneRefresh),
|
||||
gitMirrorPreSync,
|
||||
deletePipelineRun: compactCommandResult(deletePipelineRun),
|
||||
createPipelineRun: createPipelineRun === null ? null : compactCommandResult(createPipelineRun),
|
||||
deletePipelineRun: compactTriggerCommandResult(compactCommandResult(deletePipelineRun)),
|
||||
createPipelineRun: createPipelineRun === null ? null : compactTriggerCommandResult(compactCommandResult(createPipelineRun)),
|
||||
after: getPipelineRunCompact(v02PipelineRunName(sourceCommit)),
|
||||
disclosure: {
|
||||
fullTriggerOutput: "Use the async job stdout/stderr files from job status for full command details.",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1543,8 +1547,8 @@ function compactGitMirrorSync(sync: Record<string, unknown>): Record<string, unk
|
||||
namespace: sync.namespace ?? GIT_MIRROR_NAMESPACE,
|
||||
jobName: sync.jobName ?? null,
|
||||
exitCode: nested(sync, ["result", "exitCode"]) ?? null,
|
||||
stdoutTail: tailText(nested(sync, ["result", "stdout"]), 3000),
|
||||
stderrTail: tailText(nested(sync, ["result", "stderr"]), 3000),
|
||||
stdoutTail: tailText(nested(sync, ["result", "stdout"]), 1600),
|
||||
stderrTail: tailText(nested(sync, ["result", "stderr"]), 1200),
|
||||
stdoutBytes: nested(sync, ["result", "stdoutBytes"]) ?? null,
|
||||
stderrBytes: nested(sync, ["result", "stderrBytes"]) ?? null,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user