Files
rea/tests/boundary/filesystem/ciTestHistory.test.ts
T
morluto ea24207b57 perf(ci): pack each test tier from its own timing history (#5799)
* perf(ci): pack each test tier from its own timing history

Fast shards were still ordered with the latest full-suite timing artifact,
which stayed stale across compiled-CLI session reuse. Publish and download
test-timings-fast and test-timings-full separately, and keep the legacy
artifact as a fallback until a tier has its own history.

* perf(ci): drop the shared timing-history fallback

Shard lookup now reads only the artifact for the current tier. A missing
artifact leaves history unset instead of packing from the old test-timings
file.

* test(ci): look up fast history when only full timings exist

The empty-history case now requests the fast tier against a full-tier
artifact and checks that the fast lookup ran and returned nothing. A
missing tier stays a separate test that does not query.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-21 14:58:17 +08:00

325 lines
9.3 KiB
TypeScript

import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
import { delimiter, dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { expect, it } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { executeWorkflowFixture } from "../../support/workflowGit.js";
const script = fileURLToPath(
new URL("../../../scripts/ci/test-history.mjs", import.meta.url),
);
const repository = "example/rea";
const repositoryId = 1;
const now = Date.now();
function artifact(id: number, overrides: Record<string, unknown> = {}) {
return {
id: id + 100,
name: "test-timings-full",
expired: false,
created_at: new Date(now - 60_000).toISOString(),
workflow_run: {
id,
repository_id: repositoryId,
head_repository_id: repositoryId,
head_branch: "main",
},
...overrides,
};
}
function run(id: number, overrides: Record<string, unknown> = {}) {
return {
id,
status: "completed",
conclusion: "success",
path: ".github/workflows/ci.yml@main",
event: "schedule",
created_at: new Date(now - 120_000).toISOString(),
head_branch: "main",
head_repository: { full_name: repository },
...overrides,
};
}
async function invoke(
artifacts: unknown[],
runs: Record<number, unknown>,
options: {
apiError?: boolean;
repository?: string;
repositoryId?: string;
tier?: string;
} = {},
) {
const directory = await createTestTempDirectory("rea-ci-test-history-");
const fakeBin = join(directory, "bin");
await mkdir(fakeBin);
const fixture = join(directory, "api.json");
const calls = join(directory, "api-calls");
const output = join(directory, "github-output");
await writeFile(fixture, JSON.stringify({ artifacts, runs }));
await writeFile(output, "");
await writeFile(calls, "");
const fakeGh = join(fakeBin, "gh");
await writeFile(
fakeGh,
[
"#!/bin/sh",
'printf \'%s\\n\' "$*" >> "$GH_API_CALLS"',
'if [ "$GH_API_ERROR" = "true" ]; then exit 1; fi',
'if [ "$4" = "repos/example/rea/actions/artifacts" ]; then',
' node -e \'const fs=require("node:fs"); const x=JSON.parse(fs.readFileSync(process.env.GH_FIXTURE_RESPONSE,"utf8")); process.stdout.write(JSON.stringify({artifacts:x.artifacts}));\'',
"else",
' run_id="${4##*/}"',
' node -e \'const fs=require("node:fs"); const x=JSON.parse(fs.readFileSync(process.env.GH_FIXTURE_RESPONSE,"utf8")); process.stdout.write(JSON.stringify(x.runs[Number(process.argv[1])] ?? {}));\' "$run_id"',
"fi",
"",
].join("\n"),
);
await chmod(fakeGh, 0o755);
const node24 = dirname(process.execPath);
const result = await executeWorkflowFixture(process.execPath, [script], {
cwd: directory,
env: {
...process.env,
PATH: [fakeBin, node24, process.env.PATH ?? ""].join(delimiter),
GH_FIXTURE_RESPONSE: fixture,
GH_API_CALLS: calls,
GH_API_ERROR: String(options.apiError ?? false),
GH_TOKEN: "fixture-token",
CI_REPOSITORY: options.repository ?? repository,
CI_REPOSITORY_ID: options.repositoryId ?? String(repositoryId),
CI_DEFAULT_BRANCH: "main",
CI_TIMING_TIER: options.tier ?? "",
GITHUB_OUTPUT: output,
},
});
return {
result,
output: await readFile(output, "utf8"),
calls: await readFile(calls, "utf8"),
};
}
it("selects the latest trusted full run that actually published timing history", async () => {
const { result, output, calls } = await invoke(
[
artifact(15),
artifact(14),
artifact(13, {
workflow_run: { ...artifact(13).workflow_run, head_repository_id: 2 },
}),
artifact(12, {
workflow_run: { ...artifact(12).workflow_run, head_branch: "feature" },
}),
artifact(11),
],
{
15: run(15, { conclusion: "failure" }),
14: run(14, { path: ".github/workflows/release.yml" }),
11: run(11, { event: "workflow_dispatch" }),
},
{ tier: "full" },
);
expect(JSON.parse(result.stdout)).toEqual({
run_id: "11",
artifact_name: "test-timings-full",
});
expect(output).toBe("run-id=11\nartifact-name=test-timings-full\n");
expect(calls).toContain("name=test-timings-full");
expect(calls).toContain("per_page=100");
expect(calls.match(/actions\/runs\//gu)).toHaveLength(3);
expect(calls).not.toContain("actions/workflows");
});
it("rejects expired, foreign, old, and pull-request candidates", async () => {
const { result, output } = await invoke(
[
artifact(15, { expired: true }),
artifact(14, {
workflow_run: { ...artifact(14).workflow_run, head_repository_id: 2 },
}),
artifact(13, {
created_at: new Date(now - 31 * 24 * 60 * 60 * 1000).toISOString(),
}),
artifact(12),
],
{
12: run(12, { event: "pull_request" }),
},
{ tier: "full" },
);
expect(JSON.parse(result.stdout)).toEqual({
run_id: "",
artifact_name: "",
});
expect(output).toBe("run-id=\nartifact-name=\n");
});
it("writes an empty run id when GitHub history is unavailable", async () => {
const { result, output } = await invoke(
[],
{},
{
apiError: true,
tier: "full",
},
);
expect(JSON.parse(result.stdout)).toEqual({
run_id: "",
artifact_name: "",
});
expect(output).toBe("run-id=\nartifact-name=\n");
});
it("bounds run lookups to five artifacts even when inventory has more", async () => {
const ids = [25, 24, 23, 22, 21, 20, 19];
const { result, calls } = await invoke(
ids.map((id) => artifact(id)),
Object.fromEntries(
ids.map((id, index) => [
id,
run(id, index < 5 ? { conclusion: "failure" } : {}),
]),
),
{ tier: "full" },
);
expect(JSON.parse(result.stdout)).toEqual({
run_id: "",
artifact_name: "",
});
expect(calls.match(/actions\/runs\//gu)).toHaveLength(5);
});
it("returns empty history without querying for an invalid repository identity", async () => {
const { result, output, calls } = await invoke(
[],
{},
{
repository: "owner/repo?per_page=100",
repositoryId: "not-an-id",
},
);
expect(JSON.parse(result.stdout)).toEqual({
run_id: "",
artifact_name: "",
});
expect(output).toBe("run-id=\nartifact-name=\n");
expect(calls).toBe("");
});
it("selects fast history without reading the full-tier artifact", async () => {
const { result, calls } = await invoke(
[
artifact(32, {
created_at: new Date(now - 30_000).toISOString(),
}),
artifact(31, {
name: "test-timings-fast",
created_at: new Date(now - 90_000).toISOString(),
}),
artifact(30, {
name: "test-timings-fast",
created_at: new Date(now - 20_000).toISOString(),
workflow_run: {
...artifact(30).workflow_run,
head_branch: "feature",
},
}),
],
{
32: run(32, { event: "schedule" }),
31: run(31, { event: "push" }),
},
{ tier: "fast" },
);
expect(JSON.parse(result.stdout)).toEqual({
run_id: "31",
artifact_name: "test-timings-fast",
});
expect(calls).toContain("name=test-timings-fast");
expect(calls).not.toContain("name=test-timings-full");
expect(calls.match(/actions\/runs\//gu)).toHaveLength(1);
});
it("ignores pull-request fast history instead of borrowing another artifact", async () => {
const { result, calls } = await invoke(
[artifact(41, { name: "test-timings-fast" }), artifact(40)],
{
41: run(41, { event: "pull_request" }),
40: run(40, { event: "workflow_dispatch" }),
},
{ tier: "fast" },
);
expect(JSON.parse(result.stdout)).toEqual({
run_id: "",
artifact_name: "",
});
expect(calls).toContain("name=test-timings-fast");
expect(calls).not.toContain("name=test-timings-full");
expect(calls.match(/actions\/runs\//gu)).toHaveLength(1);
});
it("leaves fast history empty when only full-tier history was published", async () => {
const { result, output, calls } = await invoke(
[artifact(70)],
{ 70: run(70, { event: "schedule" }) },
{ tier: "fast" },
);
expect(JSON.parse(result.stdout)).toEqual({
run_id: "",
artifact_name: "",
});
expect(output).toBe("run-id=\nartifact-name=\n");
expect(calls).toContain("name=test-timings-fast");
expect(calls).not.toContain("name=test-timings-full");
expect(calls).not.toMatch(/actions\/runs\//u);
});
it("does not query when the tier has no timing artifact", async () => {
const { result, output, calls } = await invoke([artifact(71)], {
71: run(71, { event: "schedule" }),
});
expect(JSON.parse(result.stdout)).toEqual({
run_id: "",
artifact_name: "",
});
expect(output).toBe("run-id=\nartifact-name=\n");
expect(calls).toBe("");
});
it("selects full-tier history without using a newer fast artifact", async () => {
const { result } = await invoke(
[
artifact(61, {
name: "test-timings-fast",
created_at: new Date(now - 10_000).toISOString(),
}),
artifact(60, {
name: "test-timings-full",
created_at: new Date(now - 80_000).toISOString(),
}),
],
{
61: run(61, { event: "push" }),
60: run(60, { event: "schedule" }),
},
{ tier: "full" },
);
expect(JSON.parse(result.stdout)).toEqual({
run_id: "60",
artifact_name: "test-timings-full",
});
});