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

A preview's /__forge/ door links the live app, so one tap compares the pull with production #7929

Merged opened this

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

Merged

torque/forge:torque/7925-a-preview-s-forge-door-links-the-live-ap → main 4 commits fork

  • Merged. torque/7925-a-preview-s-forge-door-links-the-live-ap was merged into main as 92c5b0c.

Review

Sign in to review this change.
4 files changed +64 −5
docs/APPS.md +5 −1
@@ -242,7 +242,11 @@ forge, never the app, with no script, saying the app and where you are
242242 (`production` or `preview of pull #N`) and linking Home, the repository and *Make it yours*
243243 (`<repo>/make-it-yours`; both only to who may read the repository, who also
244244 get the "more pulls" line linked to `<repo>/pulls`) and *Tell the crew* (the same link `/__forge/crew` gives; signed
245 out it offers sign in). It also says what is serving, read from the deploy
245 out it offers sign in). On a preview it also links *The live app* (the production
246 address, so one tap compares the pull with production), only to who may read the
247 repository, as *What changed* is; production's door has no such link. In the
248 open-pulls list the preview's own pull is plain text marked "(this preview)"
249 instead of a link back to itself. It also says what is serving, read from the deploy
246250 record (no git): production shows the newest release and the three before it
247251 (a redeploy of the same commit is not another release), a preview shows its
248252 pull and the commit it last served, or "not deployed yet". A viewer who cannot
src/apps/door.ts +10 −4
@@ -27,6 +27,8 @@ export type DoorFacts = {
2727 pulls?: DoorPullLine[] | undefined;
2828 /** Who of the crew is working here now, as the pill's crew line says it. */
2929 crew?: CrewNow | undefined;
30 /** The production host of this app, only on a preview. */
31 live?: string | undefined;
3032 /** This host's own report door, only for a public app anyone may report on. */
3133 report?: string | undefined;
3234 };
@@ -34,7 +36,7 @@ export type DoorFacts = {
3436 /** How many pulls the door lists; one more read than this means there are others. */
3537 export const DOOR_PULL_LIMIT = 5;
3638
37 export type DoorPullLine = { number: number; title: string; check: string; href: string };
39 export type DoorPullLine = { number: number; title: string; check: string; href: string; self?: boolean };
3840
3941 const STYLE =
4042 "html{color-scheme:light dark}body{font:16px/1.5 system-ui,sans-serif;max-width:32rem;margin:3rem auto;padding:0 1rem}li{margin:.4rem 0}pre{overflow-x:auto;padding:.6rem;background:#eee;color:#111;user-select:all}" +
@@ -100,9 +102,10 @@ function servingHtml(facts: DoorFacts): string {
100102
101103 function pullsHtml(pulls: DoorPullLine[] | undefined, morePulls: string | undefined): string {
102104 if (pulls === undefined || pulls.length === 0) return "";
103 const items = pulls.slice(0, DOOR_PULL_LIMIT).map((p) =>
104 link(p.href, `#${p.number} ${[...p.title].slice(0, 120).join("")} · check ${p.check}`),
105 );
105 const items = pulls.slice(0, DOOR_PULL_LIMIT).map((p) => {
106 const text = `#${p.number} ${[...p.title].slice(0, 120).join("")} · check ${p.check}`;
107 return p.self === true ? `<li>${escapeAttr(text)} (this preview)</li>` : link(p.href, text);
108 });
106109 const words = "More pulls are open on the forge.";
107110 const more =
108111 pulls.length <= DOOR_PULL_LIMIT
@@ -130,6 +133,9 @@ export function doorPage(facts: DoorFacts, head: boolean): Response {
130133 links.push(link(new URL(`/${where.repo}/pulls/${where.pull}/files`, forgeUrl).href, "What changed"));
131134 links.push(link(`${repoUrl}/make-it-yours`, "Make it yours"));
132135 morePulls = `${repoUrl}/pulls`;
136 // Production's address is for a reader of the app, as What changed is.
137 if (facts.live !== undefined && where.env !== "production")
138 links.push(link(facts.live, "The live app"));
133139 }
134140 if (facts.tell !== undefined) links.push(link(facts.tell, "Tell the crew"));
135141 else if (facts.signin !== undefined)
src/apps/proxy.ts +4
@@ -474,6 +474,7 @@ function doorPulls(
474474 number: p.number,
475475 title: p.title,
476476 check: checkWord(p.run, p.headOid),
477 ...(env === target.env ? { self: true } : {}),
477478 href: live
478479 ? runtime.urlFor(target.app, env)
479480 : new URL(
@@ -944,6 +945,9 @@ export async function proxyApp(
944945 {
945946 where,
946947 pulls,
948 ...(target.env === "production"
949 ? {}
950 : { live: runtime.urlFor(target.app, "production") }),
947951 ...(crew === undefined ? {} : { crew }),
948952 ...(serving === undefined ? {} : { serving }),
949953 forgeUrl: runtime.options.forgeUrl,
test/apps-door.test.ts +45
@@ -443,6 +443,51 @@ test("a preview links What changed for a reader only, never on production or for
443443 expect(await text({ app: "notes", env: "production", repo: "alice/notes" })).not.toContain("What changed");
444444 });
445445
446 test("a preview's door links the live app and marks its own pull; production's has neither", async () => {
447 const live = runtime.urlFor(record, "production");
448 const preview = doorPage(
449 {
450 where: { app: "notes", env: "pull-7", pull: 7, repo: "alice/notes" },
451 forgeUrl: "http://forge.test",
452 live,
453 pulls: [
454 { number: 7, title: "mine", check: "none", href: "http://x/7", self: true },
455 { number: 8, title: "other", check: "none", href: "http://x/8" },
456 ],
457 },
458 false,
459 );
460 const html = await preview.text();
461 expect(html).toContain(`<li><a href="${live}">The live app</a></li>`);
462 expect(html).toContain("#7 mine · check none (this preview)");
463 expect(html).not.toContain('href="http://x/7"');
464 expect(html).toContain('href="http://x/8"');
465 const prod = await doorPage(
466 { where: { app: "notes", env: "production" }, forgeUrl: "http://forge.test", pulls: [] },
467 false,
468 ).text();
469 expect(prod).not.toContain("The live app");
470 expect(prod).not.toContain("this preview");
471 // Without the repository to read, no production address either.
472 const bare = await doorPage(
473 { where: { app: "notes", env: "pull-7", pull: 7 }, forgeUrl: "http://forge.test", live },
474 false,
475 ).text();
476 expect(bare).not.toContain("The live app");
477 // The newest pull is among the five the door lists, so the proxy marks it.
478 const fresh = createIssue(app.db, { repoId: record.repoId, authorId: alice, title: "newest", kind: "pull" });
479 if (!fresh.ok) throw new Error(fresh.error);
480 app.db
481 .query(
482 "INSERT INTO pull (issue_id, base_branch, head_branch, base_oid, head_oid) VALUES (?, 'main', 'h', 'b', 'x')",
483 )
484 .run(fresh.value.id);
485 const real = await (await door(`notes--${fresh.value.number}.${DOMAIN}`)).text();
486 expect(real).toContain(">The live app</a>");
487 expect(real).toContain(`#${fresh.value.number} newest · check none (this preview)</li>`);
488 expect(await (await door(`notes.${DOMAIN}`)).text()).not.toContain("The live app");
489 });
490
446491 test("the door names the crew run working here, linked, to who may see it", async () => {
447492 const bob = await createUser(app.db, {
448493 origin: "seed",

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs