fix: render gh preflight as table
This commit is contained in:
@@ -290,6 +290,11 @@ async function main(): Promise<void> {
|
|||||||
if (top === "gh") {
|
if (top === "gh") {
|
||||||
const result = await runGhCommand(args.slice(1));
|
const result = await runGhCommand(args.slice(1));
|
||||||
const ok = (result as { ok?: unknown }).ok !== false;
|
const ok = (result as { ok?: unknown }).ok !== false;
|
||||||
|
if (isRenderedCliResult(result)) {
|
||||||
|
emitText(result.renderedText, result.command || commandName);
|
||||||
|
if (!ok) process.exitCode = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
emitJson(commandName, result, ok);
|
emitJson(commandName, result, ok);
|
||||||
if (!ok) process.exitCode = 1;
|
if (!ok) process.exitCode = 1;
|
||||||
return;
|
return;
|
||||||
|
|||||||
+68
-1
@@ -5230,7 +5230,7 @@ async function prPreflight(repo: string, number: number, commandName: "preflight
|
|||||||
const metadataSummary = prMetadataSummary(metadata);
|
const metadataSummary = prMetadataSummary(metadata);
|
||||||
const statusChecks = statusRollupSummary(repo, number, metadata.statusCheckRollup, includeRaw);
|
const statusChecks = statusRollupSummary(repo, number, metadata.statusCheckRollup, includeRaw);
|
||||||
const closeout = prCloseoutSummary(summary, metadataSummary, statusChecks);
|
const closeout = prCloseoutSummary(summary, metadataSummary, statusChecks);
|
||||||
return {
|
const result: GitHubCommandResult = {
|
||||||
ok: true,
|
ok: true,
|
||||||
command: commandName,
|
command: commandName,
|
||||||
canonicalCommand: `bun scripts/cli.ts gh pr preflight ${number} --repo ${repo}`,
|
canonicalCommand: `bun scripts/cli.ts gh pr preflight ${number} --repo ${repo}`,
|
||||||
@@ -5251,6 +5251,73 @@ async function prPreflight(repo: string, number: number, commandName: "preflight
|
|||||||
policy,
|
policy,
|
||||||
...(includeRaw ? { raw: { authStatus: auth, pullRequest, closeoutMetadata: metadataSummary } } : {}),
|
...(includeRaw ? { raw: { authStatus: auth, pullRequest, closeoutMetadata: metadataSummary } } : {}),
|
||||||
};
|
};
|
||||||
|
if (includeRaw) return result;
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
contentType: "text/plain",
|
||||||
|
renderedText: renderPrPreflightTable(result),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPrPreflightTable(result: GitHubCommandResult): string {
|
||||||
|
const pullRequest = isRecord(result.pullRequest) ? result.pullRequest : {};
|
||||||
|
const mergeability = isRecord(result.mergeability) ? result.mergeability : {};
|
||||||
|
const statusChecks = isRecord(result.statusChecks) ? result.statusChecks : {};
|
||||||
|
const counts = isRecord(statusChecks.counts) ? statusChecks.counts : {};
|
||||||
|
const policy = isRecord(result.policy) ? result.policy : {};
|
||||||
|
const blockers = Array.isArray(mergeability.blockers) ? mergeability.blockers.map(String) : [];
|
||||||
|
const pending = Array.isArray(mergeability.pending) ? mergeability.pending.map(String) : [];
|
||||||
|
const conclusion = ghText(mergeability.conclusion);
|
||||||
|
const rows = [[
|
||||||
|
`#${ghText(result.number)}`,
|
||||||
|
ghText(pullRequest.stateDetail ?? pullRequest.state),
|
||||||
|
ghText(mergeability.mergeable),
|
||||||
|
ghText(mergeability.mergeStateStatus),
|
||||||
|
`${ghText(statusChecks.totalContexts)} total ${ghText(counts.success)} ok ${ghText(counts.failure)} fail ${ghText(counts.pending)} pending`,
|
||||||
|
conclusion,
|
||||||
|
]];
|
||||||
|
const lines = [
|
||||||
|
`gh pr preflight (${conclusion})`,
|
||||||
|
"",
|
||||||
|
ghTable(["PR", "STATE", "MERGEABLE", "MERGE_STATE", "CHECKS", "CONCLUSION"], rows),
|
||||||
|
"",
|
||||||
|
"Summary:",
|
||||||
|
` repo=${ghText(result.repo)} title=${ghShort(ghText(pullRequest.title), 96)}`,
|
||||||
|
` head=${ghText(isRecord(pullRequest.head) ? pullRequest.head.ref : null)} base=${ghText(isRecord(pullRequest.base) ? pullRequest.base.ref : null)}`,
|
||||||
|
` blockers=${blockers.length === 0 ? "-" : blockers.join(",")} pending=${pending.length === 0 ? "-" : pending.join(",")}`,
|
||||||
|
"",
|
||||||
|
"Next:",
|
||||||
|
];
|
||||||
|
const mergeCommand = ghText(policy.mergeCommand);
|
||||||
|
if (mergeability.readyForCommanderMerge === true && mergeCommand !== "-") {
|
||||||
|
lines.push(` ${mergeCommand}`);
|
||||||
|
}
|
||||||
|
lines.push(` bun scripts/cli.ts gh pr preflight ${ghText(result.number)} --repo ${ghText(result.repo)} --full`);
|
||||||
|
lines.push("", "Disclosure:");
|
||||||
|
lines.push(" default view is a bounded table; use --full or --raw for structured PR/check metadata.");
|
||||||
|
return lines.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function ghTable(headers: string[], rows: string[][]): string {
|
||||||
|
const normalizedRows = rows.map((row) => headers.map((_, index) => row[index] ?? ""));
|
||||||
|
const widths = headers.map((header, index) => Math.max(header.length, ...normalizedRows.map((row) => row[index].length)));
|
||||||
|
return [
|
||||||
|
headers.map((header, index) => header.padEnd(widths[index])).join(" ").trimEnd(),
|
||||||
|
...normalizedRows.map((row) => row.map((cell, index) => cell.padEnd(widths[index])).join(" ").trimEnd()),
|
||||||
|
].join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function ghText(value: unknown): string {
|
||||||
|
if (value === null || value === undefined || value === "") return "-";
|
||||||
|
if (typeof value === "string") return value;
|
||||||
|
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
||||||
|
return JSON.stringify(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ghShort(value: string, maxLength: number): string {
|
||||||
|
if (value.length <= maxLength) return value;
|
||||||
|
if (maxLength <= 1) return value.slice(0, maxLength);
|
||||||
|
return `${value.slice(0, maxLength - 1)}~`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function repoSummary(repo: GitHubRepository): Record<string, unknown> {
|
function repoSummary(repo: GitHubRepository): Record<string, unknown> {
|
||||||
|
|||||||
Reference in New Issue
Block a user