CI: validate every push and pull request; stars refreshed on main and weekly

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-04 21:07:15 -04:00
1 parent 6eef671f14
commit 912bc328cf
8 files changed
+194 -46

No files matched your search

+1 -45
View File
@@ -3,52 +3,8 @@ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { test } from "node:test";
import { crc32, deflateSync } from "node:zlib";
import { read, weighted } from "../scripts/catalog.mjs";
function chunk(type, data) {
const head = Buffer.alloc(8);
head.writeUInt32BE(data.length);
head.write(type, 4, "latin1");
const sum = Buffer.alloc(4);
sum.writeUInt32BE(crc32(Buffer.concat([head.subarray(4), data])));
return Buffer.concat([head, data, sum]);
}
/** A gray PNG `side` pixels square whose data is one pixel, its scanline led by `filter`. */
function png(filter, side = 1) {
const header = Buffer.from([0, 0, 0, side, 0, 0, 0, side, 8, 0, 0, 0, 0]);
const image = deflateSync(Buffer.from([filter, 1]));
return Buffer.concat([Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), chunk("IHDR", header), chunk("IDAT", image), chunk("IEND", Buffer.alloc(0))]);
}
const PNG = png(0);
const broken = Buffer.from(PNG);
broken[broken.length - 20] ^= 0xff;
const good = {
id: "tally",
name: "Tally",
author: "Ada",
description: "Counts things.",
category: "work",
platforms: ["macOS", "Linux"],
website: null,
source: "https://github.com/ada/tally",
publishedAt: "2026-10-04T00:00:00Z",
previews: ["preview0.png"],
};
/** A catalog in a temp folder: one app, its files, and featured.json. */
function catalog({ app = good, folder = "tally", files = {}, featured = [] } = {}) {
const root = mkdtempSync(join(tmpdir(), "showcase-"));
const dir = join(root, "apps", folder);
mkdirSync(dir, { recursive: true });
writeFileSync(join(dir, "manifest.json"), JSON.stringify(app));
writeFileSync(join(dir, "preview0.png"), PNG);
for (const [name, body] of Object.entries(files)) writeFileSync(join(dir, name), body);
writeFileSync(join(root, "featured.json"), JSON.stringify(featured));
return root;
}
import { broken, catalog, good, PNG, png } from "./fixture.mjs";
test("a good app reads back with its README", () => {
const root = catalog({ files: { "README.md": "# Tally\n\nSee [the source](https://github.com/ada/tally).\n\n![Main](preview0.png)\n" }, featured: ["tally"] });
+48
View File
@@ -0,0 +1,48 @@
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { crc32, deflateSync } from "node:zlib";
function chunk(type, data) {
const head = Buffer.alloc(8);
head.writeUInt32BE(data.length);
head.write(type, 4, "latin1");
const sum = Buffer.alloc(4);
sum.writeUInt32BE(crc32(Buffer.concat([head.subarray(4), data])));
return Buffer.concat([head, data, sum]);
}
/** A gray PNG `side` pixels square whose data is one pixel, its scanline led by `filter`. */
export function png(filter, side = 1) {
const header = Buffer.from([0, 0, 0, side, 0, 0, 0, side, 8, 0, 0, 0, 0]);
const image = deflateSync(Buffer.from([filter, 1]));
return Buffer.concat([Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), chunk("IHDR", header), chunk("IDAT", image), chunk("IEND", Buffer.alloc(0))]);
}
export const PNG = png(0);
export const broken = Buffer.from(PNG);
broken[broken.length - 20] ^= 0xff;
export const good = {
id: "tally",
name: "Tally",
author: "Ada",
description: "Counts things.",
category: "work",
platforms: ["macOS", "Linux"],
website: null,
source: "https://github.com/ada/tally",
publishedAt: "2026-10-04T00:00:00Z",
previews: ["preview0.png"],
};
/** A catalog in a temp folder: one app, its files, and featured.json. */
export function catalog({ app = good, folder = "tally", files = {}, featured = [] } = {}) {
const root = mkdtempSync(join(tmpdir(), "showcase-"));
const dir = join(root, "apps", folder);
mkdirSync(dir, { recursive: true });
writeFileSync(join(dir, "manifest.json"), JSON.stringify(app));
writeFileSync(join(dir, "preview0.png"), PNG);
for (const [name, body] of Object.entries(files)) writeFileSync(join(dir, name), body);
writeFileSync(join(root, "featured.json"), JSON.stringify(featured));
return root;
}
+33
View File
@@ -0,0 +1,33 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { test } from "node:test";
import { refresh } from "../scripts/stars.mjs";
import { catalog, good } from "./fixture.mjs";
const manifest = (root) => JSON.parse(readFileSync(join(root, "apps", "tally", "manifest.json"), "utf8"));
test("a new count writes stars and the time", async () => {
const root = catalog();
const asked = [];
const changed = await refresh(root, async (repo) => (asked.push(repo), 42), "2026-10-05T00:00:00.000Z");
assert.deepEqual(asked, [{ owner: "ada", repo: "tally" }]);
assert.deepEqual(changed, ["tally"]);
assert.equal(manifest(root).stars, 42);
assert.equal(manifest(root).starsUpdatedAt, "2026-10-05T00:00:00.000Z");
});
test("the same count keeps the time", async () => {
const root = catalog({ app: { ...good, stars: 42, starsUpdatedAt: "2026-10-01T00:00:00Z" } });
assert.deepEqual(await refresh(root, async () => 42, "2026-10-05T00:00:00.000Z"), []);
assert.equal(manifest(root).starsUpdatedAt, "2026-10-01T00:00:00Z");
});
test("an app off GitHub is not asked", async () => {
const root = catalog({ app: { ...good, source: null, website: "https://tally.app/" } });
assert.deepEqual(await refresh(root, async () => assert.fail("asked"), "2026-10-05T00:00:00.000Z"), []);
});
test("a bad count fails", async () => {
await assert.rejects(refresh(catalog(), async () => undefined, "2026-10-05T00:00:00.000Z"), /GitHub gave undefined stars/);
});