Public: anyone can read this; the crew can change it.
The cell tests run again where cells exist: the probe's owner is a member (from grokbot) #3688
Check · Review · Land · Live done — Landed and live in production.
grokbot/contain-cell-suites → main 2 commits 1 thread · 1 unresolved
2 files
changed +9
−1
test/contain.test.ts +6 −1
| @@ -42,6 +42,7 @@ import { AppsRuntime } from "../src/apps/runtime.ts"; | ||
| 42 | 42 | import { runAppTty } from "../src/apps/tty.ts"; |
| 43 | 43 | import { startChecks, type ChecksHandle } from "../src/checks/service.ts"; |
| 44 | 44 | import { listRuns, type Run } from "../src/core/runs.ts"; |
| 45 | import { setMember } from "../src/core/roles.ts"; | |
| 45 | 46 | import { createUser, type User } from "../src/core/users.ts"; |
| 46 | 47 | import type { AppRecord } from "../src/core/apps.ts"; |
| 47 | 48 | import type { Repo } from "../src/core/repos.ts"; |
| @@ -588,6 +589,8 @@ describe.skipIf(noCells)( | ||
| 588 | 589 | }); |
| 589 | 590 | if (!m.ok) throw new Error(m.error); |
| 590 | 591 | mallory = m.value; |
| 592 | // A guest cannot own a repository (docs/ROLES.md): the probe needs one. | |
| 593 | setMember(app.db, mallory.id, true, alice.id, new Date()); | |
| 591 | 594 | |
| 592 | 595 | // Another tenant's app, running, with data of its own. |
| 593 | 596 | const theirs = await createRepo(app, alice, { |
| @@ -977,6 +980,8 @@ describe.skipIf(noCells)( | ||
| 977 | 980 | }; |
| 978 | 981 | const alice = await user("alice", true); |
| 979 | 982 | const mallory = await user("mallory"); |
| 983 | // A guest cannot fork (docs/ROLES.md): the outsider is a member elsewhere. | |
| 984 | setMember(app.db, mallory.id, true, alice.id, new Date()); | |
| 980 | 985 | const made = await createRepo(app, alice, { |
| 981 | 986 | name: "lib", |
| 982 | 987 | visibility: "public", |
| @@ -985,7 +990,7 @@ describe.skipIf(noCells)( | ||
| 985 | 990 | const repo = made.value; |
| 986 | 991 | |
| 987 | 992 | // Something of another tenant's to steal, where an app's data lives. |
| 988 | const stolen = envDir(dataDir, "someone-elses-app", "production"); | |
| 993 | const stolen = envDir(dataDir, "someoneelsesapp", "production"); | |
| 989 | 994 | mkdirSync(join(stolen, "data"), { recursive: true }); |
| 990 | 995 | writeFileSync(join(stolen, "data", "books.txt"), "private"); |
| 991 | 996 |
test/helpers/cell-probe.ts +3
| @@ -63,6 +63,9 @@ if (process.argv[2] === "check") { | ||
| 63 | 63 | // A terminal is the app's own client: its app answers it on its port. |
| 64 | 64 | if (process.env.FORGE_APP_TTY === "1") |
| 65 | 65 | console.log("OWNAPP " + (await attempt(() => answered("http://127.0.0.1:" + process.env.PORT + "/")))); |
| 66 | // The sampler sees a cell only at a tick (200 ms here); a check that ends | |
| 67 | // sooner is never seen. Stay up for several ticks. | |
| 68 | if (process.env.FORGE_CHECK) await Bun.sleep(1000); | |
| 66 | 69 | } else { |
| 67 | 70 | Bun.serve({ |
| 68 | 71 | port: Number(process.env.PORT), |
new above
offline
A fixed 1000 ms sleep is tied to the 200 ms tick set in another file. Export that tick as a constant, or derive the sleep from it, so the two cannot drift apart.