mesh/merge-gate pass: builds build-agent, gitea, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did witho…
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery delivered
Every merge to the controller's repository rebuilt the route proxy and the build seat's holder, because their builds read that repository whole. Named, the build seat hands each only its program's build source and the planner moves each only when that changes. A rename was said under its new name alone, so a file moved out of a build source changed nothing the planner could see.
92 lines
5.0 KiB
TypeScript
92 lines
5.0 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { test } from "node:test";
|
|
import { createServer } from "node:http";
|
|
import { GiteaClient } from "../client.ts";
|
|
|
|
test("every page of a pull request's files is read, though the forge caps a page at fifty", async () => {
|
|
const total = 59;
|
|
const server = createServer((req, res) => {
|
|
const url = new URL(req.url ?? "", "http://x");
|
|
const page = Number(url.searchParams.get("page") ?? "1");
|
|
const start = (page - 1) * 50;
|
|
const files = Array.from({ length: Math.max(0, Math.min(50, total - start)) }, (_, i) => ({
|
|
filename: `modules/m${start + i}/x`, status: start + i === 3 ? "deleted" : "changed" }));
|
|
res.setHeader("content-type", "application/json");
|
|
res.end(JSON.stringify(files));
|
|
});
|
|
await new Promise<void>((r) => server.listen(0, r));
|
|
const port = (server.address() as any).port;
|
|
const client = new GiteaClient(`http://127.0.0.1:${port}`, "t");
|
|
const got = await client.listPullFiles("novox", "mesh-catalog", 60);
|
|
server.close();
|
|
assert.equal(got.paths.length, total);
|
|
assert.equal(got.truncated, false);
|
|
assert.equal(new Set(got.paths).size, total);
|
|
assert.deepEqual(got.removed, ["modules/m3/x"], "a file the merge deleted is said as deleted");
|
|
});
|
|
|
|
test("a pass asks only the repositories that moved since the last look, every one before the first", async () => {
|
|
const { movedSince } = await import("../client.ts");
|
|
const repos = [
|
|
{ full_name: "a/old", name: "old", owner: "a", private: false, html_url: "", updated_at: "2026-10-05T10:00:00Z" },
|
|
{ full_name: "a/new", name: "new", owner: "a", private: false, html_url: "", updated_at: "2026-10-05T16:10:02Z" },
|
|
{ full_name: "a/unknown", name: "unknown", owner: "a", private: false, html_url: "" },
|
|
];
|
|
assert.deepEqual(movedSince(repos, "").map((r) => r.name), ["old", "new", "unknown"]);
|
|
assert.deepEqual(movedSince(repos, "2026-10-05T16:09:00.000Z").map((r) => r.name), ["new", "unknown"]);
|
|
assert.deepEqual(movedSince(repos, "2026-10-05T18:10:02+02:00").map((r) => r.name), ["new", "unknown"], "an offset is a moment, not a string");
|
|
});
|
|
|
|
test("the directories above a merge's files that hold a module at the commit are said, the root never", async () => {
|
|
const { directoriesAbove } = await import("../client.ts");
|
|
assert.deepEqual(directoriesAbove(["modules/showcase/index.ts", "modules/showcase/daemon/x.ts", "README.md", "/modules/lib/a.go"]),
|
|
["modules", "modules/lib", "modules/showcase", "modules/showcase/daemon"]);
|
|
const asked: string[] = [];
|
|
const server = createServer((req, res) => {
|
|
const url = new URL(req.url ?? "", "http://x");
|
|
asked.push(`${url.pathname}@${url.searchParams.get("ref")}`);
|
|
const held = ["/api/v1/repos/novox/mesh-catalog/contents/modules/showcase/module.json"];
|
|
res.statusCode = held.includes(url.pathname) ? 200 : 404;
|
|
res.end(res.statusCode === 200 ? "{}" : '{"message":"not found"}');
|
|
});
|
|
await new Promise<void>((r) => server.listen(0, r));
|
|
const port = (server.address() as any).port;
|
|
const client = new GiteaClient(`http://127.0.0.1:${port}`, "t");
|
|
const got = await client.moduleDirsAt("novox", "mesh-catalog", "abc", ["modules/showcase/index.ts", "modules/lib/x.go"]);
|
|
const capped = await client.moduleDirsAt("novox", "mesh-catalog", "abc", ["a/b/c/d.ts"], 2);
|
|
server.close();
|
|
assert.deepEqual(got, ["modules/showcase"], "a directory holding a manifest is a module; one holding none is not");
|
|
assert.ok(asked.every((a) => a.endsWith("@abc")), "looked up at the merge commit");
|
|
assert.equal(capped, null, "past the bound it is not said, and the mesh keeps its old rule");
|
|
});
|
|
|
|
test("a lookup the forge refuses is thrown, not read as no module", async () => {
|
|
const server = createServer((_req, res) => {
|
|
res.statusCode = 500;
|
|
res.end("down");
|
|
});
|
|
await new Promise<void>((r) => server.listen(0, r));
|
|
const port = (server.address() as any).port;
|
|
const client = new GiteaClient(`http://127.0.0.1:${port}`, "t");
|
|
await assert.rejects(client.moduleDirsAt("novox", "mesh-catalog", "abc", ["modules/x/y.ts"]));
|
|
server.close();
|
|
});
|
|
|
|
test("a renamed file is said under its old name too, as gone (novox/hq ADR 0267)", async () => {
|
|
const server = createServer((req, res) => {
|
|
const page = Number(new URL(req.url ?? "", "http://x").searchParams.get("page") ?? "1");
|
|
res.setHeader("content-type", "application/json");
|
|
res.end(JSON.stringify(page > 1 ? [] : [
|
|
{ filename: "internal/elsewhere/moved.go", previous_filename: "internal/broker/moved.go", status: "renamed" },
|
|
{ filename: "README.md", status: "changed" },
|
|
]));
|
|
});
|
|
await new Promise<void>((r) => server.listen(0, r));
|
|
const port = (server.address() as any).port;
|
|
const client = new GiteaClient(`http://127.0.0.1:${port}`, "t");
|
|
const got = await client.listPullFiles("novox", "mesh-controller", 7);
|
|
server.close();
|
|
assert.deepEqual(got.paths, ["internal/elsewhere/moved.go", "internal/broker/moved.go", "README.md"]);
|
|
assert.deepEqual(got.removed, ["internal/broker/moved.go"], "the old name is gone from the tree");
|
|
});
|