fix: add hwlab v02 closeout verdict

This commit is contained in:
Codex
2026-06-04 23:21:52 +00:00
parent b3d52b03cf
commit d513d560d9
2 changed files with 419 additions and 25 deletions
+307 -21
View File
@@ -92,7 +92,7 @@ interface G14RecordRolloutOptions {
}
interface G14ControlPlaneOptions {
action: "status" | "apply" | "trigger-current" | "cleanup-runs" | "cleanup-released-pvs" | "runtime-migration";
action: "status" | "closeout" | "apply" | "trigger-current" | "cleanup-runs" | "cleanup-released-pvs" | "runtime-migration";
lane: "v02" | "g14" | "all";
dryRun: boolean;
confirm: boolean;
@@ -193,7 +193,7 @@ interface CiPipelineMetrics {
export interface V02PrCommentInput {
pr: OpenPullRequest;
phase: string;
state: "waiting-ci" | "blocked" | "merge-failed" | "cd-started" | "cd-succeeded" | "cd-failed" | "cd-timeout" | "cd-blocked";
state: "waiting-ci" | "blocked" | "merge-failed" | "cd-started" | "cd-succeeded" | "cd-superseded" | "cd-failed" | "cd-timeout" | "cd-blocked";
startedAt: string;
observedAt: string;
elapsedSeconds: number | null;
@@ -281,13 +281,14 @@ function parseControlPlaneOptions(args: string[]): G14ControlPlaneOptions {
const actionRaw = rawAction === "rerun-current" ? "trigger-current" : rawAction;
if (
actionRaw !== "status" &&
actionRaw !== "closeout" &&
actionRaw !== "apply" &&
actionRaw !== "trigger-current" &&
actionRaw !== "cleanup-runs" &&
actionRaw !== "cleanup-released-pvs" &&
actionRaw !== "runtime-migration"
) {
throw new Error("control-plane usage: status|apply|trigger-current|runtime-migration --lane v02 | cleanup-runs --lane v02|g14|all | cleanup-released-pvs --lane all [--dry-run|--confirm]");
throw new Error("control-plane usage: status|closeout|apply|trigger-current|runtime-migration --lane v02 | cleanup-runs --lane v02|g14|all | cleanup-released-pvs --lane all [--dry-run|--confirm]");
}
const lane = optionValue(args, "--lane") ?? (actionRaw === "cleanup-released-pvs" ? "all" : "v02");
if (actionRaw === "cleanup-runs") {
@@ -295,7 +296,7 @@ function parseControlPlaneOptions(args: string[]): G14ControlPlaneOptions {
} else if (actionRaw === "cleanup-released-pvs") {
if (lane !== "all") throw new Error("control-plane cleanup-released-pvs requires --lane all because released PVs no longer preserve the v02/g14 PipelineRun lane");
} else if (lane !== "v02") {
throw new Error("control-plane status/apply/trigger-current/runtime-migration currently requires --lane v02");
throw new Error("control-plane status/closeout/apply/trigger-current/runtime-migration currently requires --lane v02");
}
const confirm = args.includes("--confirm");
const explicitDryRun = args.includes("--dry-run");
@@ -305,17 +306,20 @@ function parseControlPlaneOptions(args: string[]): G14ControlPlaneOptions {
if (allowLiveDbRead && actionRaw !== "runtime-migration") throw new Error("--allow-live-db-read is only valid for control-plane runtime-migration");
const sourceCommitRaw = optionValue(args, "--source-commit");
const pipelineRunRaw = optionValue(args, "--pipeline-run");
if ((sourceCommitRaw !== undefined || pipelineRunRaw !== undefined) && actionRaw !== "status") {
throw new Error("--source-commit and --pipeline-run are only valid for control-plane status");
if ((sourceCommitRaw !== undefined || pipelineRunRaw !== undefined) && actionRaw !== "status" && actionRaw !== "closeout") {
throw new Error("--source-commit and --pipeline-run are only valid for control-plane status/closeout");
}
if (sourceCommitRaw !== undefined && pipelineRunRaw !== undefined) throw new Error("control-plane status accepts only one of --source-commit or --pipeline-run");
if (actionRaw === "closeout" && sourceCommitRaw === undefined && pipelineRunRaw === undefined) {
throw new Error("control-plane closeout requires --source-commit <full-sha> or --pipeline-run hwlab-v02-ci-poll-<sha>");
}
if (sourceCommitRaw !== undefined && pipelineRunRaw !== undefined) throw new Error("control-plane status/closeout accepts only one of --source-commit or --pipeline-run");
return {
action: actionRaw,
lane,
confirm,
wait: args.includes("--wait"),
allowLiveDbRead,
dryRun: actionRaw === "status" ? true : explicitDryRun || !confirm,
dryRun: actionRaw === "status" || actionRaw === "closeout" ? true : explicitDryRun || !confirm,
timeoutSeconds: positiveIntegerOption(args, "--timeout-seconds", 120, 600),
minAgeMinutes: positiveIntegerOption(args, "--min-age-minutes", 60, 10080),
limit: positiveIntegerOption(args, "--limit", 20, 200),
@@ -436,6 +440,15 @@ function stringOrNull(value: unknown): string | null {
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
}
function fieldBoolean(value: unknown): boolean | null {
if (value === true || value === false) return value;
if (typeof value !== "string") return null;
const normalized = value.trim().toLowerCase();
if (normalized === "true" || normalized === "yes" || normalized === "1") return true;
if (normalized === "false" || normalized === "no" || normalized === "0") return false;
return null;
}
function nested(value: unknown, keys: string[]): unknown {
let current = value;
for (const key of keys) current = record(current)[key];
@@ -1003,7 +1016,7 @@ function v02ControlPlaneStatusBundle(target: V02ControlPlaneStatusTarget = {}):
"section statusTarget printf 'mode\\t%s\\nsourceCommit\\t%s\\npipelineRun\\t%s\\n' \"$target_mode\" \"$source_commit\" \"$pipeline_run\"",
"section sourceCommit printf '%s\\n' \"$source_commit\"",
"section pipelineRunName printf '%s\\n' \"$pipeline_run\"",
`section sourceHeads sh -c ${shellQuote(v02SourceHeadsProbeScript())}`,
`section sourceHeads sh -c ${shellQuote(v02SourceHeadsProbeScript())} sh "$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`,
@@ -1022,14 +1035,33 @@ function v02ControlPlaneStatusBundle(target: V02ControlPlaneStatusTarget = {}):
function v02SourceHeadsProbeScript(): string {
return [
"set +e",
"target_source_commit=${1:-}",
`cicd_repo=${shellQuote(V02_CICD_REPO)}`,
`workspace=${shellQuote(V02_WORKSPACE)}`,
"rev_cicd() { git --git-dir=\"$cicd_repo\" rev-parse \"$1\" 2>/dev/null || true; }",
"rev_workspace() { git -C \"$workspace\" rev-parse \"$1\" 2>/dev/null || true; }",
"origin_head=$(rev_cicd refs/remotes/origin/v0.2)",
"printf 'cicdRepo\\t%s\\n' \"$cicd_repo\"",
"printf 'cicdRepoExists\\t%s\\n' \"$([ -d \"$cicd_repo/objects\" ] && printf yes || printf no)\"",
"printf 'cicdSourceHead\\t%s\\n' \"$(rev_cicd refs/remotes/origin/v0.2)\"",
"printf 'originHead\\t%s\\n' \"$(rev_cicd refs/remotes/origin/v0.2)\"",
"printf 'cicdSourceHead\\t%s\\n' \"$origin_head\"",
"printf 'originHead\\t%s\\n' \"$origin_head\"",
"printf 'targetSourceCommit\\t%s\\n' \"$target_source_commit\"",
"target_object_exists=",
"target_ancestor=",
"target_ancestor_exit=",
"if [ -n \"$target_source_commit\" ] && git --git-dir=\"$cicd_repo\" cat-file -e \"$target_source_commit^{commit}\" 2>/dev/null; then",
" target_object_exists=true",
" if [ -n \"$origin_head\" ]; then",
" git --git-dir=\"$cicd_repo\" merge-base --is-ancestor \"$target_source_commit\" \"$origin_head\" >/dev/null 2>&1",
" target_ancestor_exit=$?",
" if [ \"$target_ancestor_exit\" = 0 ]; then target_ancestor=true; elif [ \"$target_ancestor_exit\" = 1 ]; then target_ancestor=false; else target_ancestor=unknown; fi",
" fi",
"elif [ -n \"$target_source_commit\" ]; then",
" target_object_exists=false",
"fi",
"printf 'targetObjectExists\\t%s\\n' \"$target_object_exists\"",
"printf 'targetAncestorOfOriginHead\\t%s\\n' \"$target_ancestor\"",
"printf 'targetAncestorExitCode\\t%s\\n' \"$target_ancestor_exit\"",
"printf 'workspacePath\\t%s\\n' \"$workspace\"",
"printf 'workspaceBranch\\t%s\\n' \"$(git -C \"$workspace\" rev-parse --abbrev-ref HEAD 2>/dev/null || true)\"",
"printf 'workspaceHead\\t%s\\n' \"$(rev_workspace HEAD)\"",
@@ -1387,12 +1419,21 @@ function keyValueLinesFromText(text: string): Record<string, string> {
function v02SourceHeadsFromText(text: string, commandOk: boolean, exitCode: number | null, stderr: string): Record<string, unknown> {
const fields = keyValueLinesFromText(text);
const dirtyCount = numericField(fields.workspaceDirtyCount);
const targetSourceCommit = fields.targetSourceCommit || null;
return {
ok: commandOk,
cicdRepo: fields.cicdRepo || V02_CICD_REPO,
cicdRepoExists: fields.cicdRepoExists === "yes",
cicdSourceHead: fields.cicdSourceHead || null,
originHead: fields.originHead || null,
target: {
sourceCommit: targetSourceCommit,
objectExists: fieldBoolean(fields.targetObjectExists),
ancestorOfOriginHead: fieldBoolean(fields.targetAncestorOfOriginHead),
ancestorExitCode: numericField(fields.targetAncestorExitCode),
},
targetObjectExists: fieldBoolean(fields.targetObjectExists),
targetAncestorOfOriginHead: fieldBoolean(fields.targetAncestorOfOriginHead),
workspace: {
path: fields.workspacePath || V02_WORKSPACE,
branch: fields.workspaceBranch || null,
@@ -1622,6 +1663,200 @@ export function v02LatestOnlyTargetValidation(input: {
};
}
function v02CloseoutRecommendedNext(input: {
closeable: boolean;
blockedReasons: string[];
pendingReasons: string[];
statusCommand: string;
sourceCommit: string | null;
gitMirrorSummary: Record<string, unknown>;
}): Record<string, unknown> {
const rawFlushCommand = stringOrNull(input.gitMirrorSummary.flushCommand) ?? "bun scripts/cli.ts hwlab g14 git-mirror flush --confirm";
const flushCommand = rawFlushCommand.includes("--wait") ? rawFlushCommand : `${rawFlushCommand} --wait`;
if (input.closeable) {
return {
action: "comment-and-close-issue",
command: input.sourceCommit === null
? input.statusCommand
: `bun scripts/cli.ts hwlab g14 control-plane closeout --lane v02 --source-commit ${input.sourceCommit}`,
};
}
if (input.pendingReasons.includes("git-mirror-not-flushed")) {
return { action: "flush-git-mirror", command: flushCommand };
}
if (input.pendingReasons.includes("argo-not-healthy")) {
return { action: "wait-and-recheck", command: input.statusCommand };
}
if (input.pendingReasons.includes("pipeline-run-not-final")) {
return { action: "wait-pipelinerun", command: input.statusCommand };
}
if (input.blockedReasons.includes("target-pipelinerun-missing")) {
return { action: "trigger-current-or-inspect-target", command: "bun scripts/cli.ts hwlab g14 control-plane trigger-current --lane v02 --confirm" };
}
return { action: "inspect-status", command: input.statusCommand };
}
export function v02CloseoutVerdict(status: Record<string, unknown>): Record<string, unknown> {
const statusTarget = record(status.statusTarget);
const targetMode = stringOrNull(statusTarget.mode) ?? "latest-source-head";
const sourceCommit = stringOrNull(status.sourceCommit) ?? stringOrNull(statusTarget.sourceCommit);
const pipelineRun = record(status.pipelineRun);
const targetValidation = record(status.targetValidation);
const targetValidationState = stringOrNull(targetValidation.state);
const argoFields = record(record(status.argo).fields);
const gitMirrorSummary = record(record(status.gitMirror).summary);
const sourceHeadsTarget = record(record(status.sourceHeads).target);
const commitAlignment = record(status.commitAlignment);
const latestHead = stringOrNull(commitAlignment.originHead) ?? stringOrNull(record(status.sourceHeads).originHead);
const ancestorOfLatest = sourceHeadsTarget.ancestorOfOriginHead ?? status.sourceHeadsTargetAncestorOfOriginHead ?? null;
const activePipelineRuns = Array.isArray(status.activePipelineRuns)
? status.activePipelineRuns.map((item) => record(item))
: [];
const pipelineStatus = stringOrNull(pipelineRun.status);
const pipelineExists = pipelineRun.exists !== false && Object.keys(pipelineRun).length > 0;
const pendingReasons: string[] = [];
const blockedReasons: string[] = [];
if (targetMode === "latest-source-head") {
pendingReasons.push("target-not-explicit");
}
if (!pipelineExists) {
blockedReasons.push("target-pipelinerun-missing");
} else if (pipelineStatus === "Unknown" || pipelineStatus === null) {
pendingReasons.push("pipeline-run-not-final");
} else if (pipelineStatus === "False") {
blockedReasons.push("pipeline-run-failed");
}
if (targetValidationState !== "passed" && targetValidationState !== "superseded") {
const failures = Array.isArray(targetValidation.failures) ? targetValidation.failures.map((item) => record(item)) : [];
for (const failure of failures) {
const reason = stringOrNull(failure.reason);
if (reason === "git-mirror-not-flushed") pendingReasons.push(reason);
else if (reason === "argo-not-synced-healthy") pendingReasons.push("argo-not-healthy");
else if (reason === "pipeline-run-not-succeeded" && pipelineStatus === "Unknown") pendingReasons.push("pipeline-run-not-final");
else if (reason !== null) blockedReasons.push(reason);
}
if (failures.length === 0 && targetMode !== "latest-source-head") blockedReasons.push("target-validation-not-passed");
}
if (gitMirrorSummary.pendingFlush !== false || gitMirrorSummary.githubInSync !== true) {
pendingReasons.push("git-mirror-not-flushed");
}
if (argoFields.syncStatus !== "Synced" || argoFields.health !== "Healthy") {
pendingReasons.push("argo-not-healthy");
}
if (targetValidationState === "superseded" && ancestorOfLatest !== true) {
if (ancestorOfLatest === false) blockedReasons.push("target-not-ancestor-of-latest-head");
else pendingReasons.push("ancestor-check-unresolved");
}
const uniquePendingReasons = Array.from(new Set(pendingReasons));
const uniqueBlockedReasons = Array.from(new Set(blockedReasons));
const terminalState = targetValidationState === "passed" || targetValidationState === "superseded";
const state = uniqueBlockedReasons.length > 0
? "blocked"
: uniquePendingReasons.length > 0
? "pending"
: terminalState
? targetValidationState
: "blocked";
const closeable = (state === "passed" || state === "superseded") && uniquePendingReasons.length === 0 && uniqueBlockedReasons.length === 0;
const rawStatusCommand = String(status.command ?? (
sourceCommit === null
? "bun scripts/cli.ts hwlab g14 control-plane status --lane v02"
: `bun scripts/cli.ts hwlab g14 control-plane status --lane v02 --source-commit ${sourceCommit}`
));
const statusCommand = rawStatusCommand.startsWith("bun ") ? rawStatusCommand : `bun scripts/cli.ts ${rawStatusCommand}`;
const ancestorCheck = {
required: state === "superseded",
sourceCommit,
latestHead,
objectExists: sourceHeadsTarget.objectExists ?? null,
ancestorOfLatest,
exitCode: sourceHeadsTarget.ancestorExitCode ?? null,
command: sourceCommit === null
? null
: `trans G14:/root/hwlab-v02 script -- 'git fetch origin v0.2 && git merge-base --is-ancestor ${sourceCommit} origin/v0.2'`,
};
const recommendedNext = v02CloseoutRecommendedNext({
closeable,
blockedReasons: uniqueBlockedReasons,
pendingReasons: uniquePendingReasons,
statusCommand,
sourceCommit,
gitMirrorSummary,
});
const summary = closeable
? state === "superseded"
? `closeout ready: target ${shortSha(sourceCommit ?? "")} passed and is superseded by latest v0.2 head ${shortSha(latestHead ?? "")}`
: `closeout ready: target ${shortSha(sourceCommit ?? "")} passed on v0.2`
: uniquePendingReasons.length > 0
? `closeout pending: ${uniquePendingReasons.join(",")}`
: `closeout blocked: ${uniqueBlockedReasons.join(",") || "unknown"}`;
const issueCommentMarkdown = [
`v0.2 closeout verdict: \`${state}\` (${summary})`,
"",
`- target sourceCommit: \`${sourceCommit ?? "n/a"}\``,
`- target PipelineRun: \`${String(pipelineRun.pipelineRun ?? pipelineRun.name ?? statusTarget.pipelineRun ?? "n/a")}\`; status=\`${pipelineStatus ?? "n/a"}\`; reason=\`${String(pipelineRun.reason ?? "n/a")}\``,
`- latest head: \`${latestHead ?? "n/a"}\`; ancestorOfLatest=\`${String(ancestorCheck.ancestorOfLatest ?? "n/a")}\``,
`- targetValidation: \`${targetValidationState ?? "n/a"}\`; pending=\`${uniquePendingReasons.join(",") || "none"}\`; blocked=\`${uniqueBlockedReasons.join(",") || "none"}\``,
`- Git mirror: pendingFlush=\`${String(gitMirrorSummary.pendingFlush ?? "n/a")}\`, githubInSync=\`${String(gitMirrorSummary.githubInSync ?? "n/a")}\`, flushCommand=\`${String(gitMirrorSummary.flushCommand ?? "none")}\``,
`- Argo: sync=\`${String(argoFields.syncStatus ?? "n/a")}\`, health=\`${String(argoFields.health ?? "n/a")}\`, revision=\`${String(argoFields.syncRevision ?? "n/a")}\``,
`- active v0.2 PipelineRuns: \`${activePipelineRuns.length}\``,
`- recommended next: \`${String(recommendedNext.action ?? "inspect-status")}\` -> \`${String(recommendedNext.command ?? statusCommand)}\``,
].join("\n");
return {
ok: closeable,
closeable,
state,
summary,
targetMode,
sourceCommit,
latestHead,
pipelineRun: {
name: pipelineRun.pipelineRun ?? pipelineRun.name ?? statusTarget.pipelineRun ?? null,
exists: pipelineExists,
status: pipelineStatus,
reason: pipelineRun.reason ?? null,
},
targetValidation: {
state: targetValidationState,
ok: targetValidation.ok ?? null,
failures: Array.isArray(targetValidation.failures) ? targetValidation.failures.slice(0, 10) : [],
},
latestOnly: {
superseded: targetValidation.latestOnlySuperseded === true || state === "superseded",
reasons: stringArray(targetValidation.latestOnlyReasons),
ancestorCheck,
},
gitMirror: {
pendingFlush: gitMirrorSummary.pendingFlush ?? null,
githubInSync: gitMirrorSummary.githubInSync ?? null,
flushNeeded: gitMirrorSummary.flushNeeded ?? null,
flushCommand: gitMirrorSummary.flushCommand ?? null,
lastSync: gitMirrorSummary.lastSync ?? null,
lastWrite: gitMirrorSummary.lastWrite ?? null,
lastFlush: gitMirrorSummary.lastFlush ?? null,
},
argo: {
syncStatus: argoFields.syncStatus ?? null,
health: argoFields.health ?? null,
syncRevision: argoFields.syncRevision ?? null,
targetRevision: argoFields.targetRevision ?? null,
path: argoFields.path ?? null,
},
runtime: {
webAssetsOk: nested(status, ["webAssets", "ok"]) ?? null,
webAssetsSummary: nested(status, ["webAssets", "summary"]) ?? null,
apiRevision: nested(status, ["webAssets", "apiRevision"]) ?? nested(status, ["commitAlignment", "apiRevision"]) ?? null,
serviceSourceCommits: nested(status, ["commitAlignment", "serviceSourceCommits"]) ?? null,
},
activePipelineRuns,
recentPipelineRuns: status.recentPipelineRuns ?? null,
pendingReasons: uniquePendingReasons,
blockedReasons: uniqueBlockedReasons,
recommendedNext,
issueCommentMarkdown,
};
}
export function v02CommitAlignment(input: {
expectedSourceHead: string | null;
sourceHeads: Record<string, unknown>;
@@ -2533,6 +2768,7 @@ function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): Record
commitAlignment,
targetValidation: targetValidationBase,
});
const sourceHeadsTarget = record(sourceHeads.target);
const falseGreenGuard = targetValidation.state === "superseded"
? {
ok: null,
@@ -2560,7 +2796,7 @@ function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): Record
: targetMode === "source-commit"
? "explicit --source-commit"
: "G14 CI/CD dedicated bare repo refs/remotes/origin/v0.2; workspace checkout is observable but isolated";
return {
const status: Record<string, unknown> = {
ok: baseOk && targetPipelineRunOk && (!strictHeadAlignment || commitAlignment.aligned !== false),
command: statusCommand,
lane: "v02",
@@ -2571,6 +2807,7 @@ function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): Record
sourceCommit,
pipelineRun,
strictHeadAlignment,
ancestorOfLatest: sourceHeadsTarget.ancestorOfOriginHead ?? null,
note: strictHeadAlignment
? "default status validates the latest v0.2 source head alignment"
: "targeted status inspects the requested PipelineRun/source commit without failing merely because origin/v0.2 advanced later",
@@ -2591,6 +2828,7 @@ function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): Record
commitAlignment,
targetValidation,
sourceHeads,
sourceHeadsTargetAncestorOfOriginHead: sourceHeadsTarget.ancestorOfOriginHead ?? null,
gitMirror,
controlPlane: {
ok: shellSectionOk(controlPlane),
@@ -2626,13 +2864,29 @@ function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): Record
? "activePipelineRuns shows running v02 CI even when origin/v0.2 advanced after a previous trigger"
: "no active v02 PipelineRun observed",
};
return {
...status,
closeout: v02CloseoutVerdict(status),
};
}
function runV02ControlPlane(options: G14ControlPlaneOptions): Record<string, unknown> {
if (options.action === "cleanup-runs") return runControlPlaneCleanup(options);
if (options.action === "cleanup-released-pvs") return runControlPlaneReleasedPvCleanup(options);
if (options.action === "status" && options.pipelineRun !== undefined) return v02ControlPlaneStatus({ pipelineRun: options.pipelineRun, mode: "pipeline-run" });
if (options.action === "status" && options.sourceCommit !== undefined) return v02ControlPlaneStatus({ sourceCommit: options.sourceCommit, mode: "source-commit" });
if ((options.action === "status" || options.action === "closeout") && options.pipelineRun !== undefined) {
const status = v02ControlPlaneStatus({ pipelineRun: options.pipelineRun, mode: "pipeline-run" });
if (options.action === "closeout") return v02ControlPlaneCloseout(status);
return status;
}
if ((options.action === "status" || options.action === "closeout") && options.sourceCommit !== undefined) {
const status = v02ControlPlaneStatus({ sourceCommit: options.sourceCommit, mode: "source-commit" });
if (options.action === "closeout") return v02ControlPlaneCloseout(status);
return status;
}
if (options.action === "closeout") {
const status = v02ControlPlaneStatus();
return v02ControlPlaneCloseout(status);
}
const snapshot = options.action === "trigger-current" ? getV02TriggerSnapshot() : null;
const latestHead = options.action === "trigger-current" ? resolveV02LatestRemoteHead() : null;
const head = snapshot === null
@@ -4760,7 +5014,7 @@ function v02PrConflictState(summary: Record<string, unknown>): string {
return "clear-or-unknown";
}
function summarizeV02CdStatus(status: Record<string, unknown>): Record<string, unknown> {
export function summarizeV02CdStatus(status: Record<string, unknown>): Record<string, unknown> {
const pipelineRun = record(status.pipelineRun);
const targetValidation = record(status.targetValidation);
const gitMirror = record(status.gitMirror);
@@ -4779,8 +5033,8 @@ function summarizeV02CdStatus(status: Record<string, unknown>): Record<string, u
targetValidationOk: targetValidation.ok ?? null,
targetValidationFailures: Array.isArray(targetValidation.failures) ? targetValidation.failures.slice(0, 10) : [],
targetValidationWarnings: Array.isArray(targetValidation.warnings) ? targetValidation.warnings.slice(0, 10) : [],
argoSync: argo.syncStatus ?? nested(argo, ["summary", "syncStatus"]) ?? null,
argoHealth: argo.healthStatus ?? nested(argo, ["summary", "healthStatus"]) ?? null,
argoSync: nested(argo, ["fields", "syncStatus"]) ?? argo.syncStatus ?? nested(argo, ["summary", "syncStatus"]) ?? null,
argoHealth: nested(argo, ["fields", "health"]) ?? argo.healthStatus ?? nested(argo, ["summary", "healthStatus"]) ?? null,
webAssetsOk: webAssets.ok ?? null,
pendingFlush: gitMirrorSummary.pendingFlush ?? null,
githubInSync: gitMirrorSummary.githubInSync ?? null,
@@ -4795,6 +5049,33 @@ function v02CdPassed(status: Record<string, unknown>): boolean {
return state === "passed" || state === "superseded";
}
function v02ControlPlaneCloseout(status: Record<string, unknown>): Record<string, unknown> {
const closeout = record(status.closeout);
const sourceCommit = stringOrNull(status.sourceCommit);
const pipelineRun = stringOrNull(nested(status, ["statusTarget", "pipelineRun"])) ?? stringOrNull(nested(status, ["pipelineRun", "pipelineRun"]));
const command = sourceCommit !== null
? `hwlab g14 control-plane closeout --lane v02 --source-commit ${sourceCommit}`
: pipelineRun !== null
? `hwlab g14 control-plane closeout --lane v02 --pipeline-run ${pipelineRun}`
: "hwlab g14 control-plane closeout --lane v02";
return {
ok: closeout.closeable === true,
command,
lane: "v02",
closeout,
target: status.statusTarget ?? null,
sourceCommit: status.sourceCommit ?? null,
pipelineRun: status.pipelineRun ?? null,
targetValidation: status.targetValidation ?? null,
latestHead: nested(status, ["commitAlignment", "originHead"]) ?? nested(status, ["sourceHeads", "originHead"]) ?? null,
gitMirror: record(record(status.gitMirror).summary),
argo: record(status.argo).fields ?? null,
activePipelineRuns: status.activePipelineRuns ?? [],
recommendedNext: closeout.recommendedNext ?? null,
issueCommentMarkdown: closeout.issueCommentMarkdown ?? null,
};
}
function v02PipelineSucceeded(status: Record<string, unknown>): boolean {
return String(nested(status, ["pipelineRun", "status"]) ?? "") === "True";
}
@@ -4804,9 +5085,12 @@ function v02CdFailed(status: Record<string, unknown>): boolean {
return pipelineStatus === "False";
}
function activeV02PipelineRuns(status: Record<string, unknown>): Record<string, unknown>[] {
const active = record(status.activePipelineRuns);
const items = Array.isArray(active.items) ? active.items : [];
export function activeV02PipelineRuns(status: Record<string, unknown>): Record<string, unknown>[] {
const items = Array.isArray(status.activePipelineRuns)
? status.activePipelineRuns
: Array.isArray(record(status.activePipelineRuns).items)
? record(status.activePipelineRuns).items
: [];
return items.map((item) => record(item)).filter((item) => String(item.status ?? "") === "Unknown");
}
@@ -5352,6 +5636,8 @@ export function hwlabG14Help(): Record<string, unknown> {
"bun scripts/cli.ts hwlab g14 control-plane status --lane v02",
"bun scripts/cli.ts hwlab g14 control-plane status --lane v02 --pipeline-run hwlab-v02-ci-poll-<short-sha>",
"bun scripts/cli.ts hwlab g14 control-plane status --lane v02 --source-commit <full-sha>",
"bun scripts/cli.ts hwlab g14 control-plane closeout --lane v02 --pipeline-run hwlab-v02-ci-poll-<short-sha>",
"bun scripts/cli.ts hwlab g14 control-plane closeout --lane v02 --source-commit <full-sha>",
"bun scripts/cli.ts hwlab g14 control-plane apply --lane v02 --dry-run",
"bun scripts/cli.ts hwlab g14 control-plane apply --lane v02 --confirm",
"bun scripts/cli.ts hwlab g14 control-plane trigger-current --lane v02 --confirm",
@@ -5376,7 +5662,7 @@ export function hwlabG14Help(): Record<string, unknown> {
"bun scripts/cli.ts hwlab g14 tools-image build --name ci-node-tools --tag node22-alpine-bun-v1 --confirm",
"bun scripts/cli.ts job status <jobId> --tail-bytes 30000",
],
description: "G14 HWLAB PR monitor, DEV rollout command, bounded v0.2 control-plane bootstrap/cleanup/runtime-migration helper, v0.2 runtime SecretRef bootstrap, devops-infra git mirror maintenance, and controlled CI tools image build/status entry. The public monitor starts a fire-and-forget job. Default monitor lane is base=G14; --lane v02 monitors base=v0.2 PRs, waits for GitHub preflight/CI readiness, automatically merges ready PRs without waiting for other active v0.2 PipelineRuns, triggers v0.2 CD with latest-only GitOps writeback, flushes the git mirror when needed, and posts deduplicated PR comments for pending, blocked/conflict, success, superseded, failure, or timeout states. confirmed control-plane trigger-current and git-mirror sync/flush also return async jobs by default, with --wait reserved for explicit synchronous debugging. control-plane status/apply/cleanup-runs/cleanup-released-pvs/runtime-migration uses UniDesk G14:k3s routes for v0.2 Tekton/Argo control resources, runtime migration, and completed CI workspace retention only. secret status/ensure is the standard v0.2 runtime SecretRef bootstrap path; it never reads or prints secret values. git-mirror status/apply/sync/flush is the manual devops-infra mirror/relay control path and does not install a CronJob.",
description: "G14 HWLAB PR monitor, DEV rollout command, bounded v0.2 control-plane bootstrap/cleanup/runtime-migration helper, v0.2 runtime SecretRef bootstrap, devops-infra git mirror maintenance, and controlled CI tools image build/status entry. The public monitor starts a fire-and-forget job. Default monitor lane is base=G14; --lane v02 monitors base=v0.2 PRs, waits for GitHub preflight/CI readiness, automatically merges ready PRs without waiting for other active v0.2 PipelineRuns, triggers v0.2 CD with latest-only GitOps writeback, flushes the git mirror when needed, and posts deduplicated PR comments for pending, blocked/conflict, success, superseded, failure, or timeout states. confirmed control-plane trigger-current and git-mirror sync/flush also return async jobs by default, with --wait reserved for explicit synchronous debugging. control-plane status/closeout/apply/cleanup-runs/cleanup-released-pvs/runtime-migration uses UniDesk G14:k3s routes for v0.2 Tekton/Argo control resources, runtime migration, historical PipelineRun/source-commit closeout verdicts, GitOps mirror flush state, and completed CI workspace retention only. secret status/ensure is the standard v0.2 runtime SecretRef bootstrap path; it never reads or prints secret values. git-mirror status/apply/sync/flush is the manual devops-infra mirror/relay control path and does not install a CronJob.",
defaults: {
repo: HWLAB_REPO,
base: G14_SOURCE_BRANCH,