mesh/merge-gate head 8d8dcd5ebb86 merged into trunk cd239283207a — pass: builds gitea, lab → novox, shanks; no bus step; every machine composes with the ch…
mesh/repo-check head 8d8dcd5ebb86 merged into trunk cd239283207a — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered
The lab's credential came from the package team, which also writes the @novox packages, and the branches a run clones are not reviewed yet. The lab now contributes {"access": "read"} to its npm-package-registry requirement, and gitea's provisioner puts such a consumer on a team of its own, readers: code read on the org's repositories, package read, no write, and off the package team. The build agent, which publishes, stays on packages. A stop's SIGTERM to the run's process group killed the wrapper before it removed the credential file. The run's script now removes it as soon as its clones are done and traps every way it ends, and a run's start and lab_check remove what a crash or a reboot left.
57 lines
2.6 KiB
TypeScript
57 lines
2.6 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { grant, holds, PACKAGE_TEAM, READ_TEAM, teamFor, type Forge } from "../provisioner/teams.ts";
|
|
|
|
// Defends novox/hq issue 624: the lab reads the forge with a credential of its own that can write no
|
|
// package. A consumer that contributes {"access": "read"} joins a team with code and package read only.
|
|
|
|
function aForge(): { forge: Forge; did: string[] } {
|
|
const did: string[] = [];
|
|
const teams: Record<string, number> = {};
|
|
const forge: Forge = {
|
|
async ensureOrg(org) { did.push(`org ${org}`); },
|
|
async ensureTeam(org, team, packageWrite) {
|
|
did.push(`team ${org}/${team} packages:${packageWrite ? "write" : "read"}`);
|
|
return (teams[team] ??= Object.keys(teams).length + 1);
|
|
},
|
|
async ensureUser(username) { did.push(`user ${username}`); },
|
|
async addUserToTeam(id, username) { did.push(`add ${username} to ${id}`); },
|
|
async removeUserFromTeam(id, username) { did.push(`remove ${username} from ${id}`); },
|
|
async holdsTeamMember(org, team, username) { did.push(`holds ${username} in ${org}/${team}`); return true; },
|
|
};
|
|
return { forge, did };
|
|
}
|
|
|
|
test("a consumer that asks nothing, or write, publishes: the package team", () => {
|
|
assert.deepEqual(teamFor({}), { team: PACKAGE_TEAM, packageWrite: true });
|
|
assert.deepEqual(teamFor({ access: "write" }), { team: PACKAGE_TEAM, packageWrite: true });
|
|
});
|
|
|
|
test("a consumer that asks to read joins the readers, who write no package", () => {
|
|
assert.deepEqual(teamFor({ access: "read" }), { team: READ_TEAM, packageWrite: false });
|
|
assert.throws(() => teamFor({ access: "admin" }), /not "read" or "write"/);
|
|
});
|
|
|
|
test("a reader is made, put on the readers team, and taken off the package team", async () => {
|
|
const { forge, did } = aForge();
|
|
await grant(forge, { as: "lab-shanks", password: "pw", values: { access: "read" } });
|
|
assert.deepEqual(did, [
|
|
"org novox",
|
|
"team novox/readers packages:read",
|
|
"user lab-shanks",
|
|
"add lab-shanks to 1",
|
|
"team novox/packages packages:write",
|
|
"remove lab-shanks from 2",
|
|
]);
|
|
did.length = 0;
|
|
await holds(forge, { as: "lab-shanks", password: "pw", values: { access: "read" } });
|
|
assert.deepEqual(did, ["holds lab-shanks in novox/readers"]);
|
|
});
|
|
|
|
test("a publisher is made and put on the package team, as before", async () => {
|
|
const { forge, did } = aForge();
|
|
await grant(forge, { as: "build-agent-ace", password: "pw", values: {} });
|
|
assert.deepEqual(did, ["org novox", "team novox/packages packages:write", "user build-agent-ace", "add build-agent-ace to 1"]);
|
|
});
|