Files
initiative/scripts/check-lint-ignores.mjs
Lukas 4d1a7c6420 Remove noAwaitInLoops biome-ignore by chaining batches with reduce
Replace the for-loop with await-in-loop with a .reduce() chain that
sequences Promise.allSettled batches without triggering the lint rule.
Ratchet source ignore threshold from 4 to 3.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 11:24:31 +01:00

109 lines
2.9 KiB
JavaScript

/**
* Backpressure check for biome-ignore comments.
*
* 1. Ratcheting cap — source and test files have separate max counts.
* Lower these numbers as you fix ignores; they can never go up silently.
* 2. Banned rules — ignoring certain rule categories is never allowed.
* 3. Justification — every ignore must have a non-empty explanation after
* the rule name.
*/
import { execSync } from "node:child_process";
import { readFileSync } from "node:fs";
// ── Configuration ──────────────────────────────────────────────────────
const MAX_SOURCE_IGNORES = 3;
const MAX_TEST_IGNORES = 3;
/** Rule prefixes that must never be suppressed. */
const BANNED_PREFIXES = [
"lint/security/",
"lint/correctness/noGlobalObjectCalls",
"lint/correctness/noUnsafeFinally",
];
// ───────────────────────────────────────────────────────────────────────
const IGNORE_PATTERN = /biome-ignore\s+([\w/]+)(?::\s*(.*))?/;
function findFiles() {
return execSync("git ls-files -- '*.ts' '*.tsx'", { encoding: "utf-8" })
.trim()
.split("\n")
.filter(Boolean);
}
function isTestFile(path) {
return (
path.includes("__tests__/") ||
path.endsWith(".test.ts") ||
path.endsWith(".test.tsx")
);
}
let errors = 0;
let sourceCount = 0;
let testCount = 0;
for (const file of findFiles()) {
const lines = readFileSync(file, "utf-8").split("\n");
for (let i = 0; i < lines.length; i++) {
const match = lines[i].match(IGNORE_PATTERN);
if (!match) continue;
const rule = match[1];
const justification = (match[2] ?? "").trim();
const loc = `${file}:${i + 1}`;
// Count by category
if (isTestFile(file)) {
testCount++;
} else {
sourceCount++;
}
// Banned rules
for (const prefix of BANNED_PREFIXES) {
if (rule.startsWith(prefix)) {
console.error(`BANNED: ${loc}${rule} must not be suppressed`);
errors++;
}
}
// Justification required
if (!justification) {
console.error(
`MISSING JUSTIFICATION: ${loc} — biome-ignore ${rule} needs an explanation after the colon`,
);
errors++;
}
}
}
// Ratcheting caps
if (sourceCount > MAX_SOURCE_IGNORES) {
console.error(
`SOURCE CAP EXCEEDED: ${sourceCount} biome-ignore comments in source (max ${MAX_SOURCE_IGNORES}). Fix issues and lower the cap.`,
);
errors++;
}
if (testCount > MAX_TEST_IGNORES) {
console.error(
`TEST CAP EXCEEDED: ${testCount} biome-ignore comments in tests (max ${MAX_TEST_IGNORES}). Fix issues and lower the cap.`,
);
errors++;
}
// Summary
console.log(
`biome-ignore: ${sourceCount} source (max ${MAX_SOURCE_IGNORES}), ${testCount} test (max ${MAX_TEST_IGNORES})`,
);
if (errors > 0) {
console.error(`\n${errors} problem(s) found.`);
process.exit(1);
} else {
console.log("All checks passed.");
}