Answer stability round 1: 0 🔴, 3 🟡 (0 misread); the description test refuses an empty one and needs a sentence start, the PATCH body is a tested pure function, the trial-stack block moves to Quick start
This commit is contained in:
@@ -2,7 +2,7 @@ import assert from "node:assert/strict";
|
|||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
import { test } from "node:test";
|
import { test } from "node:test";
|
||||||
|
|
||||||
test("auto-release's checkout persists no credentials, so the tag push authenticates as renovate-bot", () => {
|
test("auto-release's checkout doesn't persist credentials, so the tag push authenticates as renovate-bot", () => {
|
||||||
const workflow = readFileSync(".gitea/workflows/renovate.yml", "utf8");
|
const workflow = readFileSync(".gitea/workflows/renovate.yml", "utf8");
|
||||||
const job = workflow.slice(workflow.indexOf("\n auto-release:"));
|
const job = workflow.slice(workflow.indexOf("\n auto-release:"));
|
||||||
const checkout = job.slice(job.indexOf("actions/checkout@"), job.indexOf("\n - name:"));
|
const checkout = job.slice(job.indexOf("actions/checkout@"), job.indexOf("\n - name:"));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
import { test } from "node:test";
|
import { test } from "node:test";
|
||||||
import { DESCRIPTION, jwtFrom, leftoverPlaceholders, renderOverview } from "./dockerhub-overview.ts";
|
import { DESCRIPTION, hubPatch, jwtFrom, leftoverPlaceholders, renderOverview } from "./dockerhub-overview.ts";
|
||||||
|
|
||||||
const TEMPLATE = "release-tooling/dockerhub-overview.md.tmpl";
|
const TEMPLATE = "release-tooling/dockerhub-overview.md.tmpl";
|
||||||
const template = () => readFileSync(TEMPLATE, "utf8");
|
const template = () => readFileSync(TEMPLATE, "utf8");
|
||||||
@@ -49,9 +49,9 @@ test("jwtFrom accepts only a non-empty string token, never throwing on a hostile
|
|||||||
|
|
||||||
test("the short description opens a README sentence and fits Docker Hub's 100 characters", () => {
|
test("the short description opens a README sentence and fits Docker Hub's 100 characters", () => {
|
||||||
const readme = readFileSync("README.md", "utf8").replaceAll("**", "");
|
const readme = readFileSync("README.md", "utf8").replaceAll("**", "");
|
||||||
assert.ok(DESCRIPTION.length <= 100, `${DESCRIPTION.length} characters`);
|
assert.ok(DESCRIPTION.trim() !== "" && DESCRIPTION.length <= 100, `${DESCRIPTION.length} characters`);
|
||||||
const escaped = DESCRIPTION.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
const escaped = DESCRIPTION.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
assert.match(readme, new RegExp(`^${escaped}(?=[\\s.:,])`, "m"));
|
assert.match(readme, new RegExp(`(?:\\n\\n|\\.\\s)${escaped}(?=[\\s.:,])`));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("every command the overview shows, the README shows too", () => {
|
test("every command the overview shows, the README shows too", () => {
|
||||||
@@ -65,5 +65,9 @@ test("every command the overview shows, the README shows too", () => {
|
|||||||
const shown = new Set(commands(readFileSync("README.md", "utf8")));
|
const shown = new Set(commands(readFileSync("README.md", "utf8")));
|
||||||
const published = commands(template());
|
const published = commands(template());
|
||||||
assert.ok(published.length > 0, `${TEMPLATE} should show commands`);
|
assert.ok(published.length > 0, `${TEMPLATE} should show commands`);
|
||||||
for (const command of published) assert.ok(shown.has(command), `${TEMPLATE} runs ${command}, which README.md doesn't show`);
|
for (const command of published) assert.ok(shown.has(command), `${TEMPLATE} shows ${command}, which README.md doesn't`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("the PATCH carries the short description beside the overview", () => {
|
||||||
|
assert.deepEqual(hubPatch("# page"), { description: DESCRIPTION, full_description: "# page" });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// Publishes the Docker Hub repository overview from dockerhub-overview.md.tmpl, rendering
|
|
||||||
// `{{VERSION}}` to the release being published, and the short description.
|
|
||||||
|
|
||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
@@ -10,6 +7,10 @@ const VERSION = /^\d+\.\d+\.\d+$/;
|
|||||||
|
|
||||||
export const DESCRIPTION = "A self-hostable foundation for server-rendered web applications";
|
export const DESCRIPTION = "A self-hostable foundation for server-rendered web applications";
|
||||||
|
|
||||||
|
export function hubPatch(overview: string): { description: string; full_description: string } {
|
||||||
|
return { description: DESCRIPTION, full_description: overview };
|
||||||
|
}
|
||||||
|
|
||||||
export function renderOverview(source: string, version: string): string {
|
export function renderOverview(source: string, version: string): string {
|
||||||
return source.replaceAll("{{VERSION}}", version);
|
return source.replaceAll("{{VERSION}}", version);
|
||||||
}
|
}
|
||||||
@@ -83,7 +84,7 @@ async function main(): Promise<number> {
|
|||||||
if (!jwt) return fail("Docker Hub login returned no token");
|
if (!jwt) return fail("Docker Hub login returned no token");
|
||||||
|
|
||||||
const res = await post(`${HUB}/repositories/${repo}/`, {
|
const res = await post(`${HUB}/repositories/${repo}/`, {
|
||||||
body: JSON.stringify({ description: DESCRIPTION, full_description: body }),
|
body: JSON.stringify(hubPatch(body)),
|
||||||
headers: { authorization: `Bearer ${jwt}`, "content-type": "application/json" },
|
headers: { authorization: `Bearer ${jwt}`, "content-type": "application/json" },
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user