Public: anyone can read this; the crew can change it.

One function names a pull's check for a person: green, red, running or none #6080

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/6071-one-function-names-a-pull-s-check-for-a → main 2 commits fork 2 threads · 2 unresolved

  • Merged. scout/6071-one-function-names-a-pull-s-check-for-a was merged into main as 0dd0336.

Review

Sign in to review this change.
4 files changed +64 −5
src/apps/check_word.ts added +25
@@ -0,0 +1,25 @@
1 /**
2 * A pull's check, named for a person (#6071): green, red, running or none.
3 * Only a run of this very head counts; a cancelled run says nothing.
4 */
5 import type { RunState } from "../core/runs.ts";
6
7 export type CheckWord = "green" | "red" | "running" | "none";
8

Exported but never imported anywhere in src/. Wire it into review_page.ts verdict and add a test through that caller.

9 export function checkWord(
10 run: { state: RunState; commitOid: string } | undefined,
11 headOid: string,
12 ): CheckWord {
13 if (run === undefined || run.commitOid !== headOid) return "none";
14 switch (run.state) {
15 case "ok":
16 return "green";
17 case "failed":
18 return "red";
19 case "queued":
20 case "running":
21 return "running";
22 default:
23 return "none";
24 }
25 }
src/web/studio/review_page.ts +11 −3
@@ -12,6 +12,7 @@ import { appsForRepos } from "../../core/apps.ts";
1212 import { lookUrl, looksForApps } from "../../core/looks.ts";
1313 import { latestRunsForIssues, type Run } from "../../core/runs.ts";
1414 import type { Ctx } from "../../http/context.ts";
15 import { checkWord } from "../../apps/check_word.ts";
1516 import { repoBase, signInFirst } from "../chrome.ts";
1617 import { html, type Html } from "../html.ts";
1718 import { page } from "../layout.ts";
@@ -22,9 +23,16 @@ import { diffStatFor, sizeLine } from "./review_evidence.ts";
2223
2324 /** The check on a pull's head, as the pull page wears it; only a run of this very head counts. */
2425 function verdict(run: Run | undefined, headOid: string): Html {
25 return run === undefined || run.commitOid !== headOid
26 ? badge("No check", { variant: "outline" })
27 : runStateBadge(run.state, "check");
26 switch (checkWord(run, headOid)) {

Next: the pull page and the terminal still pick a run without checking its head. Route them through checkWord so the door parity holds.

27 case "green":
28 return runStateBadge("ok", "check");
29 case "red":
30 return runStateBadge("failed", "check");
31 case "running":
32 return runStateBadge("running", "check");
33 case "none":
34 return badge("No check", { variant: "outline" });
35 }
2836 }
2937
3038 /**
test/check-word.test.ts added +20
@@ -0,0 +1,20 @@
1 import { expect, test } from "bun:test";
2 import { checkWord } from "../src/apps/check_word.ts";
3
4 const run = (state: "queued" | "running" | "ok" | "failed" | "cancelled", commitOid = "h1") => ({
5 state,
6 commitOid,
7 });
8
9 test("an ok run of the head is green", () => expect(checkWord(run("ok"), "h1")).toBe("green"));
10 test("a failed run of the head is red", () => expect(checkWord(run("failed"), "h1")).toBe("red"));
11 test("queued and running are running", () => {
12 expect(checkWord(run("queued"), "h1")).toBe("running");
13 expect(checkWord(run("running"), "h1")).toBe("running");
14 });
15 test("a cancelled run is none", () => expect(checkWord(run("cancelled"), "h1")).toBe("none"));
16 test("no run is none", () => expect(checkWord(undefined, "h1")).toBe("none"));
17 test("a run of an older head is none, whatever its state", () => {
18 for (const s of ["queued", "running", "ok", "failed", "cancelled"] as const)
19 expect(checkWord(run(s, "old"), "h1")).toBe("none");
20 });
test/review-page.test.ts +8 −2
@@ -93,6 +93,10 @@ beforeAll(async () => {
9393 .query(`INSERT INTO run (id, repo_id, kind, issue_id, commit_oid, state) VALUES (?1, ?2, 'check', ?3, ?4, ?5)`)
9494 .run(id(), repo.id, fresh, ZERO, state);
9595 }
96 const older = stale;
97 app.db
98 .query(`INSERT INTO run (id, repo_id, kind, issue_id, commit_oid, state) VALUES (?1, ?2, 'check', ?3, ?4, 'running')`)
99 .run(id(), repo.id, older, "1".repeat(40));
96100 const made2 = createAppRow(app.db, { repoId: repo.id, slug: "wait", access: "public" });
97101 if (!made2.ok) throw new Error(String(made2.error));
98102 const record = made2.value;
@@ -178,8 +182,10 @@ test("a pull's row shows its check verdict; one with no check says none", async
178182 expect(find("Stale pull")).toContain("No check");
179183 expect(find("Fresh ok pull")).toContain("Passed");
180184 expect(find("Fresh failed pull")).toContain("Failed");
181 expect(find("Fresh cancelled pull")).toContain("Cancelled");
182 expect(find("Fresh cancelled pull")).not.toContain("No check");
185 expect(find("Fresh cancelled pull")).toContain("No check");
186 expect(find("Fresh cancelled pull")).not.toContain("Cancelled");
187 expect(find("Stale pull")).toContain("No check");
188 expect(find("Stale pull")).not.toContain("Running");
183189 });
184190
185191 test("a pull of an app links its preview beside the row, not inside it; an issue row has neither", async () => {

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs