Public: anyone can read this; the crew can change it.
The preview's sample issue has an agent run and an open closing pull, so the issue page's looks show those rows #9683
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/9678-the-preview-s-sample-issue-has-an-agent → main 1 commit fork
2 files
changed +46
−1
src/spawn/preview-seed.ts +14 −1
| @@ -182,7 +182,8 @@ async function seedWorld(app: App, admin: User): Promise<Result<void, string>> { | ||
| 182 | 182 | const [milestone, held] = issues.flatMap((i) => (i.ok ? [i.value] : [])); |
| 183 | 183 | const pull = await openPull(app, admin, repo.value, { |
| 184 | 184 | title: "Say hello", |
| 185 | body: "Adds a greeting.", | |
| 185 | // Closes the first issue, so its page draws a Closes with row. | |
| 186 | body: `Adds a greeting.\n\nCloses #${String(milestone!.number)}`, | |
| 186 | 187 | baseBranch: repo.value.defaultBranch, |
| 187 | 188 | headBranch: "greeting", |
| 188 | 189 | }); |
| @@ -204,6 +205,18 @@ async function seedWorld(app: App, admin: User): Promise<Result<void, string>> { | ||
| 204 | 205 | open.push(i.value); |
| 205 | 206 | } |
| 206 | 207 | |
| 208 | // One finished agent run on the first issue, so its page draws a Runs row. | |
| 209 | // Recorded only: createRun/claimRun/finishRun start no agent and spend nothing. | |
| 210 | const recorded = createRun(app.db, { | |
| 211 | repoId: repo.value.id, | |
| 212 | kind: "agent", | |
| 213 | issueId: milestone!.id, | |
| 214 | actorId: admin.id, | |
| 215 | reason: "seed", | |
| 216 | }); | |
| 217 | claimRun(app.db, recorded.id); | |
| 218 | finishRun(app.db, recorded.id, { state: "ok", summary: "A seeded run", costUsd: 0 }); | |
| 219 | ||
| 207 | 220 | // A flow week: agent runs that started and spent this week, and a valve |
| 208 | 221 | // turned part way, so /flow has a pipe to draw and one to turn. |
| 209 | 222 | for (const usd of [0.42, 1.18, 0.75]) { |
test/preview-looks.test.ts +32
| @@ -56,3 +56,35 @@ describe("the seeded held page", () => { | ||
| 56 | 56 | for (const t of review.themes.slice(THEMES_AT_REST)) expect(rest).not.toContain(`${t.name} <`); |
| 57 | 57 | }); |
| 58 | 58 | }); |
| 59 | ||
| 60 | describe("the seeded first issue", () => { | |
| 61 | let dir: string; | |
| 62 | let app: App; | |
| 63 | let servers: Servers; | |
| 64 | beforeAll(async () => { | |
| 65 | dir = await mkdtemp(join(tmpdir(), "forge-preview-issue-")); | |
| 66 | app = createApp({ dataDir: dir, port: 0 }); | |
| 67 | const seeded = await seedPreview(app, { FORGE_APP_ENV: "preview" }); | |
| 68 | if (!seeded.ok) throw new Error(seeded.error); | |
| 69 | servers = await serve(app); | |
| 70 | }, 60_000); | |
| 71 | afterAll(async () => { | |
| 72 | await servers.stop(); | |
| 73 | await rm(dir, { recursive: true, force: true }); | |
| 74 | }); | |
| 75 | ||
| 76 | test("its page carries a Runs row and a Closes with row, and a second seed adds none", async () => { | |
| 77 | const count = () => | |
| 78 | (app.db.query("SELECT COUNT(*) AS n FROM run").get() as { n: number }).n; | |
| 79 | const before = count(); | |
| 80 | const again = await seedPreview(app, { FORGE_APP_ENV: "preview" }); | |
| 81 | expect(again.ok && again.value.seeded).toBe(false); | |
| 82 | expect(count()).toBe(before); | |
| 83 | const res = await fetch(`${servers.url}/preview-admin/sample/issues/1`); | |
| 84 | expect(res.status).toBe(200); | |
| 85 | const html = await res.text(); | |
| 86 | expect(html).toContain("<h2>Runs</h2>"); | |
| 87 | expect(html).toContain("<h2>Closes with</h2>"); | |
| 88 | expect(html).toContain("A seeded run"); | |
| 89 | }); | |
| 90 | }); |