cli/src/commands/ci-status.tsblame
View source
59e66671import { spinner, log, note } from "@clack/prompts";
69d1a722import { hubRequest } from "../api.js";
69d1a723import { getRepoSlug } from "../config.js";
0d9d7234import { STATUS_COLORS, STATUS_ICONS, RESET, formatDurationRange } from "../format.js";
69d1a725
69d1a726interface PipelineRun {
69d1a727 id: number;
69d1a728 pipeline_name: string;
69d1a729 status: string;
69d1a7210 trigger_ref: string | null;
69d1a7211 commit_id: string | null;
69d1a7212 started_at: string | null;
69d1a7213 finished_at: string | null;
69d1a7214 duration_ms: number | null;
69d1a7215}
69d1a7216
69d1a7217interface PipelineStep {
69d1a7218 id: number;
69d1a7219 name: string;
69d1a7220 image: string;
69d1a7221 status: string;
69d1a7222 started_at: string | null;
69d1a7223 finished_at: string | null;
69d1a7224 step_index: number;
69d1a7225}
69d1a7226
69d1a7227export async function ciStatus(args: string[]) {
69d1a7228 const slug = await getRepoSlug(args);
69d1a7229
69d1a7230 // Find run ID: first positional arg that's a number
69d1a7231 let runId = args.find((a) => !a.startsWith("--") && /^\d+$/.test(a));
69d1a7232
69d1a7233 if (!runId) {
69d1a7234 // Get latest run
59e666735 const s = spinner();
59e666736 s.start("Fetching latest run");
69d1a7237 const { runs } = await hubRequest<{ runs: any[] }>(
69d1a7238 `/api/repos/${slug}/canopy/runs?limit=1`
69d1a7239 );
69d1a7240 if (runs.length === 0) {
59e666741 s.stop("No runs found");
59e666742 log.info("No pipeline runs.");
69d1a7243 return;
69d1a7244 }
69d1a7245 runId = String(runs[0].id);
59e666746 s.stop(`Run #${runId}`);
69d1a7247 }
69d1a7248
59e666749 const s2 = spinner();
59e666750 s2.start(`Fetching run #${runId}`);
69d1a7251 const { run, steps } = await hubRequest<{ run: PipelineRun; steps: PipelineStep[] }>(
69d1a7252 `/api/repos/${slug}/canopy/runs/${runId}`
69d1a7253 );
59e666754 s2.stop(`${run.pipeline_name}`);
69d1a7255
69d1a7256 // Header
69d1a7257 const color = STATUS_COLORS[run.status] ?? "";
59e666758 const headerLines = [
59e666759 `Run #${run.id} ${color}${run.status}${RESET} branch: ${run.trigger_ref ?? "-"}`,
59e666760 ];
59e666761 if (run.commit_id) headerLines.push(`Commit: ${run.commit_id.slice(0, 12)}`);
59e666762 note(headerLines.join("\n"), run.pipeline_name);
69d1a7263
69d1a7264 // Steps
69d1a7265 for (const step of steps) {
69d1a7266 const icon = STATUS_ICONS[step.status] ?? "?";
0d9d72367 const dur = formatDurationRange(step.started_at, step.finished_at);
69d1a7268 const durStr = dur ? ` (${dur})` : "";
59e666769 log.message(`${icon} ${step.step_index}. ${step.name}${durStr}`);
69d1a7270 }
69d1a7271}