Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Merge checks: statuses and check runs on every commit | 1 | /** |
| 2 | * Words for a commit's checks, as the badge beside a commit and its list | |
| 3 | * say them (components/commit-checks.tsx). | |
| 4 | */ | |
| 5 | import type { CheckItem, CommitChecks } from "@g1t/contracts"; | |
| 6 | ||
| 7 | /** The headline over a commit's checks. */ | |
| 8 | export function checksHeadline(checks: Pick<CommitChecks, "state">): string { | |
| 9 | if (checks.state === "failure") return "Some checks were not successful"; | |
| 10 | if (checks.state === "pending") return "Some checks haven't completed yet"; | |
| 11 | if (checks.state === "none") return "No checks"; | |
| 12 | return "All checks have passed"; | |
| 13 | } | |
| 14 | ||
| 15 | /** "1 failing, 1 in progress and 2 successful checks", under the headline. */ | |
| 16 | export function checksTally(checks: Pick<CommitChecks, "successful" | "failed" | "pending" | "skipped" | "total">): string { | |
| 17 | const parts: string[] = []; | |
| 18 | if (checks.failed) parts.push(`${checks.failed} failing`); | |
| 19 | if (checks.pending) parts.push(`${checks.pending} in progress`); | |
| 20 | if (checks.skipped) parts.push(`${checks.skipped} skipped`); | |
| 21 | if (checks.successful) parts.push(`${checks.successful} successful`); | |
| 22 | const list = parts.length > 1 ? `${parts.slice(0, -1).join(", ")} and ${parts[parts.length - 1]}` : (parts[0] ?? "No"); | |
| 23 | return `${list} ${checks.total === 1 ? "check" : "checks"}`; | |
| 24 | } | |
| 25 | ||
| 26 | /** `25s`, `1m 12s` or `1h 4m` between two times; empty without both. */ | |
| 27 | export function took(start: string | null, end: string | null): string { | |
| 28 | if (!start || !end) return ""; | |
| 29 | const seconds = Math.max(0, Math.round((new Date(end).getTime() - new Date(start).getTime()) / 1000)); | |
| 30 | if (Number.isNaN(seconds)) return ""; | |
| 31 | if (seconds < 60) return `${seconds}s`; | |
| 32 | const minutes = Math.floor(seconds / 60); | |
| 33 | if (minutes < 60) return `${minutes}m ${seconds % 60}s`; | |
| 34 | return `${Math.floor(minutes / 60)}h ${minutes % 60}m`; | |
| 35 | } | |
| 36 | ||
| 37 | /** | |
| 38 | * What one check says after its name: a status's description; for a check | |
| 39 | * run, how it went and how long it took (`Successful in 25s`), then its | |
| 40 | * title. | |
| 41 | */ | |
| 42 | export function checkDetail(item: CheckItem): string { | |
| 43 | if (item.kind === "status") return item.description ?? stateWord(item); | |
| 44 | const time = took(item.startedAt, item.completedAt); | |
| 45 | let word = stateWord(item); | |
| 46 | if (time && item.state === "success") word = `Successful in ${time}`; | |
| 47 | else if (time && item.state === "failure") word = `Failing after ${time}`; | |
| 48 | return item.description ? `${word} — ${item.description}` : word; | |
| 49 | } | |
| 50 | ||
| 51 | function stateWord(item: Pick<CheckItem, "state" | "startedAt">): string { | |
| 52 | switch (item.state) { | |
| 53 | case "success": | |
| 54 | return "Successful"; | |
| 55 | case "failure": | |
| 56 | return "Failing"; | |
| 57 | case "pending": | |
| 58 | return item.startedAt ? "In progress" : "Queued"; | |
| 59 | case "cancelled": | |
| 60 | return "Cancelled"; | |
| 61 | case "skipped": | |
| 62 | return "Skipped"; | |
| 63 | default: | |
| 64 | return "Neutral"; | |
| 65 | } | |
| 66 | } | |
| 67 | ||
| 68 | /** | |
| 69 | * Where a check's Details link goes: its page on g1t when it has one (a | |
| 70 | * check run's report, or a job's run), otherwise the reporter's page. A | |
| 71 | * link to g1t itself is made a path; anything else opens apart. | |
| 72 | */ | |
| 73 | export function detailsLink(item: Pick<CheckItem, "url" | "detailsUrl">, site = "https://g1t.sh"): { href: string; external: boolean } | null { | |
| 74 | const target = item.url ?? item.detailsUrl; | |
| 75 | if (!target) return null; | |
| 76 | if (target.startsWith("/")) return { href: target, external: false }; | |
| 77 | if (target.startsWith(`${site}/`)) return { href: target.slice(site.length), external: false }; | |
| 78 | if (/^https?:\/\//.test(target)) return { href: target, external: true }; | |
| 79 | return null; | |
| 80 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.