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

A pure read counts the open pulls whose check is red, and those queued for a check, as two flow numbers #6431

Merged opened this

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

Merged

scout/forge:scout/6423-a-pure-read-counts-the-open-pulls-whose → main 1 commit fork

  • Merged. scout/6423-a-pure-read-counts-the-open-pulls-whose was merged into main as e8dd002.

Review

Sign in to review this change.
2 files changed +142 −0
src/flow/checks_pile.ts added +30
@@ -0,0 +1,30 @@
1 /**
2 * Open pulls whose check is red, and those with a check waiting for a slot
3 * (#5930). Read from the same check runs the pulls list words its status
4 * from: only a run of the pull's current head counts, newest first.
5 */
6
7 import type { Database } from "bun:sqlite";
8
9 export interface ChecksPile {
10 /** Open, unmerged pulls whose latest check on the current head failed. */
11 readonly red: number;
12 /** Open, unmerged pulls with a check on the current head queued for a slot. */
13 readonly queued: number;
14 }
15
16 /** `publicOnly` counts public repositories alone, as `readVitals` does. */
17 export function readChecksPile(db: Database, publicOnly = false): ChecksPile {
18 const row = db
19 .query<{ red: number | null; queued: number | null }, [number]>(
20 `SELECT SUM(latest = 'failed') AS red, SUM(waiting) AS queued FROM (
21 SELECT (SELECT c.state FROM run c WHERE c.kind = 'check' AND c.issue_id = i.id
22 AND c.commit_oid = p.head_oid ORDER BY c.id DESC LIMIT 1) AS latest,
23 EXISTS (SELECT 1 FROM run c WHERE c.kind = 'check' AND c.issue_id = i.id
24 AND c.commit_oid = p.head_oid AND c.state = 'queued') AS waiting
25 FROM issue i JOIN pull p ON p.issue_id = i.id JOIN repo r ON r.id = i.repo_id
26 WHERE i.state = 'open' AND p.merged_at IS NULL AND (?1 = 0 OR r.visibility = 'public'))`,
27 )
28 .get(publicOnly ? 1 : 0);
29 return { red: row?.red ?? 0, queued: row?.queued ?? 0 };
30 }
test/flow-checks-pile.test.ts added +112
@@ -0,0 +1,112 @@
1 /** The checks pile (#5930): open pulls red on their current head, and those with a check queued. */
2 import { afterAll, beforeAll, describe, expect, test } from "bun:test";
3 import { mkdtempSync, rmSync } from "node:fs";
4 import { tmpdir } from "node:os";
5 import { join } from "node:path";
6 import { createApp, type App } from "../src/app.ts";
7 import { createRepo } from "../src/core/repos.ts";
8 import { createUser } from "../src/core/users.ts";
9 import { id } from "../src/kernel/id.ts";
10 import { readChecksPile } from "../src/flow/checks_pile.ts";
11
12 let root: string;
13 let app: App;
14 let ownerId: string;
15 let pub: string;
16 let priv: string;
17 let n = 0;
18 let seq = 0;
19
20 beforeAll(async () => {
21 root = mkdtempSync(join(tmpdir(), "forge-checks-pile-"));
22 app = createApp({ dataDir: root, port: 0 });
23 const made = await createUser(app.db, { username: "trevato", email: "[email protected]", password: "a-good-passphrase", origin: "seed", trusted: true, adminIfFirst: true });
24 if (!made.ok) throw new Error(made.error);
25 ownerId = made.value.id;
26 for (const [name, visibility] of [["open", "public"], ["secret", "private"]] as const) {
27 const repo = await createRepo(app.db, app.reposRoot, { ownerId, name, visibility, description: "r" });
28 if (!repo.ok) throw new Error(repo.error);
29 if (name === "open") pub = repo.value.id;
30 else priv = repo.value.id;
31 }
32 });
33 afterAll(() => {
34 app.close();
35 rmSync(root, { recursive: true, force: true });
36 });
37
38 function pull(repoId: string, head: string, opts: { merged?: boolean } = {}): string {
39 const issue = id();
40 app.db
41 .query(`INSERT INTO issue (id, repo_id, number, kind, title, body, author_id, state) VALUES (?1, ?2, ?3, 'pull', 't', '', ?4, ?5)`)
42 .run(issue, repoId, ++n, ownerId, opts.merged ? "closed" : "open");
43 app.db
44 .query(`INSERT INTO pull (issue_id, base_branch, head_branch, base_oid, head_oid, head_repo_id, merged_at) VALUES (?1, 'main', 'b', '', ?2, ?3, ?4)`)
45 .run(issue, head, repoId, opts.merged ? "2026-10-26T00:00:00.000Z" : null);
46 return issue;
47 }
48 function check(repoId: string, issue: string, oid: string, state: string): void {
49 app.db
50 .query(`INSERT INTO run (id, repo_id, kind, issue_id, commit_oid, state) VALUES (?1, ?2, 'check', ?3, ?4, ?5)`)
51 .run(`${String(++seq).padStart(4, "0")}${id()}`, repoId, issue, oid, state);
52 }
53 const clear = (): void => {
54 app.db.query(`DELETE FROM run`).run();
55 app.db.query(`DELETE FROM pull`).run();
56 app.db.query(`DELETE FROM issue`).run();
57 };
58
59 describe("checks pile", () => {
60 test("nothing yet reads zero", () => {
61 expect(readChecksPile(app.db)).toEqual({ red: 0, queued: 0 });
62 });
63
64 test("a red pull counts; red on an older head, green on the current, does not", () => {
65 clear();
66 const a = pull(pub, "h1");
67 check(pub, a, "h1", "failed");
68 const b = pull(pub, "h2");
69 check(pub, b, "h1", "failed");
70 check(pub, b, "h2", "ok");
71 expect(readChecksPile(app.db)).toEqual({ red: 1, queued: 0 });
72 });
73
74 test("a red run on the old head does not count when the current head has none", () => {
75 clear();
76 check(pub, pull(pub, "h2"), "h1", "failed");
77 expect(readChecksPile(app.db).red).toBe(0);
78 });
79
80 test("a later green on the same head clears red", () => {
81 clear();
82 const a = pull(pub, "h1");
83 check(pub, a, "h1", "failed");
84 check(pub, a, "h1", "ok");
85 expect(readChecksPile(app.db).red).toBe(0);
86 });
87
88 test("a merged pull is not counted", () => {
89 clear();
90 const a = pull(pub, "h1", { merged: true });
91 check(pub, a, "h1", "failed");
92 check(pub, a, "h1", "queued");
93 expect(readChecksPile(app.db)).toEqual({ red: 0, queued: 0 });
94 });
95
96 test("a queued check is counted once, even with two queued", () => {
97 clear();
98 const a = pull(pub, "h1");
99 check(pub, a, "h1", "queued");
100 check(pub, a, "h1", "queued");
101 expect(readChecksPile(app.db)).toEqual({ red: 0, queued: 1 });
102 });
103
104 test("publicOnly hides private repositories", () => {
105 clear();
106 check(priv, pull(priv, "p1"), "p1", "failed");
107 check(priv, pull(priv, "p2"), "p2", "queued");
108 check(pub, pull(pub, "h1"), "h1", "failed");
109 expect(readChecksPile(app.db)).toEqual({ red: 2, queued: 1 });
110 expect(readChecksPile(app.db, true)).toEqual({ red: 1, queued: 0 });
111 });
112 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs