Public: anyone can read this; the crew can change it.
The changelog's "Live:" commit links to that commit, so a reader goes from what is live to what it contains in one tap #8370
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/8336-the-changelog-s-live-commit-links-to-tha → main 1 commit fork
2 files
changed +28
−2
src/web/pages/changelog.ts +8 −2
| @@ -8,6 +8,7 @@ | ||
| 8 | 8 | |
| 9 | 9 | import { notePhase, takeSessionTime, timePhaseAsync } from "../../core/route_timing.ts"; |
| 10 | 10 | import type { Ctx } from "../../http/context.ts"; |
| 11 | import { canRead, getRepo } from "../../core/repos.ts"; | |
| 11 | 12 | import { newestLive, secondsWords } from "../../keeper/landed.ts"; |
| 12 | 13 | import { dayHeading, dayOf, daysJs, shippedToday } from "../../release/days.ts"; |
| 13 | 14 | import { readLandings, type Landing, type Landings } from "../../release/landings.ts"; |
| @@ -118,13 +119,16 @@ export function shippedRegion( | ||
| 118 | 119 | now: Date = new Date(), |
| 119 | 120 | zone = "UTC", |
| 120 | 121 | toLive?: { version: string; seconds: number }, |
| 122 | readable = true, | |
| 121 | 123 | ): Html { |
| 122 | 124 | const keep = (l: Landing) => choice === "all" || l.repo === choice; |
| 123 | 125 | const live = read.live.filter(keep); |
| 124 | 126 | const onItsWay = read.onItsWay.filter(keep); |
| 125 | 127 | const todayIs = dayOf(now.toISOString(), zone); |
| 126 | 128 | const today = live.filter((l) => dayOf(l.at, zone) === todayIs).length; |
| 127 | const commit = read.commit === null ? null : sha(read.commit); | |
| 129 | // The short sha is a way in to the commit's page, unless there is no repository or the reader may not open it. | |
| 130 | const commit = | |
| 131 | read.commit === null ? null : sha(read.commit, readable && read.own !== undefined ? `/${read.own}/commit/${read.commit}` : undefined); | |
| 128 | 132 | // A build that is not a release has no version worth a reader's attention: the commit says it. |
| 129 | 133 | const version = |
| 130 | 134 | read.version !== "dev" ? (commit === null ? read.version : html`${read.version} · ${commit}`) : (commit ?? "a development build"); |
| @@ -155,8 +159,10 @@ export async function changelogPage(ctx: Ctx): Promise<Response> { | ||
| 155 | 159 | { label: "Everything", href: "/changelog?repo=all", current: choice === "all" }, |
| 156 | 160 | ...others.map((r) => ({ label: r, href: `/changelog?repo=${encodeURIComponent(r)}`, current: choice === r })), |
| 157 | 161 | ]); |
| 162 | const ownRepo = read.own === undefined ? undefined : getRepo(ctx.app.db, ...(read.own.split("/") as [string, string])); | |
| 163 | const readable = ownRepo !== undefined && canRead(ctx.app.db, ownRepo, ctx.auth.user); | |
| 158 | 164 | const body = html`${pageHead("Changelog", { sub: "What went live, as it happens." })}${filters} |
| 159 | <div id="shipped" data-live="${LIVE}" aria-live="polite">${shippedRegion(read, choice, new Date(), "UTC", newestLive(ctx.app.db))}</div>`; | |
| 165 | <div id="shipped" data-live="${LIVE}" aria-live="polite">${shippedRegion(read, choice, new Date(), "UTC", newestLive(ctx.app.db), readable)}</div>`; | |
| 160 | 166 | const response = page({ ctx, title: "Changelog", body, scriptJs: `${liveRegionsJs}\n${localDaysJs}` }); |
| 161 | 167 | notePhase(ctx.request, "render", performance.now() - rendering); |
| 162 | 168 | return response; |
test/changelog.test.ts +20
| @@ -385,4 +385,24 @@ describe("the top line names what is running", () => { | ||
| 385 | 385 | expect(line).toContain("1.2.3 · "); |
| 386 | 386 | expect(line).toContain("8a16183"); |
| 387 | 387 | }); |
| 388 | ||
| 389 | test("the short sha links to the commit in the forge's own repository, escaped", async () => { | |
| 390 | const { shippedRegion } = await import("../src/web/pages/changelog.ts"); | |
| 391 | const oid = "8a16183d0000000000000000000000000000abcd"; | |
| 392 | const out = String(shippedRegion({ live: [], onItsWay: [], version: "dev", commit: oid, own: "a/forge" } as any, "all")); | |
| 393 | expect(out).toContain(`<a class="sha" href="/a/forge/commit/${oid}"`); | |
| 394 | const odd = String(shippedRegion({ live: [], onItsWay: [], version: "dev", commit: oid, own: 'a/"><b>' } as any, "all")); | |
| 395 | expect(odd).not.toContain("<b>"); | |
| 396 | expect(odd).toContain("""); | |
| 397 | }); | |
| 398 | ||
| 399 | test("no link when the reader cannot open the repository, or there is none", async () => { | |
| 400 | const { shippedRegion } = await import("../src/web/pages/changelog.ts"); | |
| 401 | const oid = "8a16183d0000000000000000000000000000abcd"; | |
| 402 | const base = { live: [], onItsWay: [], version: "dev", commit: oid, own: "a/forge" } as any; | |
| 403 | const hidden = String(shippedRegion(base, "all", new Date(), "UTC", undefined, false)); | |
| 404 | expect(hidden).toContain('<span class="sha">8a16183</span>'); | |
| 405 | expect(hidden).not.toContain("/commit/"); | |
| 406 | expect(String(shippedRegion({ ...base, own: undefined }, "all"))).not.toContain("/commit/"); | |
| 407 | }); | |
| 388 | 408 | }); |
new above
offline