chore(ui): remove eslint-metrics.json lint-count snapshot

The eslint-metrics.json snapshot duplicated the violation counts already
enforced by eslint-budgets.json. Keeping it current added a CI drift check,
a pre-commit regenerate-and-flag step, and a standalone npm run lint:metrics
script, none of which caught anything the budget gate did not, yet all of
which failed noisily whenever the snapshot went stale. This drops the file
and that machinery while leaving eslint-budgets.json as the actual ratchet
gate
This commit is contained in:
Yuneng Jiang 2026-07-11 11:54:42 -07:00
parent 9659ae2f40
commit 7cdf42d770
No known key found for this signature in database
8 changed files with 8 additions and 108 deletions

View file

@ -85,7 +85,7 @@ jobs:
if: ${{ !cancelled() && steps.changed.outputs.has_files == 'true' }}
run: |
npx eslint . -f json -o "$RUNNER_TEMP/lint-report.json" || true
node scripts/check-lint-budgets.mjs "$RUNNER_TEMP/lint-report.json" eslint-budgets.json --check eslint-metrics.json
node scripts/check-lint-budgets.mjs "$RUNNER_TEMP/lint-report.json" eslint-budgets.json
- name: Check for dead code (knip)
if: ${{ !cancelled() && steps.changed.outputs.has_files == 'true' }}

View file

@ -75,19 +75,12 @@ EOF
npx eslint --no-warn-ignored --pass-on-unpruned-suppressions "${eslint_rel[@]}" || rc=1
fi
# Whole-folder lint budgets, exactly as the frontend-lint job runs them: the
# counts and the committed metrics file are not diff-scoped, so a local pass
# here means the budget step will pass in CI too. Unlike CI (which --checks and
# fails), regenerate eslint-metrics.json from the same report — same as the
# gen:api block below regenerates schema.d.ts — then flag drift so you re-stage
# it, instead of making you run npm run lint:metrics by hand.
# counts are not diff-scoped, so a local pass here means the budget step will
# pass in CI too.
report=$(mktemp)
npx eslint . -f json -o "$report" || true
node scripts/check-lint-budgets.mjs "$report" eslint-budgets.json --write eslint-metrics.json || rc=1
node scripts/check-lint-budgets.mjs "$report" eslint-budgets.json || rc=1
rm -f "$report"
if ! git diff --quiet -- eslint-metrics.json; then
echo "✗ eslint-metrics.json was stale; regenerated it. Stage it and re-run make pre-commit." >&2
rc=1
fi
exit $rc
)
}

View file

@ -1,8 +0,0 @@
{
"@typescript-eslint/no-explicit-any": 1971,
"complexity": 129,
"local/no-large-inline-object-arg": 501,
"local/no-long-condition-chain": 234,
"max-depth": 59,
"no-console": 16
}

View file

@ -8,7 +8,6 @@
"build": "next build",
"start": "next start",
"lint": "eslint .",
"lint:metrics": "node scripts/update-lint-metrics.mjs",
"test": "vitest",
"test:dot": "vitest --reporter=dot",
"test:watch": "vitest -w",

View file

@ -1,20 +1,7 @@
import { readFileSync, writeFileSync } from "fs";
import { countBudgetViolations, findDrift } from "./lint-budget-lib.mjs";
import { readFileSync } from "fs";
import { countBudgetViolations } from "./lint-budget-lib.mjs";
const argv = process.argv.slice(2);
const positional = [];
const flags = {};
for (let i = 0; i < argv.length; i += 1) {
if (argv[i] === "--check") {
flags.check = argv[(i += 1)];
} else if (argv[i] === "--write") {
flags.write = argv[(i += 1)];
} else {
positional.push(argv[i]);
}
}
const [reportPath, budgetsPath] = positional;
const [reportPath, budgetsPath] = process.argv.slice(2);
const report = JSON.parse(readFileSync(reportPath, "utf8"));
const budgets = JSON.parse(readFileSync(budgetsPath, "utf8"));
const counts = countBudgetViolations(report, budgets);
@ -32,25 +19,4 @@ for (const [rule, { max, target }] of Object.entries(budgets)) {
}
}
if (flags.write) {
writeFileSync(flags.write, JSON.stringify(counts, null, 2) + "\n");
console.log(`Wrote ${flags.write}.`);
}
if (flags.check) {
const committed = JSON.parse(readFileSync(flags.check, "utf8"));
const drift = findDrift(committed, counts);
for (const { rule, committed: was, actual } of drift) {
console.error(
`::error::${flags.check} is stale for ${rule}: committed ${was ?? "missing"}, actual ${actual ?? "not a tracked rule"}.`,
);
}
if (drift.length > 0) {
console.error(`::error::Run \`npm run lint:metrics\` and commit ${flags.check}.`);
failed = true;
} else {
console.log(`${flags.check} is up to date.`);
}
}
process.exit(failed ? 1 : 0);

View file

@ -13,10 +13,3 @@ export function countBudgetViolations(report, budgets) {
.map((rule) => [rule, counts[rule] || 0]),
);
}
export function findDrift(committed, actual) {
const rules = [...new Set([...Object.keys(actual), ...Object.keys(committed)])].sort();
return rules
.filter((rule) => committed[rule] !== actual[rule])
.map((rule) => ({ rule, committed: committed[rule] ?? null, actual: actual[rule] ?? null }));
}

View file

@ -1,25 +0,0 @@
import { execSync } from "child_process";
import { mkdtempSync, readFileSync, writeFileSync, rmSync } from "fs";
import { tmpdir } from "os";
import { join } from "path";
import { countBudgetViolations } from "./lint-budget-lib.mjs";
const ESLINT_EXIT_LINT_ERRORS = 1;
const budgets = JSON.parse(readFileSync("eslint-budgets.json", "utf8"));
const dir = mkdtempSync(join(tmpdir(), "litellm-lint-"));
const reportPath = join(dir, "report.json");
try {
execSync(`npx eslint . -f json -o "${reportPath}"`, { stdio: "inherit" });
} catch (err) {
if (err.status !== ESLINT_EXIT_LINT_ERRORS) throw err;
}
const report = JSON.parse(readFileSync(reportPath, "utf8"));
rmSync(dir, { recursive: true, force: true });
const metrics = countBudgetViolations(report, budgets);
writeFileSync("eslint-metrics.json", JSON.stringify(metrics, null, 2) + "\n");
console.log("Updated eslint-metrics.json");
console.table(metrics);

View file

@ -1,5 +1,5 @@
import { describe, it, expect } from "vitest";
import { countBudgetViolations, findDrift } from "../scripts/lint-budget-lib.mjs";
import { countBudgetViolations } from "../scripts/lint-budget-lib.mjs";
const budgets = {
"@typescript-eslint/no-explicit-any": { max: 10, target: 5 },
@ -35,21 +35,3 @@ describe("countBudgetViolations", () => {
]);
});
});
describe("findDrift", () => {
it("reports no drift when the snapshot matches the actual counts", () => {
expect(findDrift({ complexity: 5 }, { complexity: 5 })).toEqual([]);
});
it("detects a changed count", () => {
expect(findDrift({ complexity: 5 }, { complexity: 7 })).toEqual([{ rule: "complexity", committed: 5, actual: 7 }]);
});
it("detects a rule missing from the committed snapshot", () => {
expect(findDrift({}, { complexity: 7 })).toEqual([{ rule: "complexity", committed: null, actual: 7 }]);
});
it("detects a phantom rule the committed snapshot still carries", () => {
expect(findDrift({ "removed-rule": 3 }, {})).toEqual([{ rule: "removed-rule", committed: 3, actual: null }]);
});
});