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

A warning never blanks the board or paints the home red: one line, where it belongs #1128

Merged opened this in answer to

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

Merged

scout/forge:scout/1109-a-warning-never-blanks-the-board-or-pain → main 1 commit fork 1 thread · 1 unresolved

  • Merged. scout/1109-a-warning-never-blanks-the-board-or-pain was merged into main as 92aef7a.

Review

Sign in to review this change.
6 files changed +50 −22
src/kernel/vitals.ts +3 −10
@@ -1,5 +1,7 @@
11 /**
2 * The forge's standing: is it fine, and if not, what is off. Plain data in,
2 * The forge's standing: is it fine, and if not, what is off. Only what needs
3 * a person now is a need; a setting that is not the default is a note on its
4 * own page (`web/pages/capacity.ts`), never here. Plain data in,
35 * plain data out — the disk under `FORGE_DATA`, this process's memory, the
46 * queue, runs that stopped making progress, and how many apps are serving,
57 * asleep or previewed. A fixed handful of queries however many runs and
@@ -12,11 +14,6 @@ import { freemem, totalmem } from "node:os";
1214 import { recentErrors, type ErrorLine } from "./log.ts";
1315 import { leaseLapsed, listRunning, queueDepth } from "../core/runs.ts";
1416 import { STALE_AFTER_MS } from "../runs/lease.ts";
15 import { egressSetting } from "../core/capacity.ts";
16
17 /** What every new cell may reach while egress is only reported. */
18 export const EGRESS_REPORTED =
19 "Egress is reported, not enforced: every new app, preview, terminal and check cell may reach any public host on ports 80 and 443. Set it back to enforce under Settings → Capacity.";
2017
2118 /** Free disk under this share of the volume is something to say. */
2219 export const DISK_FREE_MIN = 0.1;
@@ -114,10 +111,6 @@ export function vitals(input: VitalsInput): Vitals {
114111 `${seen.lastHour} errors in the last hour (${ERROR_BURST} or more is a burst).`,
115112 );
116113
117 // Deliberate, and still to be said while it lasts (`core/capacity.ts`):
118 // only an admin sees vitals, so naming what is open here tells nobody else.
119 if (egressSetting(input.db) === "report") needs.push(EGRESS_REPORTED);
120
121114 return {
122115 ok: needs.length === 0,
123116 needs,
src/web/pages/capacity.ts +4 −5
@@ -103,13 +103,12 @@ export function capacityPage(ctx: Ctx): Response {
103103 );
104104 const body = html`${when(
105105 reported,
106 () => html`<p class="error-note mb" id="egress-reported">
107 ${icon("alert")} Egress is reported, not enforced: every new app,
106 () => html`<p class="muted small mb" id="egress-reported">

Good: a muted note on the page that owns the setting. Check at 360px that it stays readable and does not push the controls below the fold.

107 ${icon("activity")} Egress is reported, not enforced: every new app,
108108 preview, terminal and check cell may reach any public host on ports
109109 80 and 443, declared or not. Private, loopback and cluster addresses,
110 and every other port, stay refused. The forge's vitals (the board's
111 strip, the health check for admins) say so while it lasts. Set it back to enforce once each app's reported hosts
112 are in its forge.json.
110 and every other port, stay refused. Set it back to enforce once each
111 app's reported hosts are in its forge.json.
113112 </p>`,
114113 )}
115114 ${card(
test/board.test.ts +24
@@ -11,6 +11,7 @@ import { mkdtemp, rm } from "node:fs/promises";
1111 import { tmpdir } from "node:os";
1212 import { join } from "node:path";
1313 import { createApp, type App } from "../src/app.ts";
14 import { changeCapacity } from "../src/actions/capacity.ts";
1415 import { enableApp } from "../src/actions/apps.ts";
1516 import { addToCrew, createAgent } from "../src/actions/crew.ts";
1617 import { openIssue } from "../src/actions/issues.ts";
@@ -455,6 +456,26 @@ describe("the board's forge strip", () => {
455456 expect(other).not.toContain("stuck.");
456457 });
457458
459 test("a setting that is not the default is no incident: the strip stays fine and the cards render", async () => {
460 const made = await createRepo(app, admin, { name: "calm" });
461 if (!made.ok) throw new Error(String(made.error));
462 const enabled = await enableApp(app, admin, made.value, { slug: "calm" });
463 if (!enabled.ok) throw new Error(String(enabled.error));
464 claimRun(app.db, createRun(app.db, { repoId: made.value.id, kind: "agent" }).id);
465 // Clear the stuck run the first test left behind.
466 app.db.query("UPDATE run SET state = 'failed' WHERE heartbeat_at = ?1").run("2020-01-01T00:00:00.000Z");
467 expect(changeCapacity(app, admin, "cells.egress", "report").ok).toBe(true);
468 try {
469 const text = await board("root");
470 expect(text).toContain("All fine");
471 expect(text).not.toContain("board-forge-need");
472 expect(text).not.toContain("error-note");
473 expect(text).toContain("board-card board-run");
474 } finally {
475 changeCapacity(app, admin, "cells.egress", "enforce");
476 }
477 });
478
458479 test("a blocked rollout shows in the status line, escaped, for an admin only", async () => {
459480 const guard = mkdtempSync(join(tmpdir(), "forge-board-guard-"));
460481 process.env["FORGE_GUARD_DIR"] = guard;
@@ -467,6 +488,9 @@ describe("the board's forge strip", () => {
467488 const blocked = await board("root");
468489 expect(blocked).toContain("rollout blocked: quota refused &lt;i&gt;8Gi&lt;/i&gt;");
469490 expect(blocked).not.toContain("<i>8Gi</i>");
491 // One line, and the board beneath it still renders.
492 expect(blocked.match(/class="board-forge-need"/g)?.length).toBe(1);
493 expect(blocked).toContain("board-card board-run");
470494 expect(await board("bob")).not.toContain("rollout blocked");
471495 } finally {
472496 delete process.env["FORGE_GUARD_DIR"];
test/capacity.test.ts +3 −5
@@ -35,7 +35,6 @@ import { createUser, type User } from "../src/core/users.ts";
3535 import { startCrew } from "../src/crew/dispatch.ts";
3636 import { Gate } from "../src/git/env.ts";
3737 import { readHealth } from "../src/actions/health.ts";
38 import { EGRESS_REPORTED } from "../src/kernel/vitals.ts";
3938 import { serve, type Servers } from "../src/http/server.ts";
4039 import { readRunLog } from "../src/runs/log.ts";
4140
@@ -344,12 +343,12 @@ describe("report mode is loud to admins, and to nobody else", () => {
344343 const needs = (who: User | undefined): string[] =>
345344 "needs" in readHealth(app, who) ? (readHealth(app, who) as { needs: string[] }).needs : [];
346345
347 test("reported: the admin's vitals and the Capacity page name what is open", async () => {
346 test("reported: the Capacity page says it once, as a note; vitals do not", async () => {
348347 expect(changeCapacity(app, alice, "cells.egress", "report").ok).toBe(true);
349 expect(needs(alice)).toContain(EGRESS_REPORTED);
350 expect(EGRESS_REPORTED).toContain("any public host on ports 80 and 443");
348 expect(needs(alice)).toEqual([]);
351349 const shown = await page();
352350 expect(shown).toContain('id="egress-reported"');
351 expect(shown).not.toMatch(/error-note[^>]*id="egress-reported"/);
353352 expect(shown.replace(/\s+/g, " ")).toContain("may reach any public host on ports 80 and 443");
354353 });
355354
@@ -365,7 +364,6 @@ describe("report mode is loud to admins, and to nobody else", () => {
365364
366365 test("enforced: no warning anywhere", async () => {
367366 expect(changeCapacity(app, alice, "cells.egress", "enforce").ok).toBe(true);
368 expect(needs(alice)).not.toContain(EGRESS_REPORTED);
369367 expect(await page()).not.toContain('id="egress-reported"');
370368 });
371369 });
test/vitals.test.ts +2 −2
@@ -148,8 +148,8 @@ test("the number of queries does not grow with runs", () => {
148148 if (i % 2) app.db.query("UPDATE run SET state='running' WHERE id=?1").run(r.id);
149149 }
150150 expect(count()).toBe(before);
151 // The queue, the running runs, and the egress mode (`core/capacity.ts`).
152 expect(before).toBe(3);
151 // The queue and the running runs.
152 expect(before).toBe(2);
153153 });
154154
155155 test("errors are counted, bounded, redacted, and a burst is said", async () => {
test/web.test.ts +14
@@ -410,6 +410,20 @@ describe("web pages end to end", () => {
410410 expect(stale.status).toBe(404);
411411 });
412412
413 test("the home carries no error-note for a setting that is not the default", async () => {
414 const { changeCapacity } = await import("../src/actions/capacity.ts");
415 const { getUserByName } = await import("../src/core/users.ts");
416 const ada = getUserByName(app.db, "ada")!;
417 expect(changeCapacity(app, ada, "cells.egress", "report").ok).toBe(true);
418 try {
419 const text = await (await fetch(base, { headers: { cookie } })).text();
420 expect(text).not.toContain("error-note");
421 expect(text).not.toContain("Egress is reported");
422 } finally {
423 changeCapacity(app, ada, "cells.egress", "enforce");
424 }
425 });
426
413427 test("new repo via the form, empty state renders", async () => {
414428 const response = await fetch(`${base}/new`, {
415429 method: "POST",

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs