mirror of
https://github.com/vercel/eve.git
synced 2026-09-20 05:35:39 +08:00
f44e16a3e5
Co-authored-by: Casey Gowrie <ctgowrie@gmail.com> Co-authored-by: Allen Zhou <46854522+allenzhou101@users.noreply.github.com> Co-authored-by: Rui Conti <ruiconti@gmail.com> Co-authored-by: JJ Kasper <jj@jjsweb.site> Co-authored-by: Timo Lins <1440854+timolins@users.noreply.github.com> Co-authored-by: Felix Arntz <3531426+felixarntz@users.noreply.github.com> Co-authored-by: Shar Dara <2982650+darafsheh@users.noreply.github.com> Co-authored-by: John Phamous <johnphammail@gmail.com>
135 lines
3.5 KiB
JavaScript
135 lines
3.5 KiB
JavaScript
import { readFile } from "node:fs/promises";
|
|
import { resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
function formatBytes(bytes) {
|
|
if (bytes < 1_000) {
|
|
return `${bytes} B`;
|
|
}
|
|
|
|
if (bytes < 1_000_000) {
|
|
return `${(bytes / 1_000).toFixed(1)} kB`;
|
|
}
|
|
|
|
return `${(bytes / 1_000_000).toFixed(2)} MB`;
|
|
}
|
|
|
|
function formatRatioPercent(ratio) {
|
|
if (!Number.isFinite(ratio)) {
|
|
return "new";
|
|
}
|
|
|
|
return `${(ratio * 100).toFixed(1)}%`;
|
|
}
|
|
|
|
function formatFailure(check) {
|
|
if (check.kind === "runtime-dependency") {
|
|
return `New runtime dependency ${check.dependency} was added. Runtime dependencies increase the install footprint; prefer a vendored devDependency when possible`;
|
|
}
|
|
|
|
return `${check.metric} grew ${formatRatioPercent(check.increaseRatio)} (${formatBytes(check.baseline)} -> ${formatBytes(check.current)}), above the ${formatRatioPercent(check.thresholdRatio)} limit`;
|
|
}
|
|
|
|
function printUsage() {
|
|
process.stdout.write(
|
|
[
|
|
"Usage: node ./scripts/nitro-bundle-report-budget.mjs --report-json <path> [options]",
|
|
"",
|
|
"Options:",
|
|
" --report-json <path> Bundle report JSON generated by nitro-bundle-report.mjs",
|
|
" --acknowledged Allow budget failures to pass",
|
|
" --help Show this help text",
|
|
"",
|
|
].join("\n"),
|
|
);
|
|
}
|
|
|
|
function parseArguments(argv) {
|
|
const parsedArguments = {
|
|
acknowledged: false,
|
|
reportJsonPath: null,
|
|
};
|
|
|
|
for (let index = 0; index < argv.length; index += 1) {
|
|
const argument = argv[index];
|
|
|
|
if (argument === "--help") {
|
|
printUsage();
|
|
process.exit(0);
|
|
}
|
|
|
|
if (argument === "--acknowledged") {
|
|
parsedArguments.acknowledged = true;
|
|
continue;
|
|
}
|
|
|
|
const value = argv[index + 1];
|
|
|
|
if (value === undefined) {
|
|
throw new Error(`Missing value for "${argument}".`);
|
|
}
|
|
|
|
if (argument === "--report-json") {
|
|
parsedArguments.reportJsonPath = value;
|
|
index += 1;
|
|
continue;
|
|
}
|
|
|
|
throw new Error(`Unknown argument "${argument}".`);
|
|
}
|
|
|
|
if (parsedArguments.reportJsonPath === null) {
|
|
throw new Error('The "--report-json" option is required.');
|
|
}
|
|
|
|
return parsedArguments;
|
|
}
|
|
|
|
async function main() {
|
|
const args = parseArguments(process.argv.slice(2));
|
|
const report = JSON.parse(await readFile(resolve(args.reportJsonPath), "utf8"));
|
|
const sizeBudget = report.comparison?.sizeBudget;
|
|
|
|
if (!sizeBudget) {
|
|
process.stdout.write("No baseline comparison is available; skipping bundle warning policy.\n");
|
|
return;
|
|
}
|
|
|
|
const failures = sizeBudget.checks.filter((check) => check.failed);
|
|
|
|
if (failures.length === 0) {
|
|
process.stdout.write("Bundle warning policy passed.\n");
|
|
return;
|
|
}
|
|
|
|
const messageLines = [
|
|
"Bundle warning policy exceeded:",
|
|
...failures.map((failure) => `- ${formatFailure(failure)}`),
|
|
"",
|
|
"The pull request comment contains the same failure details.",
|
|
];
|
|
|
|
if (args.acknowledged) {
|
|
process.stdout.write(
|
|
`${messageLines.join("\n")}\nThe acknowledge-bundle-warning label is present, so this check is passing.\n`,
|
|
);
|
|
return;
|
|
}
|
|
|
|
process.stderr.write(
|
|
`${messageLines.join("\n")}\nAdd the acknowledge-bundle-warning label to acknowledge the regression and pass without regenerating the report.\n`,
|
|
);
|
|
process.exitCode = 1;
|
|
}
|
|
|
|
const executedScriptPath = process.argv[1] ? resolve(process.argv[1]) : null;
|
|
const moduleScriptPath = resolve(fileURLToPath(import.meta.url));
|
|
|
|
if (
|
|
executedScriptPath !== null &&
|
|
moduleScriptPath !== null &&
|
|
executedScriptPath === moduleScriptPath
|
|
) {
|
|
await main();
|
|
}
|