test: exercise CI trust and remote cache authority policies

This commit is contained in:
morluto committed 2026-11-10 16:40:47 -05:00
1 parent 38286d4bc3
commit b05f472592
2 files changed
+104 -25

No files matched your search

+102 -24
View File
@@ -10,6 +10,7 @@ import {
writeFile,
} from "node:fs/promises";
import { delimiter, join } from "node:path";
import { runInNewContext } from "node:vm";
import { describe, expect, it } from "vitest";
import { parse } from "yaml";
@@ -17,6 +18,69 @@ import { z } from "zod";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
// These policy expressions use only JS-compatible boolean operators, property
// access, literals and format; exercise the parsed workflow rather than copies.
const evaluatePolicy = (
expression: string,
context: Record<string, unknown>,
): unknown =>
runInNewContext(
expression.replace(/^\$\{\{\s*|\s*\}\}$/gu, ""),
{
...context,
format: (template: string, value: string) =>
template.replace("{0}", value),
},
{ timeout: 100 },
);
const assertRetentionPolicy = (expression: string): void => {
for (const conclusion of [
"success",
"failure",
"timed_out",
"cancelled",
"skipped",
"action_required",
]) {
for (const event of [
"push",
"schedule",
"workflow_dispatch",
"pull_request",
]) {
for (const [repositoryName, branch] of [
["owner/repo", "main"],
["untrusted/fork", "main"],
["owner/repo", "feature"],
]) {
const permitted =
repositoryName === "owner/repo" &&
branch === "main" &&
event !== "pull_request" &&
["success", "failure", "timed_out", "cancelled"].includes(conclusion);
expect(
evaluatePolicy(expression, {
github: {
repository: "owner/repo",
event: {
repository: { default_branch: "main" },
workflow_run: {
conclusion,
event,
head_repository: { full_name: repositoryName },
head_branch: branch,
},
},
},
}),
`${repositoryName}:${branch}:${event}:${conclusion}`,
).toBe(permitted);
}
}
}
};
const repository = process.cwd();
const actionPath = join(repository, ".github/actions/npm-cache/action.yml");
const readAction = async () =>
@@ -512,30 +576,7 @@ it("deletes superseded caches only from the trusted follow-up workflow", async (
actions: "write",
});
const job = workflow.jobs.retain;
expect(job?.if).toContain(
"github.event.workflow_run.conclusion == 'success'",
);
expect(job?.if).toContain(
"github.event.workflow_run.conclusion == 'failure'",
);
expect(job?.if).toContain(
"github.event.workflow_run.conclusion == 'timed_out'",
);
expect(job?.if).toContain(
"github.event.workflow_run.conclusion == 'cancelled'",
);
expect(job?.if).toContain(
"github.event.workflow_run.head_repository.full_name == github.repository",
);
expect(job?.if).toContain(
"github.event.workflow_run.head_branch == github.event.repository.default_branch",
);
expect(job?.if).toContain("github.event.workflow_run.event == 'push'");
expect(job?.if).toContain("github.event.workflow_run.event == 'schedule'");
expect(job?.if).toContain(
"github.event.workflow_run.event == 'workflow_dispatch'",
);
expect(job?.if).not.toContain("pull_request");
assertRetentionPolicy(z.string().parse(job?.if));
const steps = job?.steps ?? [];
expect(steps.some((step) => step.run === "npm ci")).toBe(false);
const checkouts = steps.filter(
@@ -729,6 +770,43 @@ it("exports turbo remote-cache credentials wherever a workflow runs turbo", asyn
expect(cache, `${file}:${name}`).not.toContain("local:rw,remote:r'");
} else expect(cache, `${file}:${name}`).toContain("local:rw,remote:r'");
expect(cache, `${file}:${name}`).toContain("local:rw,remote:rw");
for (const event of [
"push",
"schedule",
"workflow_dispatch",
"pull_request",
"workflow_call",
]) {
for (const ref of ["refs/heads/main", "refs/heads/feature"]) {
for (const grant of [false, true]) {
const permitted =
(grantsReleaseWrite && grant) ||
(ref === "refs/heads/main" &&
(["push", "schedule", "workflow_dispatch"].includes(event) ||
(grantsCalledEvent && event === "workflow_call")));
const context = {
github: {
ref,
event_name: event,
event: { repository: { default_branch: "main" } },
},
inputs: { remote_cache_write: grant },
secrets: { TURBO_TOKEN: "recording-token" },
};
const label = `${file}:${name}:${event}:${ref}:${grant}`;
expect(evaluatePolicy(token, context), label).toBe(
permitted ? "recording-token" : "",
);
expect(evaluatePolicy(cache, context), label).toBe(
permitted
? "local:rw,remote:rw"
: grantsReleaseWrite
? "local:rw"
: "local:rw,remote:r",
);
}
}
}
expect(env.TURBO_TEAM, `${file}:${name}`).toBe("${{ vars.TURBO_TEAM }}");
}
}
@@ -501,6 +501,7 @@ it("selects only a trusted successful ancestor from recent CI push runs", async
}) => {
skip(process.platform === "win32", "the fake gh is a POSIX shell script");
const { directory, base } = await fixture();
const foreignBase = await change(directory, ["README.md"]);
const head = await change(directory, ["src/evm/client.ts"]);
const bin = join(directory, "fake-bin");
await mkdir(bin);
@@ -517,7 +518,7 @@ it("selects only a trusted successful ancestor from recent CI push runs", async
conclusion: "success",
head_branch: "main",
head_repository: { full_name: "untrusted/fork" },
head_sha: base,
head_sha: foreignBase,
},
{
event: "push",