Files
cloudflare__vinext/tests/performance-benchmarks.test.ts

1307 lines
49 KiB
TypeScript

import { execFileSync, spawnSync } from "node:child_process";
import {
chmodSync,
cpSync,
mkdirSync,
mkdtempSync,
readFileSync,
symlinkSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { gzipSync } from "node:zlib";
import { describe, expect, it } from "vite-plus/test";
import {
isNextjsBenchmarkInput,
nextjsBenchmarkInputTreeJq,
nextjsInputFingerprint,
} from "../benchmarks/perf/nextjs-input-fingerprint.mts";
import { DEFAULT_PAIRED_ROUNDS, pairedRevisionOrder } from "../benchmarks/perf/pairing.mts";
describe("paired performance benchmarks", () => {
it("pins the TypeScript dependencies required by the standalone Next.js benchmark", () => {
const packageJson = JSON.parse(
readFileSync(join(import.meta.dirname, "../benchmarks/nextjs/package.json"), "utf8"),
);
const scenarios = JSON.parse(
readFileSync(join(import.meta.dirname, "../benchmarks/perf/scenarios.json"), "utf8"),
);
expect(packageJson.devDependencies).toMatchObject({
"@types/node": "25.9.2",
"@types/react": "19.2.16",
// Next.js 16 resolves typescript/lib/typescript.js, which native TypeScript 7 removed.
typescript: "5.9.3",
});
expect(
scenarios.setup.find(
(setup: { implementationId?: string }) => setup.implementationId === "nextjs",
).command,
).toEqual([
"npm",
"install",
"--no-save",
"typescript@5.9.3",
"@types/node@25.9.2",
"@types/react@19.2.16",
]);
});
it("alternates base/head order across rounds", () => {
expect(DEFAULT_PAIRED_ROUNDS % 2).toBe(0);
expect(pairedRevisionOrder(0)).toEqual(["base", "head"]);
expect(pairedRevisionOrder(1)).toEqual(["head", "base"]);
expect(pairedRevisionOrder(2)).toEqual(["base", "head"]);
});
it("installs the base checkout before overlaying trusted benchmark files", () => {
const workflow = readFileSync(
join(import.meta.dirname, "../.github/workflows/perf.yml"),
"utf8",
);
const prepareManifests = workflow.indexOf("- name: Prepare trusted benchmark manifests");
const installBase = workflow.indexOf("- name: Install base dependencies");
const installHarness = workflow.indexOf("- name: Install trusted performance harness");
const manifestStep = workflow.slice(prepareManifests, installBase);
expect(prepareManifests).toBeGreaterThan(-1);
expect(installBase).toBeGreaterThan(prepareManifests);
expect(installHarness).toBeGreaterThan(installBase);
expect(manifestStep).not.toContain('roots+=(".perf-base")');
});
it("keeps untrusted benchmark processes away from baselines and result files", () => {
const workflow = readFileSync(
join(import.meta.dirname, "../.github/workflows/perf.yml"),
"utf8",
);
const runner = readFileSync(
join(import.meta.dirname, "../benchmarks/perf/run-scenarios.mjs"),
"utf8",
);
const coldStart = readFileSync(
join(import.meta.dirname, "../benchmarks/perf/cold-start.mjs"),
"utf8",
);
const buildTime = readFileSync(
join(import.meta.dirname, "../benchmarks/perf/build-time.mjs"),
"utf8",
);
expect(workflow).toContain("vinext-perf-head");
expect(workflow).toContain("vinext-perf-base");
expect(workflow).toContain(
'echo "VINEXT_PERF_BASE_ROOT=$RUNNER_TEMP/vinext-perf-base/checkout"',
);
expect(workflow).toContain('mv .perf-base-staging "$VINEXT_PERF_BASE_ROOT"');
expect(workflow).toContain('chmod 700 "$(dirname "$VINEXT_PERF_BASE_ROOT")"');
expect(workflow).toContain("- name: Validate performance workspace paths");
expect(workflow).toContain('if [ ! -d "$path" ] || [ -L "$path" ]; then');
expect(workflow).toContain('if [ "$(realpath "$path")" != "$path" ]; then');
expect(workflow).toContain("benchmarks/vinext/app");
expect(workflow).toContain("benchmarks/nextjs/app");
expect(workflow).toContain("rm -rf .perf-base-staging .perf-manifests .perf-harness");
expect(workflow).toContain("grant_write_paths()");
expect(workflow).toContain("packages/vinext/dist");
expect(workflow).toContain("node_modules/.vite/task-cache");
expect(workflow).toContain("benchmarks/nextjs/node_modules");
expect(workflow).toContain('sudo chmod +t "$path"');
expect(workflow).toContain('sudo setfacl -m u:"$user":rwx "$path"');
expect(workflow).toContain('sudo setfacl -m d:u:"$user":rwx,d:u:"$USER":rwx "$path"');
expect(workflow).toContain('sudo chown -R "$user":"$user" "$path"');
expect(workflow).toContain('if [ -L "$path" ]; then');
expect(workflow).toContain('case "$(realpath "$path")" in');
expect(workflow).toContain('sudo chmod -R u+rwX "$path"');
expect(workflow).toContain('sudo setfacl -R -m u:"$USER":rwX "$path"');
expect(workflow).toContain('sudo -u "$user" test -w "$path"');
expect(workflow).not.toContain('setfacl -R -m u:vinext-perf-head:rwX "$GITHUB_WORKSPACE"');
expect(workflow).toContain("- name: Lock benchmark inputs after setup");
expect(workflow).toContain('"$root/packages/vinext/dist"');
expect(workflow).toContain('"$root/packages/cloudflare/dist"');
expect(workflow).toContain('"$root/node_modules/.vite/task-cache"');
expect(workflow).toContain("benchmarks/vinext/node_modules/.vite-temp");
expect(workflow).toContain('sudo chown -R "$USER":"$USER" "$path"');
expect(workflow).toContain("benchmarks/perf/validate-profile-traces.mjs");
expect(workflow).toContain(
"github.event.pull_request.head.repo.full_name != github.repository && github.event.pull_request.base.sha",
);
expect(workflow).toContain("github.event.pull_request.head.sha || github.sha");
expect(workflow).toContain(
'cp -R .perf-harness/benchmarks/vinext "$trusted_harness/benchmarks/vinext"',
);
expect(workflow).toContain(
'cp -R .perf-harness/benchmarks/nextjs "$trusted_harness/benchmarks/nextjs"',
);
expect(workflow).toContain('if [ -f "$trace_validator" ]; then');
expect(workflow).not.toContain('u:vinext-perf:rwx "$VINEXT_PERF_RESULTS_ROOT"');
expect(runner).toContain("VINEXT_PERF_TARGET_USER: userForRoot(root)");
expect(runner).toContain('!name.startsWith("VINEXT_PERF_")');
expect(runner).toContain('execFileSync("which", ["vp"]');
expect(runner).not.toContain('join(root, "node_modules/.bin/vp")');
expect(runner).toContain("function profilerCommand() {\n return [profilerBin];\n}");
expect(runner).toContain('for (const signal of ["-STOP", "-KILL"])');
expect(runner).toContain('["ps", "-u", user, "-o", "pid=,stat=,args="]');
expect(runner).toContain("!/^\\s*\\d+\\s+\\S*Z/.test(process)");
expect(runner).toContain("for (let attempt = 0; attempt < 20; attempt++)");
expect(runner).toContain("await cleanupTargetUser(root)");
expect(runner).toContain("else await runUntrusted(");
expect(runner).toContain(
"await runUntrusted(command[0], command.slice(1), timingEnv, root, root)",
);
expect(runner).toContain("await runUntrusted(\n profiler[0]");
expect(coldStart).toContain('name.startsWith("VINEXT_PERF_")');
expect(coldStart).toContain('const profiling = process.env.VINEXT_PERF_PROFILE === "true"');
expect(coldStart).toContain('join(projectDir, "node_modules/vite-plus/bin/vp")');
expect(coldStart).toContain("detached: true");
expect(coldStart).toContain("return targetUser && !profiling");
expect(coldStart).toContain("await Promise.all(paths.map(clearDirectory))");
expect(coldStart).toContain("const entries = await readdir(path)");
expect(buildTime).toContain('name.startsWith("VINEXT_PERF_")');
expect(buildTime).toContain("const entries = await readdir(outputDirectory)");
expect(buildTime).toContain('const profiling = process.env.VINEXT_PERF_PROFILE === "true"');
expect(buildTime).toContain('join(projectDir, "node_modules/vite-plus/bin/vp")');
expect(buildTime).toContain(
"globalThis.process.execve(command, [command, ...args], targetEnvironment())",
);
expect(buildTime).toContain("return targetUser && !profiling");
expect(buildTime).toContain("detached: true");
expect(buildTime).not.toContain(
'rm(join(projectDir, framework === "vinext" ? "dist" : ".next")',
);
});
it("requires dispatched workflow code to come from main", () => {
const workflow = readFileSync(
join(import.meta.dirname, "../.github/workflows/perf.yml"),
"utf8",
);
const validation = readFileSync(
join(import.meta.dirname, "../benchmarks/perf/validate-results.mjs"),
"utf8",
);
expect(workflow).toContain("- name: Validate dispatched workflow ref");
expect(workflow).toContain('[ "$VINEXT_PERF_WORKFLOW_SHA" != "$(git rev-parse origin/main)" ]');
expect(validation).toContain("sourceRun.head_repository?.full_name === repository");
expect(validation).toContain('sourceRun.head_branch === "main"');
expect(validation).toContain("Dispatched workflow ref is not the default branch");
});
it("keeps Next.js enabled until the trusted base supports fingerprinting", () => {
const workflow = readFileSync(
join(import.meta.dirname, "../.github/workflows/perf.yml"),
"utf8",
);
const detectionStep = workflow.slice(
workflow.indexOf("- name: Detect Next.js benchmark input changes"),
workflow.indexOf("- name: Prepare trusted benchmark manifests"),
);
const compatibilityGuard = detectionStep.indexOf('[ ! -f "$fingerprint_script" ]');
const fingerprintInvocation = detectionStep.indexOf(
'head_fingerprint=$(node "$fingerprint_script" .)',
);
expect(compatibilityGuard).toBeGreaterThan(-1);
expect(detectionStep).toContain('grep -q "skippedImplementations" "$base_validator"');
expect(detectionStep).toContain("keeping Next.js for rollout compatibility");
expect(detectionStep).toContain("exit 0");
expect(fingerprintInvocation).toBeGreaterThan(compatibilityGuard);
});
it("isolates pull request comment permissions from benchmark publishing", () => {
const workflow = readFileSync(
join(import.meta.dirname, "../.github/workflows/perf-publish.yml"),
"utf8",
);
const publishJob = workflow.slice(
workflow.indexOf(" publish:"),
workflow.indexOf(" comment:"),
);
const commentJob = workflow.slice(workflow.indexOf(" comment:"));
expect(publishJob).toContain("actions: read");
expect(publishJob).toContain("contents: read");
expect(publishJob).not.toContain("issues: write");
expect(commentJob).toContain("actions: read");
expect(commentJob).toContain("pull-requests: write");
expect(commentJob).not.toContain("issues: write");
expect(commentJob).not.toContain("secrets.");
expect(commentJob).not.toContain("actions/checkout");
expect(commentJob).not.toContain("performance-artifact");
});
it("fingerprints every Next.js measurement input", () => {
const entries = [
gitTreeEntry(".github/workflows/perf.yml", "0"),
gitTreeEntry("benchmarks/nextjs/package.json", "1"),
gitTreeEntry("benchmarks/nextjs/next.config.ts", "2"),
gitTreeEntry("benchmarks/generate-app.mjs", "3"),
gitTreeEntry("benchmarks/perf/scenarios.json", "4"),
gitTreeEntry("benchmarks/perf/cold-start.mjs", "5"),
gitTreeEntry("benchmarks/perf/normalize-results.mjs", "5a"),
gitTreeEntry("benchmarks/perf/format-pr-comment.mjs", "6"),
gitTreeEntry("benchmarks/nextjs/app/page.tsx", "7"),
];
const fingerprint = nextjsInputFingerprint(entries);
for (const path of [
".github/workflows/perf.yml",
"benchmarks/nextjs/package.json",
"benchmarks/nextjs/next.config.ts",
"benchmarks/generate-app.mjs",
"benchmarks/perf/scenarios.json",
"benchmarks/perf/cold-start.mjs",
"benchmarks/perf/normalize-results.mjs",
]) {
expect(isNextjsBenchmarkInput(path)).toBe(true);
expect(
nextjsInputFingerprint(
entries.map((entry) =>
entry.path === path ? { ...entry, sha: `${entry.sha}x` } : entry,
),
),
).not.toBe(fingerprint);
}
expect(isNextjsBenchmarkInput("benchmarks/perf/format-pr-comment.mjs")).toBe(false);
expect(isNextjsBenchmarkInput("benchmarks/nextjs/app/page.tsx")).toBe(false);
});
const jqAvailable = spawnSync("jq", ["--version"], { encoding: "utf8" }).status === 0;
(jqAvailable ? it : it.skip)("keeps the remote tree jq predicate aligned with JS inputs", () => {
const entries = [
richGitTreeEntry(".github/workflows/perf.yml", "0"),
richGitTreeEntry("benchmarks/generate-app.mjs", "1"),
richGitTreeEntry("benchmarks/nextjs/package.json", "2"),
richGitTreeEntry("benchmarks/nextjs/app", "3"),
richGitTreeEntry("benchmarks/nextjs/app/page.tsx", "4"),
richGitTreeEntry("benchmarks/nextjs/appfoo/page.tsx", "5"),
richGitTreeEntry("benchmarks/perf/scenarios.json", "6"),
richGitTreeEntry("benchmarks/perf/README.md", "7"),
richGitTreeEntry("benchmarks/perf/format-pr-comment.mjs", "8"),
richGitTreeEntry("benchmarks/perf/upload-results.mjs", "9"),
richGitTreeEntry("benchmarks/perf/validate-results.mjs", "10"),
richGitTreeEntry("packages/vinext/src/index.ts", "11"),
{ path: "benchmarks/perf/scenarios.json", sha: "tree", type: "tree", mode: "040000" },
];
const jq = spawnSync("jq", [nextjsBenchmarkInputTreeJq], {
input: JSON.stringify(githubTree(entries)),
encoding: "utf8",
});
expect(jq.status, jq.stderr).toBe(0);
expect(JSON.parse(jq.stdout).tree).toEqual(
entries
.filter((entry) => entry.type === "blob" && isNextjsBenchmarkInput(entry.path))
.map((entry) => ({ path: entry.path, sha: entry.sha, type: entry.type })),
);
});
it("rejects symlinked bundle outputs", () => {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-bundle-symlink-"));
const outputDirectory = join(directory, "benchmarks/vinext/dist");
const linkedDirectory = join(directory, "linked-client");
mkdirSync(linkedDirectory, { recursive: true });
mkdirSync(outputDirectory, { recursive: true });
writeFileSync(join(linkedDirectory, "entry.js"), "console.log('linked')");
execFileSync("ln", ["-s", linkedDirectory, join(outputDirectory, "client")]);
expect(() =>
execFileSync(process.execPath, ["benchmarks/perf/bundle-size.mjs", "vinext"], {
cwd: join(import.meta.dirname, ".."),
env: { ...process.env, VINEXT_PERF_TARGET_ROOT: directory },
stdio: "pipe",
}),
).toThrow("Bundle output may not be a symlink");
});
it("rejects bundle outputs beneath symlinked benchmark ancestors", () => {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-bundle-ancestor-"));
const linkedRoot = mkdtempSync(join(tmpdir(), "vinext-perf-linked-root-"));
mkdirSync(join(directory, "benchmarks"), { recursive: true });
mkdirSync(join(linkedRoot, "dist/client"), { recursive: true });
writeFileSync(join(linkedRoot, "dist/client/entry.js"), "console.log('linked')");
execFileSync("ln", ["-s", linkedRoot, join(directory, "benchmarks/vinext")]);
expect(() =>
execFileSync(process.execPath, ["benchmarks/perf/bundle-size.mjs", "vinext"], {
cwd: join(import.meta.dirname, ".."),
env: { ...process.env, VINEXT_PERF_TARGET_ROOT: directory },
stdio: "pipe",
}),
).toThrow("Bundle output escapes the benchmark checkout");
});
it("measures the eager RSC entry closure and complete server bundle separately", () => {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-server-bundle-"));
const repositoryRoot = join(import.meta.dirname, "..");
const serverDirectory = join(directory, "benchmarks/vinext/dist/server");
const samplesPath = join(directory, "samples.jsonl");
const rscEntry =
"import './_next/static/shared.js'; export { value } from './_next/static/reexport.js'; import('./_next/static/lazy.js'); export default function handler() { return 'rsc'; }";
const ssrEntry = "export function render() { return 'ssr'; }";
const sharedChunk = "import '../../index.js'; export const shared = 'chunk';";
const reexportedChunk = "export const value = 'reexported';";
const lazyChunk = "export const lazy = 'lazy';";
mkdirSync(join(serverDirectory, "ssr"), { recursive: true });
mkdirSync(join(serverDirectory, "_next/static"), { recursive: true });
writeFileSync(join(directory, "package.json"), '{"private":true}');
symlinkSync(join(repositoryRoot, "node_modules"), join(directory, "node_modules"), "dir");
writeFileSync(join(serverDirectory, "index.js"), rscEntry);
writeFileSync(join(serverDirectory, "ssr/index.js"), ssrEntry);
writeFileSync(join(serverDirectory, "_next/static/shared.js"), sharedChunk);
writeFileSync(join(serverDirectory, "_next/static/reexport.js"), reexportedChunk);
writeFileSync(join(serverDirectory, "_next/static/lazy.js"), lazyChunk);
writeFileSync(join(serverDirectory, "vinext-server.json"), "{}");
const baseEnvironment = {
...process.env,
VINEXT_PERF_TARGET_ROOT: directory,
VINEXT_PERF_SAMPLES: samplesPath,
VINEXT_PERF_SCENARIO_ID: "bundle-size",
VINEXT_PERF_SUITE: "Build",
VINEXT_PERF_LABEL: "Bundle size",
VINEXT_PERF_IMPLEMENTATION_ID: "vinext",
VINEXT_PERF_IMPLEMENTATION_LABEL: "vinext",
VINEXT_PERF_UNIT: "bytes",
VINEXT_PERF_LOWER_IS_BETTER: "true",
VINEXT_PERF_REVISION: "head",
};
execFileSync(process.execPath, ["benchmarks/perf/bundle-size.mjs", "vinext", "rsc-entry"], {
cwd: join(import.meta.dirname, ".."),
env: { ...baseEnvironment, VINEXT_PERF_BENCHMARK_ID: "vinext-rsc-entry-gzip" },
});
execFileSync(process.execPath, ["benchmarks/perf/bundle-size.mjs", "vinext", "server"], {
cwd: join(import.meta.dirname, ".."),
env: { ...baseEnvironment, VINEXT_PERF_BENCHMARK_ID: "vinext-server-bundle-gzip" },
});
const samples = readFileSync(samplesPath, "utf8")
.trim()
.split("\n")
.map((line) => JSON.parse(line));
expect(samples.map((sample) => sample.value)).toEqual([
gzipSync(rscEntry).length + gzipSync(sharedChunk).length + gzipSync(reexportedChunk).length,
gzipSync(rscEntry).length +
gzipSync(ssrEntry).length +
gzipSync(sharedChunk).length +
gzipSync(reexportedChunk).length +
gzipSync(lazyChunk).length,
]);
});
it("resolves Vite from the benchmark target when the trusted harness is relocated", () => {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-relocated-harness-"));
const repositoryRoot = join(import.meta.dirname, "..");
const targetRoot = join(directory, "target");
const harnessRoot = join(directory, "harness");
const serverDirectory = join(targetRoot, "benchmarks/vinext/dist/server");
const samplesPath = join(directory, "samples.jsonl");
mkdirSync(serverDirectory, { recursive: true });
mkdirSync(harnessRoot, { recursive: true });
cpSync(join(repositoryRoot, "benchmarks/perf"), join(harnessRoot, "benchmarks/perf"), {
recursive: true,
});
writeFileSync(join(targetRoot, "package.json"), '{"private":true}');
symlinkSync(join(repositoryRoot, "node_modules"), join(targetRoot, "node_modules"), "dir");
writeFileSync(join(serverDirectory, "index.js"), "import './shared.js';");
writeFileSync(join(serverDirectory, "shared.js"), "export const shared = true;");
execFileSync(
process.execPath,
[join(harnessRoot, "benchmarks/perf/bundle-size.mjs"), "vinext", "rsc-entry"],
{
cwd: harnessRoot,
env: {
...process.env,
VINEXT_PERF_TARGET_ROOT: targetRoot,
VINEXT_PERF_SAMPLES: samplesPath,
VINEXT_PERF_SCENARIO_ID: "bundle-size",
VINEXT_PERF_SUITE: "Build",
VINEXT_PERF_BENCHMARK_ID: "vinext-rsc-entry-gzip",
VINEXT_PERF_LABEL: "RSC entry",
VINEXT_PERF_IMPLEMENTATION_ID: "vinext",
VINEXT_PERF_IMPLEMENTATION_LABEL: "vinext",
VINEXT_PERF_UNIT: "bytes",
VINEXT_PERF_LOWER_IS_BETTER: "true",
VINEXT_PERF_REVISION: "head",
},
},
);
const sample = JSON.parse(readFileSync(samplesPath, "utf8"));
expect(sample.value).toBe(
gzipSync("import './shared.js';").length + gzipSync("export const shared = true;").length,
);
});
it("measures only the eager client entry closure", () => {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-client-entry-"));
const clientDirectory = join(directory, "benchmarks/vinext/dist/client");
const chunksDirectory = join(clientDirectory, "assets");
const manifestDirectory = join(clientDirectory, ".vite");
const samplesPath = join(directory, "samples.jsonl");
const entry = "import './shared.js'; console.log('entry');";
const shared = "export const shared = 'shared';";
const lazy = "export const lazy = 'lazy';";
mkdirSync(chunksDirectory, { recursive: true });
mkdirSync(manifestDirectory, { recursive: true });
writeFileSync(join(chunksDirectory, "entry.js"), entry);
writeFileSync(join(chunksDirectory, "shared.js"), shared);
writeFileSync(join(chunksDirectory, "lazy.js"), lazy);
writeFileSync(
join(manifestDirectory, "manifest.json"),
JSON.stringify({
"virtual:entry": {
file: "assets/entry.js",
isEntry: true,
imports: ["shared"],
dynamicImports: ["lazy"],
},
shared: {
file: "assets/shared.js",
imports: ["virtual:entry"],
},
lazy: {
file: "assets/lazy.js",
isDynamicEntry: true,
},
}),
);
execFileSync(process.execPath, ["benchmarks/perf/bundle-size.mjs", "vinext", "client-entry"], {
cwd: join(import.meta.dirname, ".."),
env: {
...process.env,
VINEXT_PERF_TARGET_ROOT: directory,
VINEXT_PERF_SAMPLES: samplesPath,
VINEXT_PERF_BENCHMARK_ID: "vinext-client-entry-gzip",
VINEXT_PERF_SCENARIO_ID: "client-entry-gzip",
VINEXT_PERF_SUITE: "Build",
VINEXT_PERF_LABEL: "Client entry size",
VINEXT_PERF_IMPLEMENTATION_ID: "vinext",
VINEXT_PERF_IMPLEMENTATION_LABEL: "vinext",
VINEXT_PERF_UNIT: "bytes",
VINEXT_PERF_LOWER_IS_BETTER: "true",
VINEXT_PERF_REVISION: "head",
},
});
const sample = JSON.parse(readFileSync(samplesPath, "utf8"));
expect(sample.value).toBe(gzipSync(entry).length + gzipSync(shared).length);
});
it("normalizes same-run baseline samples separately from head samples", () => {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-"));
const samplesPath = join(directory, "samples.jsonl");
const resultsPath = join(directory, "results.json");
const profilesPath = join(directory, "profiles");
const profileDirectory = join(profilesPath, "vinext-production-build");
mkdirSync(profileDirectory, { recursive: true });
writeFileSync(
join(profileDirectory, "samply-profile.json.gz"),
gzipSync(JSON.stringify({ threads: [] })),
);
const sample = {
schemaVersion: 1,
benchmarkId: "vinext-production-build",
scenarioId: "production-build",
suite: "Build",
label: "Production build time",
description: "Build",
implementationId: "vinext",
implementationLabel: "vinext",
profile: true,
unit: "ms",
lowerIsBetter: true,
measuredAt: "2026-01-01T00:00:00.000Z",
};
writeFileSync(
samplesPath,
[
{ ...sample, revision: "base", value: 100 },
{ ...sample, revision: "head", value: 90 },
{ ...sample, revision: "head", value: 92 },
{ ...sample, revision: "base", value: 102 },
]
.map((value) => JSON.stringify(value))
.join("\n"),
);
execFileSync(
process.execPath,
["benchmarks/perf/normalize-results.mjs", samplesPath, resultsPath, profilesPath],
{
cwd: join(import.meta.dirname, ".."),
env: {
...process.env,
VINEXT_PERF_RUN_KIND: "pull_request",
VINEXT_PERF_COMMIT_SHA: "local",
VINEXT_PERF_BASE_SHA: "a".repeat(40),
VINEXT_PERF_PR_NUMBER: "1",
},
},
);
const results = JSON.parse(readFileSync(resultsPath, "utf8"));
expect(results.schemaVersion).toBe(2);
expect(results.run.skippedImplementations).toEqual([]);
expect(results.benchmarks[0].samples).toMatchObject({ rounds: 2, median: 91 });
expect(results.benchmarks[0].baselineSamples).toMatchObject({
rounds: 2,
median: 101,
});
expect(results.benchmarks[0].profileRounds).toBe(1);
});
it("requires every diagnostic profile to contain filterable traces", () => {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-traces-"));
const resultsPath = join(directory, "results.json");
const firstProfile = "profiles/dev/samply-profile.json.gz";
const secondProfile = "profiles/build/samply-profile.json.gz";
mkdirSync(join(directory, "profiles/dev"), { recursive: true });
mkdirSync(join(directory, "profiles/build"), { recursive: true });
writeFileSync(
join(directory, firstProfile),
gzipSync(profileWithSources(["file:///repo/packages/vinext/src/index.ts"])),
);
writeFileSync(
join(directory, secondProfile),
gzipSync(
profileWithSources([
"file:///repo/packages/vinext/src/index.ts",
"file:///repo/node_modules/vite-plus-core/dist/vite/node/index.js",
"file:///repo/node_modules/rolldown/dist/index.mjs",
]),
),
);
writeFileSync(
resultsPath,
JSON.stringify({
benchmarks: [
{ benchmarkId: "vinext-dev", profileFile: firstProfile },
{ benchmarkId: "vinext-build", profileFile: secondProfile },
],
}),
);
expect(() =>
execFileSync(
process.execPath,
["benchmarks/perf/validate-profile-traces.mjs", resultsPath, directory],
{ cwd: join(import.meta.dirname, ".."), encoding: "utf8", stdio: "pipe" },
),
).toThrow("vinext-dev profile is missing sampled vite, rolldown frames");
});
it("reports unchanged Next.js as skipped", () => {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-comment-"));
const resultsPath = join(directory, "results.json");
const responsePath = join(directory, "response.json");
const outputPath = join(directory, "comment.md");
writeFileSync(
resultsPath,
JSON.stringify({
run: {
kind: "pull_request",
pullRequest: 42,
baseSha: "b".repeat(40),
measuredAt: "2026-01-01T00:00:00.000Z",
skippedImplementations: ["nextjs"],
},
benchmarks: [
{
benchmarkId: "vinext-production-build",
samples: { median: 90 },
baselineSamples: { median: 100 },
},
],
}),
);
writeFileSync(
responsePath,
JSON.stringify({
comparison: {
head: { shortSha: "1234567" },
baseline: null,
measurements: [
{
benchmarkId: "vinext-production-build",
label: "Production build time",
implementationLabel: "vinext",
unit: "ms",
lowerIsBetter: true,
baseline: null,
current: { median: 999 },
},
],
},
}),
);
execFileSync(
process.execPath,
["benchmarks/perf/format-pr-comment.mjs", resultsPath, responsePath, outputPath],
{ cwd: join(import.meta.dirname, "..") },
);
const comment = readFileSync(outputPath, "utf8");
expect(comment).toContain(
"using alternating same-runner rounds. Next.js was unchanged and skipped.",
);
expect(comment).toContain("1 improved · 0 regressed · 0 within ±1.5%");
expect(comment).not.toContain("Next.js |");
});
it("labels mixed paired and historical PR comment baselines", () => {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-mixed-comment-"));
const resultsPath = join(directory, "results.json");
const responsePath = join(directory, "response.json");
const outputPath = join(directory, "comment.md");
writeFileSync(
resultsPath,
JSON.stringify({
run: {
kind: "pull_request",
pullRequest: 42,
baseSha: "b".repeat(40),
measuredAt: "2026-01-01T00:00:00.000Z",
},
benchmarks: [
{
benchmarkId: "paired",
samples: { median: 90 },
baselineSamples: { median: 100 },
},
{ benchmarkId: "historical", samples: { median: 80 }, baselineSamples: null },
],
}),
);
writeFileSync(
responsePath,
JSON.stringify({
comparison: {
head: { shortSha: "aaaaaaa" },
baseline: { shortSha: "bbbbbbb" },
measurements: [
commentMeasurement("paired", 100, 90),
commentMeasurement("historical", 100, 80),
],
},
}),
);
execFileSync(
process.execPath,
["benchmarks/perf/format-pr-comment.mjs", resultsPath, responsePath, outputPath],
{ cwd: join(import.meta.dirname, "..") },
);
const comment = readFileSync(outputPath, "utf8");
expect(comment).toContain(
"Paired benchmarks use alternating same-runner rounds; unpaired benchmarks use the stored base-run baseline.",
);
expect(comment).toContain("mixed paired/historical baselines");
});
it("accepts legacy PR artifacts without skipped implementation metadata", () => {
const headSha = "a".repeat(40);
const baseSha = "b".repeat(40);
const measuredAt = "2026-06-18T12:00:00.000Z";
const payload = performancePayload({
headSha,
baseSha,
measuredAt,
benchmarks: [performanceBenchmark("vinext", false)],
});
validatePerformancePayload(payload, "pull_request", {
"repos/cloudflare/vinext/actions/runs/123": sourceRun("pull_request", headSha),
"repos/cloudflare/vinext/pulls/42": pullRequest(headSha, baseSha),
[`repos/cloudflare/vinext/contents/benchmarks/perf/scenarios.json?ref=${baseSha}`]:
githubFile(
JSON.stringify({
scenarios: [performanceScenario([{ id: "vinext", label: "vinext" }])],
}),
),
[`repos/cloudflare/vinext/git/commits/${headSha}`]: commit(measuredAt),
});
});
it("accepts dispatched PR artifacts that skip unchanged Next.js", () => {
const workflowSha = "c".repeat(40);
const headSha = "a".repeat(40);
const baseSha = "b".repeat(40);
const measuredAt = "2026-06-18T12:00:00.000Z";
const nextjsInputs = [
gitTreeEntry("benchmarks/nextjs/package.json", "1"),
gitTreeEntry("benchmarks/generate-app.mjs", "2"),
gitTreeEntry("benchmarks/perf/scenarios.json", "3"),
];
const payload = performancePayload({
headSha,
baseSha,
measuredAt,
skippedImplementations: ["nextjs"],
benchmarks: [performanceBenchmark("vinext", true)],
});
validatePerformancePayload(payload, "workflow_dispatch", {
"repos/cloudflare/vinext/actions/runs/123": sourceRun(
"workflow_dispatch",
workflowSha,
"main",
),
"repos/cloudflare/vinext/pulls/42": pullRequest(headSha, baseSha),
[`repos/cloudflare/vinext/contents/benchmarks/perf/scenarios.json?ref=${workflowSha}`]:
githubFile(
JSON.stringify({
scenarios: [
performanceScenario([
{ id: "nextjs", label: "Next.js", compareBase: true },
{ id: "vinext", label: "vinext", compareBase: true },
]),
],
}),
),
[`repos/cloudflare/vinext/git/trees/${baseSha}?recursive=1`]: githubTree(nextjsInputs),
[`repos/cloudflare/vinext/git/trees/${headSha}?recursive=1`]: githubTree(nextjsInputs),
[`repos/cloudflare/vinext/git/commits/${headSha}`]: commit(measuredAt),
});
});
it("accepts dispatched main artifacts after main advances", () => {
const workflowSha = "c".repeat(40);
const repositoryRoot = join(import.meta.dirname, "..");
execFileSync("git", ["fetch", "--no-tags", "origin", "main"], {
cwd: repositoryRoot,
});
const commitSha = execFileSync("git", ["rev-parse", "origin/main"], {
cwd: repositoryRoot,
encoding: "utf8",
}).trim();
const measuredAt = execFileSync("git", ["show", "-s", "--format=%cI", commitSha], {
cwd: repositoryRoot,
encoding: "utf8",
}).trim();
const payload = mainPerformancePayload({
commitSha,
measuredAt,
benchmarks: [performanceBenchmark("vinext", false)],
});
validatePerformancePayload(payload, "workflow_dispatch", {
"repos/cloudflare/vinext/actions/runs/123": sourceRun(
"workflow_dispatch",
workflowSha,
"main",
),
[`repos/cloudflare/vinext/contents/benchmarks/perf/scenarios.json?ref=${workflowSha}`]:
githubFile(
JSON.stringify({
scenarios: [performanceScenario([{ id: "vinext", label: "vinext" }])],
}),
),
[`repos/cloudflare/vinext/git/commits/${commitSha}`]: commit(measuredAt),
});
}, 15_000);
it("rejects dispatched artifacts from workflow refs outside main", () => {
const workflowSha = "c".repeat(40);
const headSha = "a".repeat(40);
const baseSha = "b".repeat(40);
const measuredAt = "2026-06-18T12:00:00.000Z";
const payload = performancePayload({
headSha,
baseSha,
measuredAt,
benchmarks: [performanceBenchmark("vinext", true)],
});
expect(() =>
validatePerformancePayload(payload, "workflow_dispatch", {
"repos/cloudflare/vinext/actions/runs/123": sourceRun("workflow_dispatch", workflowSha),
"repos/cloudflare/vinext/pulls/42": pullRequest(headSha, baseSha),
}),
).toThrow("Dispatched workflow ref is not the default branch");
});
it("validates skipped Next.js against the synthetic merge commit", () => {
const headSha = "a".repeat(40);
const baseSha = "b".repeat(40);
const mergeSha = "c".repeat(40);
const measuredAt = "2026-06-18T12:00:00.000Z";
const baseInputs = [
gitTreeEntry("benchmarks/nextjs/package.json", "1"),
gitTreeEntry("benchmarks/generate-app.mjs", "2"),
gitTreeEntry("benchmarks/perf/scenarios.json", "3"),
];
const staleHeadInputs = baseInputs.map((entry) =>
entry.path === "benchmarks/perf/scenarios.json" ? { ...entry, sha: "stale" } : entry,
);
const payload = performancePayload({
headSha,
baseSha,
measuredAt,
skippedImplementations: ["nextjs"],
benchmarks: [performanceBenchmark("vinext", true)],
});
validatePerformancePayload(payload, "pull_request", {
"repos/cloudflare/vinext/actions/runs/123": sourceRun("pull_request", headSha),
"repos/cloudflare/vinext/pulls/42": pullRequest(headSha, baseSha, mergeSha),
[`repos/cloudflare/vinext/contents/benchmarks/perf/scenarios.json?ref=${baseSha}`]:
githubFile(
JSON.stringify({
scenarios: [
performanceScenario([
{ id: "nextjs", label: "Next.js", compareBase: true },
{ id: "vinext", label: "vinext", compareBase: true },
]),
],
}),
),
[`repos/cloudflare/vinext/git/trees/${baseSha}?recursive=1`]: githubTree(baseInputs),
[`repos/cloudflare/vinext/git/trees/${mergeSha}?recursive=1`]: githubTree(baseInputs),
[`repos/cloudflare/vinext/git/trees/${headSha}?recursive=1`]: githubTree(staleHeadInputs),
[`repos/cloudflare/vinext/git/commits/${headSha}`]: commit(measuredAt),
});
});
it("filters remote tree responses before validating skipped Next.js inputs", () => {
const headSha = "a".repeat(40);
const baseSha = "b".repeat(40);
const mergeSha = "c".repeat(40);
const measuredAt = "2026-06-18T12:00:00.000Z";
const nextjsInputs = [
gitTreeEntry("benchmarks/nextjs/package.json", "1"),
gitTreeEntry("benchmarks/generate-app.mjs", "2"),
gitTreeEntry("benchmarks/perf/scenarios.json", "3"),
];
const ignoredEntries = [
richGitTreeEntry("benchmarks/nextjs/app/page.tsx", "app"),
richGitTreeEntry("benchmarks/perf/README.md", "readme"),
richGitTreeEntry("benchmarks/perf/format-pr-comment.mjs", "formatter"),
{ path: "benchmarks/perf", sha: "tree", type: "tree", mode: "040000" },
...Array.from({ length: 5_000 }, (_, index) =>
richGitTreeEntry(`packages/vinext/src/generated-${index}.ts`, `${index}`),
),
];
const payload = performancePayload({
headSha,
baseSha,
measuredAt,
skippedImplementations: ["nextjs"],
benchmarks: [performanceBenchmark("vinext", true)],
});
const requests = validatePerformancePayload(payload, "pull_request", {
"repos/cloudflare/vinext/actions/runs/123": sourceRun("pull_request", headSha),
"repos/cloudflare/vinext/pulls/42": pullRequest(headSha, baseSha, mergeSha),
[`repos/cloudflare/vinext/contents/benchmarks/perf/scenarios.json?ref=${baseSha}`]:
githubFile(
JSON.stringify({
scenarios: [
performanceScenario([
{ id: "nextjs", label: "Next.js", compareBase: true },
{ id: "vinext", label: "vinext", compareBase: true },
]),
],
}),
),
[`repos/cloudflare/vinext/git/trees/${baseSha}?recursive=1`]: githubTree([
...nextjsInputs,
...ignoredEntries,
]),
[`repos/cloudflare/vinext/git/trees/${mergeSha}?recursive=1`]: githubTree([
...nextjsInputs,
...ignoredEntries,
]),
[`repos/cloudflare/vinext/git/commits/${headSha}`]: commit(measuredAt),
});
const treeRequests = requests.filter((request) => request[1]?.includes("/git/trees/"));
expect(treeRequests).toHaveLength(2);
for (const request of treeRequests) {
const jqIndex = request.indexOf("--jq");
expect(jqIndex).toBeGreaterThan(-1);
expect(request[jqIndex + 1]).toBe(nextjsBenchmarkInputTreeJq);
}
});
it("rejects skipped Next.js when a benchmark runtime input changed", () => {
const workflowSha = "c".repeat(40);
const headSha = "a".repeat(40);
const baseSha = "b".repeat(40);
const measuredAt = "2026-06-18T12:00:00.000Z";
const baseInputs = [
gitTreeEntry("benchmarks/nextjs/package.json", "1"),
gitTreeEntry("benchmarks/generate-app.mjs", "2"),
gitTreeEntry("benchmarks/perf/scenarios.json", "3"),
];
const headInputs = baseInputs.map((entry) =>
entry.path === "benchmarks/perf/scenarios.json" ? { ...entry, sha: "changed" } : entry,
);
const payload = performancePayload({
headSha,
baseSha,
measuredAt,
skippedImplementations: ["nextjs"],
benchmarks: [performanceBenchmark("vinext", true)],
});
expect(() =>
validatePerformancePayload(payload, "workflow_dispatch", {
"repos/cloudflare/vinext/actions/runs/123": sourceRun("workflow_dispatch", workflowSha),
"repos/cloudflare/vinext/pulls/42": pullRequest(headSha, baseSha),
[`repos/cloudflare/vinext/contents/benchmarks/perf/scenarios.json?ref=${workflowSha}`]:
githubFile(
JSON.stringify({
scenarios: [
performanceScenario([
{ id: "nextjs", label: "Next.js", compareBase: true },
{ id: "vinext", label: "vinext", compareBase: true },
]),
],
}),
),
[`repos/cloudflare/vinext/git/trees/${baseSha}?recursive=1`]: githubTree(baseInputs),
[`repos/cloudflare/vinext/git/trees/${headSha}?recursive=1`]: githubTree(headInputs),
}),
).toThrow();
});
it("requires paired profiles to declare their single profiling round", () => {
const headSha = "a".repeat(40);
const baseSha = "b".repeat(40);
const measuredAt = "2026-06-18T12:00:00.000Z";
const benchmark = {
...performanceBenchmark("vinext", true),
profileFile: "perf-profiles/vinext-production-build/samply-profile.json.gz",
profileRounds: 1,
};
const payload = performancePayload({
headSha,
baseSha,
measuredAt,
benchmarks: [benchmark],
});
const responses = {
"repos/cloudflare/vinext/actions/runs/123": sourceRun("pull_request", headSha),
"repos/cloudflare/vinext/pulls/42": pullRequest(headSha, baseSha),
[`repos/cloudflare/vinext/contents/benchmarks/perf/scenarios.json?ref=${baseSha}`]:
githubFile(
JSON.stringify({
scenarios: [
performanceScenario([
{ id: "vinext", label: "vinext", compareBase: true, profile: true },
]),
],
}),
),
[`repos/cloudflare/vinext/git/commits/${headSha}`]: commit(measuredAt),
};
expect(() => validatePerformancePayload(payload, "pull_request", responses)).not.toThrow();
expect(() =>
validatePerformancePayload(
{
...payload,
benchmarks: [{ ...benchmark, profileRounds: 6 }],
},
"pull_request",
responses,
),
).toThrow("Paired profile must contain one round");
});
});
function validatePerformancePayload(
payload: Record<string, unknown>,
sourceEvent: string,
githubResponses: Record<string, unknown>,
) {
const directory = mkdtempSync(join(tmpdir(), "vinext-perf-validator-"));
const payloadPath = join(directory, "results.json");
const responsesPath = join(directory, "responses.json");
const requestsPath = join(directory, "requests.jsonl");
const ghPath = join(directory, "gh");
writeFileSync(payloadPath, JSON.stringify(payload));
writeFileSync(responsesPath, JSON.stringify(githubResponses));
for (const benchmark of payload.benchmarks as Array<{ profileFile?: string | null }>) {
if (!benchmark.profileFile) continue;
const profilePath = join(directory, benchmark.profileFile);
mkdirSync(join(profilePath, ".."), { recursive: true });
writeFileSync(profilePath, gzipSync(JSON.stringify({ threads: [] })));
}
writeFileSync(
ghPath,
`#!/usr/bin/env node
const fs = require("node:fs");
fs.appendFileSync(process.env.MOCK_GH_REQUESTS, JSON.stringify(process.argv.slice(2)) + "\\n");
const responses = JSON.parse(fs.readFileSync(process.env.MOCK_GH_RESPONSES, "utf8"));
let response = responses[process.argv[3]];
if (response === undefined) {
console.error("Unexpected gh api request:", process.argv[3]);
process.exit(1);
}
const jqIndex = process.argv.indexOf("--jq");
function isNextjsBenchmarkInput(path) {
if (path === ".github/workflows/perf.yml" || path === "benchmarks/generate-app.mjs") return true;
if (path.startsWith("benchmarks/nextjs/")) return !path.startsWith("benchmarks/nextjs/app/");
return (
path.startsWith("benchmarks/perf/") &&
path !== "benchmarks/perf/README.md" &&
path !== "benchmarks/perf/format-pr-comment.mjs" &&
path !== "benchmarks/perf/upload-results.mjs" &&
path !== "benchmarks/perf/validate-results.mjs"
);
}
if (
jqIndex !== -1 &&
process.argv[jqIndex + 1] === process.env.MOCK_TREE_JQ &&
Array.isArray(response.tree)
) {
response = {
truncated: response.truncated,
tree: response.tree
.filter((entry) => entry.type === "blob" && isNextjsBenchmarkInput(entry.path))
.map((entry) => ({ path: entry.path, sha: entry.sha, type: entry.type })),
};
}
process.stdout.write(JSON.stringify(response));
`,
);
chmodSync(ghPath, 0o755);
const validation = spawnSync(
process.execPath,
["benchmarks/perf/validate-results.mjs", payloadPath],
{
cwd: join(import.meta.dirname, ".."),
env: {
...process.env,
PATH: `${directory}:${process.env.PATH}`,
GITHUB_REPOSITORY: "cloudflare/vinext",
GITHUB_TOKEN: "test",
VINEXT_PERF_SOURCE_EVENT: sourceEvent,
VINEXT_PERF_SOURCE_RUN_ID: "123",
VINEXT_PERF_SOURCE_RUN_ATTEMPT: "1",
MOCK_GH_RESPONSES: responsesPath,
MOCK_GH_REQUESTS: requestsPath,
MOCK_TREE_JQ: nextjsBenchmarkInputTreeJq,
},
encoding: "utf8",
},
);
if (validation.status !== 0) {
throw new Error(validation.stderr || validation.stdout || "Performance validation failed");
}
const requests = readFileSync(requestsPath, "utf8")
.trim()
.split("\n")
.filter(Boolean)
.map((line) => JSON.parse(line) as string[]);
return requests;
}
function performancePayload({
headSha,
baseSha,
measuredAt,
skippedImplementations,
benchmarks,
}: {
headSha: string;
baseSha: string;
measuredAt: string;
skippedImplementations?: string[];
benchmarks: unknown[];
}) {
return {
schemaVersion: benchmarks.some(
(benchmark) =>
typeof benchmark === "object" &&
benchmark !== null &&
"baselineSamples" in benchmark &&
benchmark.baselineSamples !== null,
)
? 2
: 1,
provider: "samply",
instrument: "walltime",
run: {
kind: "pull_request",
commitSha: headSha,
baseSha,
pullRequest: 42,
executionId: "123:1",
measuredAt,
repository: "cloudflare/vinext",
...(skippedImplementations ? { skippedImplementations } : {}),
},
system: {},
benchmarks,
};
}
function mainPerformancePayload({
commitSha,
measuredAt,
benchmarks,
}: {
commitSha: string;
measuredAt: string;
benchmarks: unknown[];
}) {
return {
schemaVersion: 1,
provider: "samply",
instrument: "walltime",
run: {
kind: "main",
commitSha,
baseSha: null,
pullRequest: null,
executionId: "123:1",
measuredAt,
repository: "cloudflare/vinext",
},
system: {},
benchmarks,
};
}
function commentMeasurement(benchmarkId: string, baseline: number, current: number) {
return {
benchmarkId,
label: benchmarkId,
implementationLabel: "vinext",
unit: "ms",
lowerIsBetter: true,
baseline: { median: baseline },
current: { median: current },
};
}
function performanceBenchmark(implementationId: string, paired: boolean) {
const samples = {
rounds: 2,
mean: 10,
median: 10,
standardDeviation: 0,
min: 10,
max: 10,
q1: 10,
q3: 10,
outliers: 0,
};
return {
benchmarkId: `${implementationId}-production-build`,
scenarioId: "production-build",
suite: "Build",
label: "Production build time",
description: "Build",
implementationId,
implementationLabel: implementationId === "nextjs" ? "Next.js" : "vinext",
unit: "ms",
lowerIsBetter: true,
samples,
baselineSamples: paired ? samples : null,
profileFile: null,
};
}
function performanceScenario(
implementations: Array<{
id: string;
label: string;
compareBase?: boolean;
profile?: boolean;
}>,
) {
return {
id: "production-build",
suite: "Build",
label: "Production build time",
description: "Build",
unit: "ms",
lowerIsBetter: true,
implementations,
};
}
function sourceRun(event: string, headSha: string, headBranch = "benchmark-branch") {
return {
path: ".github/workflows/perf.yml",
status: "completed",
conclusion: "success",
event,
run_attempt: 1,
head_sha: headSha,
head_repository: { full_name: "cloudflare/vinext" },
head_branch: headBranch,
};
}
function pullRequest(headSha: string, baseSha: string, mergeSha = "c".repeat(40)) {
return {
number: 42,
state: "open",
merge_commit_sha: mergeSha,
head: {
sha: headSha,
ref: "benchmark-branch",
repo: { full_name: "cloudflare/vinext" },
},
base: {
sha: baseSha,
repo: { full_name: "cloudflare/vinext" },
},
};
}
function githubFile(contents: string) {
return {
type: "file",
encoding: "base64",
content: Buffer.from(contents).toString("base64"),
};
}
function profileWithSources(sources: string[]) {
return JSON.stringify({
threads: [
{
stringArray: sources.map((source) => `function ${source}`),
funcTable: { name: sources.map((_, index) => index) },
frameTable: { func: sources.map((_, index) => index) },
stackTable: {
frame: sources.map((_, index) => index),
prefix: sources.map((_, index) => (index === 0 ? null : index - 1)),
},
samples: { stack: [sources.length - 1], length: 1 },
},
],
});
}
function gitTreeEntry(path: string, sha: string) {
return { path, sha, type: "blob" };
}
function richGitTreeEntry(path: string, sha: string) {
return { path, sha, type: "blob", mode: "100644", size: 123, url: "https://example.test" };
}
function githubTree(tree: Array<{ path: string; sha: string; type: string }>) {
return { truncated: false, tree };
}
function commit(measuredAt: string) {
return { committer: { date: measuredAt } };
}