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

A repository's danger-zone labels live in one module, read by Settings and search #5721

Merged opened this

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

Merged

mason/forge:mason/5657-a-repository-s-danger-zone-labels-live-i → main 1 commit fork

  • Merged. mason/5657-a-repository-s-danger-zone-labels-live-i was merged into main as c06a7f9.

Review

Sign in to review this change.
4 files changed +47 −6
src/web/danger_words.ts added +11
@@ -0,0 +1,11 @@
1 /**
2 * The words on a repository's danger zone: the two acts that cannot be
3 * undone. Settings shows them as headings and buttons, and search's
4 * confirmation names the same act, so each sentence is said here once.
5 */
6
7 /** Stops production and every preview and removes their data. */
8 export const STOP_APP = "Stop running as an app";
9
10 /** Deletes the repository, its issues, pulls and git objects. */
11 export const DELETE_REPO = "Delete this repository";
src/web/pages/search.ts +3 −2
@@ -30,6 +30,7 @@ import type { Ctx } from "../../http/context.ts";
3030 import { notePhase, takeSessionTime, timePhase, timePhaseAsync } from "../../core/route_timing.ts";
3131 import { notFoundPage, pageHead } from "../chrome.ts";
3232 import { html, when, type Html } from "../html.ts";
33 import { DELETE_REPO, STOP_APP } from "../danger_words.ts";
3334 import { icon } from "../icons.ts";
3435 import { page } from "../layout.ts";
3536 import { browseBase } from "../scope.ts";
@@ -518,7 +519,7 @@ const DESTRUCTIVE: {
518519 {
519520 pattern: /^\/([^/]+)\/([^/]+)\/settings\/delete$/,
520521 describe: (m) => ({
521 verb: "Delete this repository",
522 verb: DELETE_REPO,
522523 title: `Delete ${m[1]}/${m[2]}?`,
523524 detail:
524525 "Every issue, pull request, comment and webhook goes with it, and the git objects are removed from disk. Forks are detached first and keep working. This cannot be undone.",
@@ -638,7 +639,7 @@ const DESTRUCTIVE: {
638639 {
639640 pattern: /^\/([^/]+)\/([^/]+)\/settings\/app\/disable$/,
640641 describe: (m) => ({
641 verb: "Stop running as an app",
642 verb: STOP_APP,
642643 title: `Stop running ${m[1]}/${m[2]} as an app?`,
643644 detail:
644645 "Production and every preview stop, and their data directories and checkouts are removed from disk. The repository and its code are untouched. Run it as an app again later and it starts from empty data.",
src/web/pages/settings.ts +5 −4
@@ -96,6 +96,7 @@ import { pageTitle } from "../studio/nouns.ts";
9696 import { appHref } from "./apps.ts";
9797 import { field, readForm, type Form } from "../form.ts";
9898 import { html, when, type Html } from "../html.ts";
99 import { DELETE_REPO, STOP_APP } from "../danger_words.ts";
99100 import { icon } from "../icons.ts";
100101 import { flashTo, page, redirect } from "../layout.ts";
101102 import type { Flash } from "../flash.ts";
@@ -733,13 +734,13 @@ function appSettingsView(
733734 <div class="form-actions">
734735 ${confirmAction({
735736 action: `${base}/settings/app/disable`,
736 verb: "Stop running as an app",
737 verb: STOP_APP,
737738 })}
738739 </div>`,
739740 {
740741 tone: "danger",
741742 head: html`${icon("alert")}
742 <h2>Stop running as an app</h2>`,
743 <h2>${STOP_APP}</h2>`,
743744 },
744745 )}
745746 </div>`;
@@ -2081,13 +2082,13 @@ export function dangerPage(ctx: Ctx): Response {
20812082 <div class="form-actions">
20822083 ${confirmAction({
20832084 action: `${base}/settings/delete`,
2084 verb: "Delete this repository",
2085 verb: DELETE_REPO,
20852086 })}
20862087 </div>`,
20872088 {
20882089 tone: "danger",
20892090 head: html`${icon("alert")}
2090 <h2>Delete this repository</h2>`,
2091 <h2>${DELETE_REPO}</h2>`,
20912092 },
20922093 );
20932094 const response = settingsPageResponse(ctx, repo, "danger", "Danger zone", body);
test/danger-words.test.ts added +28
@@ -0,0 +1,28 @@
1 /**
2 * A repository's danger-zone labels are said once, in src/web/danger_words.ts
3 * (#5657). The pages that show them import them; a copy typed back into one
4 * of them fails here.
5 */
6
7 import { expect, test } from "bun:test";
8 import { readFileSync } from "node:fs";
9 import { join } from "node:path";
10 import { DELETE_REPO, STOP_APP } from "../src/web/danger_words.ts";
11
12 const root = join(import.meta.dir, "..");
13 const readers = ["src/web/pages/settings.ts", "src/web/pages/search.ts"];
14
15 test("the module says each sentence as it always read", () => {
16 expect(STOP_APP).toBe("Stop running as an app");
17 expect(DELETE_REPO).toBe("Delete this repository");
18 });
19
20 test("no file that shows them types a sentence out again", () => {
21 for (const file of readers) {
22 const text = readFileSync(join(root, file), "utf8");
23 expect(text).toContain('from "../danger_words.ts"');
24 for (const sentence of [STOP_APP, DELETE_REPO]) {
25 expect({ file, has: text.includes(sentence) }).toEqual({ file, has: false });
26 }
27 }
28 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs