clusterflux-public/scripts/code-size-guard.js
Disasmer release dry run 2bef715211 Public dry run dryrun-20b59dc46b72
Source commit: 20b59dc46b72103c2f8a516c692b5cc3d54fab19

Public tree identity: sha256:aaa5ac7b58b2a0d23c6b11e5f76324bf3839ca1f62653a83deb736932adcfbd9
2026-07-14 10:08:15 +02:00

86 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const repo = path.resolve(__dirname, "..");
const maxProductionLines = 1000;
const ignoredDirs = new Set([".git", ".cache", ".local", "target", "node_modules"]);
const rootIgnoredDirs = new Set(["experiments"]);
function isTestRustFile(relativePath) {
const normalized = relativePath.split(path.sep).join("/");
return (
normalized.endsWith("/tests.rs") ||
normalized.includes("/tests/") ||
normalized.endsWith("_test.rs")
);
}
function lineCount(source) {
return source.endsWith("\n")
? source.split("\n").length - 1
: source.split("\n").length;
}
function productionSource(source) {
// A trailing cfg(test) module is not compiled into the product and therefore
// is not production business logic. Keeping it next to the implementation is
// useful when it exercises private invariants; count only the source before
// that explicitly test-only suffix.
const testModule = /^#\[cfg\(test\)\]\r?\nmod\s+[A-Za-z_][A-Za-z0-9_]*\s*\{/m.exec(source);
return testModule ? source.slice(0, testModule.index) : source;
}
function walk(directory, results = []) {
const entries = fs.readdirSync(directory, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(directory, entry.name);
const relativePath = path.relative(repo, fullPath);
if (entry.isDirectory()) {
if (ignoredDirs.has(entry.name)) continue;
if (!relativePath.includes(path.sep) && rootIgnoredDirs.has(entry.name)) continue;
walk(fullPath, results);
continue;
}
if (entry.isFile() && entry.name.endsWith(".rs")) {
results.push(relativePath);
}
}
return results;
}
const oversizedProductionFiles = [];
const oversizedTestFiles = [];
for (const relativePath of walk(repo)) {
const source = fs.readFileSync(path.join(repo, relativePath), "utf8");
const testOnlyFile = isTestRustFile(relativePath);
const lines = lineCount(testOnlyFile ? source : productionSource(source));
if (lines <= maxProductionLines) continue;
const entry = { path: relativePath, lines };
if (testOnlyFile) {
oversizedTestFiles.push(entry);
} else {
oversizedProductionFiles.push(entry);
}
}
assert.deepStrictEqual(
oversizedProductionFiles,
[],
`production Rust files must stay at or below ${maxProductionLines} lines; split business logic before adding more code`
);
if (oversizedTestFiles.length > 0) {
console.log(
`Code-size guard ignored ${oversizedTestFiles.length} oversized test-only Rust file(s): ${oversizedTestFiles
.map((entry) => `${entry.path} (${entry.lines})`)
.join(", ")}`
);
}
console.log("Code-size guard passed");