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

The preview seed holds a recently moved repository, and its head page is a phone look showing "Moved from" #10261

Merged opened this

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

Merged

scout/forge:scout/10195-the-preview-seed-holds-a-recently-moved → main 3 commits fork 1 thread · 1 unresolved

  • Merged. scout/10195-the-preview-seed-holds-a-recently-moved was merged into main as 3ca9d74.

Review

Sign in to review this change.
3 files changed +93 −1
src/spawn/preview-looks.ts +11
@@ -38,6 +38,16 @@ export const PREVIEW_PULL_FILES = `${PREVIEW_PULL_PAGE}/files`;
3838 export const PREVIEW_APP = "hello";
3939 export const PREVIEW_APP_PAGE = `/${PREVIEW_ADMIN}/${PREVIEW_APP}`;
4040
41 /**
42 * The recently moved repository (#10195): made by the admin as `moved`, then
43 * moved to the first seeded fork owner through the action a person uses, so
44 * its head draws "Moved from preview-admin/moved on <date>". The seed refuses
45 * to finish unless the page answers 200 and holds the line.
46 */
47 export const PREVIEW_MOVED = "moved";
48 export const PREVIEW_MOVED_OWNER = "preview-ada";
49 export const PREVIEW_MOVED_PAGE = `/${PREVIEW_MOVED_OWNER}/${PREVIEW_MOVED}`;
50
4151 /** The Iterations page of the seeded fork family (#9182). */
4252 export const PREVIEW_ITERATIONS_PAGE = `${PREVIEW_REPO_HOME}/iterations`;
4353 /**
@@ -131,6 +141,7 @@ export const PREVIEW_OWNER_LOOKS: readonly OwnerLook[] = [
131141 "/flow",
132142 PREVIEW_REPO_HOME,
133143 PREVIEW_APP_PAGE,
144 PREVIEW_MOVED_PAGE,
134145 PREVIEW_PULL_PAGE,
135146 PREVIEW_PULL_FILES,
136147 PREVIEW_ITERATIONS_PAGE,
src/spawn/preview-seed.ts +38 −1
@@ -26,6 +26,8 @@ import { pinBuild } from "../actions/builds.ts";
2626 import { addReview, mergePull, openPull } from "../actions/pulls.ts";
2727 import { commitToBranch, createRepo, forkRepo } from "../actions/repos.ts";
2828 import { reviewGate } from "../actions/gate_review.ts";
29 import { forgeHttp } from "../http/server.ts";
30 import { transferRepository } from "../actions/transfer.ts";
2931 import { linkIssue } from "../actions/dependencies.ts";
3032 import { createApp as createAppRecord } from "../core/apps.ts";
3133 import { studioApp } from "../web/studio/app.ts";
@@ -57,6 +59,9 @@ import {
5759 PREVIEW_ITERATIONS_PAGE,
5860 PREVIEW_PULL,
5961 PREVIEW_PULL_PAGE,
62 PREVIEW_MOVED,
63 PREVIEW_MOVED_OWNER,
64 PREVIEW_MOVED_PAGE,
6065 PREVIEW_REPO,
6166 PREVIEW_SETTINGS_PAGES,
6267 } from "./preview-looks.ts";
@@ -69,6 +74,7 @@ export {
6974 PREVIEW_HELD_PAGE,
7075 PREVIEW_HELD_THEMES,
7176 PREVIEW_ITERATIONS_PAGE,
77 PREVIEW_MOVED_PAGE,
7278 PREVIEW_OWNER_LOOKS,
7379 PREVIEW_PULL,
7480 PREVIEW_PULL_PAGE,
@@ -76,6 +82,36 @@ export {
7682 PREVIEW_REPO_HOME,
7783 } from "./preview-looks.ts";
7884
85 /**
86 * A repository moved just now, through the action a person uses (#10195):
87 * its head draws "Moved from <old path> on <date>". Refused unless that page
88 * answers 200 and holds the line, in the first-paint HTML.
89 */
90 async function seedMoved(app: App, admin: User): Promise<Result<void, string>> {
91 const made = await createRepo(app, admin, { name: PREVIEW_MOVED, visibility: "public", description: "A repository that moved" });
92 if (!made.ok) return err(`the moved repository: ${String(made.error)}`);
93 const first = await commitToBranch(app, admin, made.value, {
94 message: "Start",
95 files: [{ path: "README.md", content: "# moved\n\nA repository that changed owner.\n" }],
96 });
97 if (!first.ok) return err(`the moved repository's commit: ${JSON.stringify(first.error)}`);
98 const moved = await transferRepository(app, admin, made.value, PREVIEW_MOVED_OWNER);
99 if (!moved.ok) return err(`the move: ${String(moved.error)}`);
outdated

Why is this import lazy? If there is no import cycle, make it static; otherwise say so in one line.

100 const http = forgeHttp(app);
101 const session = createSession(app.db, admin.id);
102 try {
103 const res = await http.handle(
104 new Request(`http://localhost${PREVIEW_MOVED_PAGE}`, { headers: { cookie: `forge_session=${session.token}` } }),
105 );
106 if (res.status !== 200) return err(`${PREVIEW_MOVED_PAGE} answers ${String(res.status)}, not 200`);
107 if (!(await res.text()).includes("moved-from")) return err(`${PREVIEW_MOVED_PAGE} holds no moved-from line`);
108 } finally {
109 destroySession(app.db, session.token);
110 http.close();
111 }
112 return ok();
113 }
114
79115 /** The seeded wave's version and headline, which the owner's /waves look shows. */
80116 export const PREVIEW_WAVE = "0.1.0";
81117 export const PREVIEW_WAVE_HEADLINE = "The sample says hello";
@@ -173,7 +209,6 @@ async function seedSettingsPages(app: App, admin: User): Promise<Result<void, st
173209 });
174210 if (!added.ok) return err(`the sample account: ${added.error}`);
175211 }
176 const { forgeHttp } = await import("../http/server.ts");
177212 const http = forgeHttp(app);
178213 const session = createSession(app.db, admin.id);
179214 try {
@@ -319,6 +354,8 @@ async function seedWorld(app: App, admin: User): Promise<Result<void, string>> {
319354 if (!gated.ok) return gated;
320355 const hosted = await seedApp(app, admin);
321356 if (!hosted.ok) return hosted;
357 const moved = await seedMoved(app, admin);
358 if (!moved.ok) return moved;
322359 const valve = turnValveFor(app, admin, `${PREVIEW_ADMIN}/${PREVIEW_REPO}`, 60);
323360 if (!valve.ok) return err(`the valve: ${valve.error}`);
324361
test/preview-moved.test.ts added +44
@@ -0,0 +1,44 @@
1 /** The preview's recently moved repository draws "Moved from" in its first-paint HTML (#10195). */
2 import { afterAll, beforeAll, expect, test } from "bun:test";
3 import { mkdtemp, rm } from "node:fs/promises";
4 import { tmpdir } from "node:os";
5 import { join } from "node:path";
6 import { createApp, type App } from "../src/app.ts";
7 import { serve, type Servers } from "../src/http/server.ts";
8 import { createSession } from "../src/core/sessions.ts";
9 import { recentMove } from "../src/core/transfer.ts";
10 import { getRepo } from "../src/core/repos.ts";
11 import { PREVIEW_ADMIN, PREVIEW_MOVED, PREVIEW_MOVED_PAGE, PREVIEW_OWNER_LOOKS } from "../src/spawn/preview-looks.ts";
12 import { previewAdmin, seedPreview } from "../src/spawn/preview-seed.ts";
13
14 let dir: string;
15 let app: App;
16 let servers: Servers;
17 beforeAll(async () => {
18 dir = await mkdtemp(join(tmpdir(), "forge-preview-moved-"));
19 app = createApp({ dataDir: dir, port: 0 });
20 const seeded = await seedPreview(app, { FORGE_APP_ENV: "preview" });
21 if (!seeded.ok) throw new Error(seeded.error);
22 servers = await serve(app);
23 }, 30_000);
24 afterAll(async () => {
25 servers.stop();
26 app.close();
27 await rm(dir, { recursive: true, force: true });
28 });
29
30 test("the moved repository's head says where from, in the HTML the server sends", async () => {
31 const cookie = `forge_session=${createSession(app.db, previewAdmin(app)!.id).token}`;
32 const res = await fetch(`${servers.url}${PREVIEW_MOVED_PAGE}`, { headers: { cookie } });
33 expect(res.status).toBe(200);
34 const html = await res.text();
35 expect(html).toContain("moved-from");
36 expect(html).toContain(`Moved from ${PREVIEW_ADMIN}/${PREVIEW_MOVED} on`);
37 const repo = getRepo(app.db, "preview-ada", PREVIEW_MOVED)!;
38 expect(recentMove(app.db, repo.id)?.from).toBe(`${PREVIEW_ADMIN}/${PREVIEW_MOVED}`);
39 });
40
41 test("its head is looked at on desktop and phone", () => {
42 for (const kind of ["desktop", "phone"] as const)
43 expect(PREVIEW_OWNER_LOOKS).toContainEqual({ page: PREVIEW_MOVED_PAGE, kind });
44 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs