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

A release post in the feed reads `<version> is serving: <first pull> and N more`, linking the release commit #6162

Merged opened this

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

Merged

scout/forge:scout/6099-a-release-post-in-the-feed-reads-version → main 1 commit fork

  • Merged. scout/6099-a-release-post-in-the-feed-reads-version was merged into main as 4f7127f.

Review

Sign in to review this change.
2 files changed +53 −2
src/feed/items.ts +26 −2
@@ -486,6 +486,20 @@ function awake(
486486 return candidates.filter((c) => all.get(c.repoId)?.archivedAt == null);
487487 }
488488
489 /** `0.7.251 is serving: <first title> and N more`, or undefined without a valid version. */
490 function releasePost(p: Record<string, unknown>): string | undefined {
491 const version = p["version"];
492 if (typeof version !== "string" || !/^\d{1,6}\.\d{1,6}\.\d{1,6}$/.test(version)) return undefined;
493 const pulls = Array.isArray(p["pulls"]) ? p["pulls"] : [];
494 const titles = pulls.flatMap((x) => {
495 const t = (x as { title?: unknown } | null)?.title;
496 return typeof t === "string" && t.trim() !== "" ? [t.trim()] : [];
497 });
498 if (titles.length === 0) return `${version} is serving`;
499 const more = titles.length - 1;
500 return `${version} is serving: ${clip(titles[0]!, 80)}${more > 0 ? ` and ${more} more` : ""}`;
501 }
502
489503 type Partial = Omit<Candidate, "actor">;
490504
491505 /** The conversations the window's events name, read once for all of them. */
@@ -574,8 +588,18 @@ function fromEvent(
574588 ...(typeof oid === "string" && /^[0-9a-f]{40}$/.test(oid) ? { look: { env, commitOid: oid } } : {}),
575589 };
576590 }
577 case "app.serving":
578 return { ...common, kind: "release", link: base(repo), what: "a new version is serving" };
591 case "app.serving": {
592 const post = releasePost(p);
593 if (post === undefined)
594 return { ...common, kind: "release", link: base(repo), what: "a new version is serving" };
595 const oid = p["commitOid"];
596 return {
597 ...common,
598 kind: "release",
599 link: typeof oid === "string" && /^[0-9a-f]{40}$/.test(oid) ? `${base(repo)}/commit/${oid}` : base(repo),
600 what: post,
601 };
602 }
579603 // A tell is a post; a comment is a reply under it, in its own words.
580604 case "issue.opened": {
581605 if (number === undefined) return undefined;
test/home-feed.test.ts +27
@@ -358,6 +358,33 @@ describe("home is the feed", () => {
358358 expect(after).not.toContain("ancient musing");
359359 });
360360
361 test("a release post reads the version and first pull, links the commit, and falls back without a version", async () => {
362 const oid = "a".repeat(40);
363 const serving = (payload: Record<string, unknown>) =>
364 app.bus.append({ kind: "app.serving", repoId: garden.id, payload: { app: "garden", env: "production", commitOid: oid, ...payload } });
365 serving({ version: "0.7.251", pulls: [{ title: "Water <b>early</b>", number: 1 }, { title: "Mulch", number: 2 }, { title: "Weed", number: 3 }] });
366 const page = await get("/", aliceCookie).then((r) => r.text());
367 expect(page).toContain("0.7.251 is serving: Water &lt;b&gt;early&lt;/b&gt; and 2 more");
368 expect(page).not.toContain("<b>early</b>");
369 expect(page).toContain(`href="/alice/garden/commit/${oid}"`);
370 const mcp = async () => {
371 const token = createToken(app.db, alice.id, "rel", "ro").token;
372 const res = await fetch(`${servers.url}/mcp`, {
373 method: "POST",
374 headers: { "content-type": "application/json", accept: "application/json, text/event-stream", authorization: `Bearer ${token}` },
375 body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "feed", arguments: { limit: 50 } } }),
376 });
377 return JSON.parse(((await res.json()) as any).result.content[0].text).items as any[];
378 };
379 const rel = (await mcp()).filter((i) => i.what.includes("is serving"));
380 expect(rel[0].what).toBe("0.7.251 is serving: Water <b>early</b> and 2 more");
381 expect(rel[0].link).toBe(`/alice/garden/commit/${oid}`);
382 serving({ version: "not-a-version", pulls: [{ title: "Nope", number: 4 }] });
383 const items = (await mcp()).filter((i) => i.what === "a new version is serving");
384 expect(items.length).toBe(1);
385 expect(items[0].link).toBe("/alice/garden");
386 });
387
361388 test("the MCP feed answers the same posts, page by page", async () => {
362389 const token = createToken(app.db, alice.id, "ro", "ro").token;
363390 const call = async (args: unknown) => {

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs