Replace NodeJS dict aliases with maps and named field reads
Agents / agent (pull_request) Has been skipped
Check / check (pull_request) Successful in 49s

This commit is contained in:
Danny Kim
2026-10-19 02:30:54 +09:00
parent 32806120b3
commit c8ffb9cc6f
15 changed files with 275 additions and 196 deletions
+5 -1
View File
@@ -15,7 +15,11 @@ const PHASES: [phase: string, firstVariable: string][] = [
test.each(PHASES)("Node loads the %s phase", async (phase, firstVariable) => {
const path = fileURLToPath(new URL(`../src/${phase}/index.ts`, import.meta.url));
const result = await runCommand(process.execPath, [path], { PATH: process.env["PATH"] ?? "" });
const result = await runCommand(
process.execPath,
[path],
new Map([["PATH", process.env["PATH"] ?? ""]]),
);
expect(result.success).toBe(false);
expect(result.stderr).toContain(`${firstVariable} is not set`);
});
+48 -43
View File
@@ -3,24 +3,22 @@ import process from "node:process";
import { assert, expect, test } from "vite-plus/test";
import { parse } from "yaml";
import { makeTempDir, runCommand } from "#testing";
import { inheritedEnvironment, makeTempDir, runCommand } from "#testing";
type JsonObject = NodeJS.Dict<unknown>;
// A parsed YAML or JSON mapping, keyed by its dynamic field names.
type Mapping = Map<string, unknown>;
const isMapping = (value: unknown): value is JsonObject =>
typeof value === "object" && value !== null && !Array.isArray(value);
const mapping = (value: unknown, at: string): JsonObject => {
assert(isMapping(value), at);
return value;
const mapping = (value: unknown, at: string): Mapping => {
assert(typeof value === "object" && value !== null && !Array.isArray(value), at);
return new Map(Object.entries(value));
};
const sequence = (value: unknown, at: string): JsonObject[] => {
const sequence = (value: unknown, at: string): Mapping[] => {
assert(Array.isArray(value), at);
return value.map((entry: unknown, index) => mapping(entry, `${at}[${index}]`));
};
async function yaml(path: string): Promise<JsonObject> {
async function yaml(path: string): Promise<Mapping> {
const value: unknown = parse(await readFile(path, "utf8"));
return mapping(value, path);
}
@@ -33,8 +31,8 @@ async function yamlFiles(): Promise<string[]> {
.filter((path) => !/^(?:\.git|\.superpowers|node_modules)\//u.test(path));
}
const findStep = (steps: JsonObject[], key: string, value: string): JsonObject => {
const step = steps.find((entry) => entry[key] === value);
const findStep = (steps: Mapping[], key: string, value: string): Mapping => {
const step = steps.find((entry) => entry.get(key) === value);
assert(step !== undefined, `${key}: ${value}`);
return step;
};
@@ -47,11 +45,12 @@ test("all committed YAML parses", async () => {
test("the action exposes only the master key and scopes it to preparation", async () => {
const action = await yaml("action.yml");
expect(Object.keys(mapping(action["inputs"], "inputs"))).toStrictEqual(["master-key"]);
const steps = sequence(mapping(action["runs"], "runs")["steps"], "runs.steps");
expect([...mapping(action.get("inputs"), "inputs").keys()]).toStrictEqual(["master-key"]);
const steps = sequence(mapping(action.get("runs"), "runs").get("steps"), "runs.steps");
for (const step of steps) {
if (typeof step["run"] === "string") {
expect(step["run"].includes("\n"), String(step["name"])).toBe(false);
const run = step.get("run");
if (typeof run === "string") {
expect(run.includes("\n"), String(step.get("name"))).toBe(false);
}
}
const checkout = findStep(steps, "uses", "actions/checkout@v4");
@@ -59,16 +58,16 @@ test("the action exposes only the master key and scopes it to preparation", asyn
const agent = findStep(steps, "id", "agent");
const post = findStep(steps, "id", "post");
findStep(steps, "id", "source");
expect(mapping(checkout["with"], "checkout.with")["token"]).toBe("${{ gitea.token }}");
expect(mapping(prepare["env"], "prepare.env")["BOT_AGENTS_MASTER_KEY"]).toBe(
expect(mapping(checkout.get("with"), "checkout.with").get("token")).toBe("${{ gitea.token }}");
expect(mapping(prepare.get("env"), "prepare.env").get("BOT_AGENTS_MASTER_KEY")).toBe(
"${{ inputs.master-key }}",
);
expect(JSON.stringify(agent).includes("BOT_AGENTS_MASTER_KEY")).toBe(false);
expect(JSON.stringify(post).includes("BOT_AGENTS_MASTER_KEY")).toBe(false);
expect(mapping(agent["env"], "agent.env")["GITEA_TOKEN"]).toBe("${{ gitea.token }}");
assert(String(post["if"]).includes("always()"));
expect(JSON.stringify(Object.fromEntries(agent)).includes("BOT_AGENTS_MASTER_KEY")).toBe(false);
expect(JSON.stringify(Object.fromEntries(post)).includes("BOT_AGENTS_MASTER_KEY")).toBe(false);
expect(mapping(agent.get("env"), "agent.env").get("GITEA_TOKEN")).toBe("${{ gitea.token }}");
assert(String(post.get("if")).includes("always()"));
for (const step of [prepare, agent, post]) {
assert(String(step["run"]).includes("steps.source.outputs.path"));
assert(String(step.get("run")).includes("steps.source.outputs.path"));
}
});
@@ -76,12 +75,11 @@ test("the source protection script stages immutable action files", async () => {
const temp = await makeTempDir();
const outputFile = `${temp}/output`;
try {
const result = await runCommand("/bin/bash", ["scripts/protect-source.sh"], {
...process.env,
ACTION_PATH: process.cwd(),
GITHUB_OUTPUT: outputFile,
RUNNER_TEMP: temp,
});
const environment = inheritedEnvironment();
environment.set("ACTION_PATH", process.cwd());
environment.set("GITHUB_OUTPUT", outputFile);
environment.set("RUNNER_TEMP", temp);
const result = await runCommand("/bin/bash", ["scripts/protect-source.sh"], environment);
assert(result.success, result.stderr);
const path = (await readFile(outputFile, "utf8")).trim().slice(5);
@@ -119,27 +117,30 @@ test("module-relative runtime assets exist", async () => {
test("the repository uses its trusted main action", async () => {
const workflow = await yaml(".gitea/workflows/agents.yml");
const job = mapping(mapping(workflow["jobs"], "jobs")["agent"], "jobs.agent");
const permissions = mapping(job["permissions"], "jobs.agent.permissions");
expect(permissions).toStrictEqual({
const job = mapping(mapping(workflow.get("jobs"), "jobs").get("agent"), "jobs.agent");
const permissions = mapping(job.get("permissions"), "jobs.agent.permissions");
expect(Object.fromEntries(permissions)).toStrictEqual({
code: "write",
issues: "write",
"pull-requests": "write",
});
const steps = sequence(job["steps"], "jobs.agent.steps");
expect(steps.findIndex((step) => step["uses"] === "./")).toStrictEqual(-1);
const steps = sequence(job.get("steps"), "jobs.agent.steps");
expect(steps.findIndex((step) => step.get("uses") === "./")).toStrictEqual(-1);
const trusted = findStep(steps, "uses", "https://git.capsulizers.com/commons/bot-agents@main");
expect(mapping(trusted["with"], "trusted.with")["master-key"]).toBe(
expect(mapping(trusted.get("with"), "trusted.with").get("master-key")).toBe(
"${{ secrets.BOT_AGENTS_MASTER_KEY }}",
);
expect(JSON.stringify(workflow).includes("gitea.actor != 'bot'")).toBe(true);
expect(JSON.stringify(Object.fromEntries(workflow)).includes("gitea.actor != 'bot'")).toBe(true);
});
test("CI checks every phase and the root isolation suite", async () => {
const workflow = await yaml(".gitea/workflows/check.yml");
const job = mapping(mapping(workflow["jobs"], "jobs")["check"], "jobs.check");
const commands = sequence(job["steps"], "jobs.check.steps")
.map((step) => (typeof step["run"] === "string" ? step["run"] : ""))
const job = mapping(mapping(workflow.get("jobs"), "jobs").get("check"), "jobs.check");
const commands = sequence(job.get("steps"), "jobs.check.steps")
.map((step) => {
const run = step.get("run");
return typeof run === "string" ? run : "";
})
.join("\n");
// `vp check` type-checks every phase, and `vp test` runs each of them under
// Node as well as the root-only isolation tests.
@@ -176,8 +177,12 @@ test("profile preparation does not receive provider credentials", async () => {
test("central profiles fall back from Codex to Claude to OpenCode", async () => {
const credentials: unknown = JSON.parse(await readFile("profiles.json", "utf8"));
const profiles = sequence(mapping(credentials, "profiles.json")["profiles"], "profiles");
expect(profiles.map((profile) => profile["type"])).toStrictEqual(["codex", "claude", "opencode"]);
expect(profiles[2]?.["model"]).toBe("openrouter/qwen/qwen3.8-27b");
assert(String(profiles[2]?.["token"]).startsWith("v1:"));
const profiles = sequence(mapping(credentials, "profiles.json").get("profiles"), "profiles");
expect(profiles.map((profile) => profile.get("type"))).toStrictEqual([
"codex",
"claude",
"opencode",
]);
expect(profiles[2]?.get("model")).toBe("openrouter/qwen/qwen3.8-27b");
assert(String(profiles[2]?.get("token")).startsWith("v1:"));
});