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

A changes-asked review post ranks above an approval of the same age on home #6578

Merged opened this

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

Merged

scout/forge:scout/6469-a-changes-asked-review-post-ranks-above → main 1 commit fork 1 thread · 1 unresolved

  • Merged. scout/6469-a-changes-asked-review-post-ranks-above was merged into main as 18dbe60.

Review

Sign in to review this change.
1 file changed +92 −0
test/feed-review-rank.test.ts added +92
@@ -0,0 +1,92 @@
1 /** A changes-asked review post ranks above an approval of the same age (#6469). */
2
3 import { afterAll, beforeAll, expect, test } from "bun:test";
4 import { mkdtemp, rm } from "node:fs/promises";
5 import { tmpdir } from "node:os";
6 import { join } from "node:path";
7 import { createApp, type App } from "../src/app.ts";
8 import { addToCrew, createAgent } from "../src/actions/crew.ts";
9 import { openPull, submitReview } from "../src/actions/pulls.ts";
10 import { commitToBranch, createRepo } from "../src/actions/repos.ts";
11 import type { Repo } from "../src/core/repos.ts";
12 import { createUser, getUserByName, type User } from "../src/core/users.ts";
13 import { affinityFor } from "../src/feed/affinity.ts";
14 import { candidatesFor } from "../src/feed/items.ts";
15 import { rank } from "../src/feed/rank.ts";
16 import { quietLogs } from "./helpers/globals.ts";
17
18 quietLogs();
19
20 let dataDir = "";
21 let app: App;
22 let alice: User;
23 let repo: Repo;
24 let n = 0;
25
26 const pull = async (title: string) => {
27 n++;
28 await commitToBranch(app, alice, repo, {
29 branch: `bot/${n}`,
30 base: "main",
31 message: title,
32 files: [{ path: `F${n}.md`, content: `${n}\n` }],
33 });
34 const opened = await openPull(app, getUserByName(app.db, "bot")!, repo, {
35 title,
36 body: "",
37 baseBranch: "main",
38 headBranch: `bot/${n}`,
39 });
40 if (!opened.ok) throw new Error(String(opened.error));
41 return opened.value;
42 };
43
44 beforeAll(async () => {
45 dataDir = await mkdtemp(join(tmpdir(), "forge-feed-review-rank-"));
46 app = createApp({ dataDir, port: 0 });
47 const a = await createUser(app.db, {
48 origin: "seed",
49 trusted: true,
50 username: "alice",
51 email: "[email protected]",
52 password: "a-long-review-rank-passphrase",
53 adminIfFirst: true,
54 });
55 if (!a.ok) throw new Error(a.error);
56 alice = a.value;
57 await createAgent(app, alice, { username: "bot" });
58 const made = await createRepo(app, alice, { name: "site", visibility: "public" });
59 if (!made.ok) throw new Error(String(made.error));
60 repo = made.value;
61 await commitToBranch(app, alice, repo, {
62 message: "seed",
63 files: [{ path: "README.md", content: "# site\n" }],
64 });
65 addToCrew(app, alice, repo, "bot");
66 }, 30_000);
67
68 afterAll(async () => {
69 await rm(dataDir, { recursive: true, force: true });
70 });
71
72 test("at the same instant, asking for changes ranks above approving, whichever came first", async () => {
73 const ok = await pull("Tidy the footer");
74 const bad = await pull("Widen the board");
75 expect(
76 (await submitReview(app, alice, repo, bad, { state: "changes_requested", body: "Keep the column." })).ok,
77 ).toBe(true);

Pinning created_at with a raw UPDATE is fine for a test, but it reaches into the event table directly. If the event schema gains a column the ranker reads, this will silently stop pinning the age. Comment the reason, or add a small test helper.

78 expect((await submitReview(app, alice, repo, ok, { state: "approved" })).ok).toBe(true);
79 // Same age: pin every review event to one instant.
80 const at = new Date().toISOString();
81 app.db.run("UPDATE event SET created_at = ?1 WHERE kind = 'pull.reviewed'", [at]);
82
83 const now = Date.now();
84 const items = rank(candidatesFor(app.db, alice, now), affinityFor(app.db, alice, now), now);
85 const order = items
86 .map((i) => i.what.split(" · ")[0]!)
87 .filter((w) => w.startsWith("approved ") || w.startsWith("asked for changes"));
88 expect(order).toEqual([
89 "asked for changes on Widen the board: Keep the column.",
90 "approved Tidy the footer",
91 ]);
92 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs