mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-07 15:52:52 +03:00
fix(quality): clear the cycle's 11 net-new ESLint errors + make validate-release-green suppressions-aware
- executor-kiro/save-call-log/call-logs-correlation tests: replace 15 'as any' casts with typed shapes (net-new no-explicit-any errors from #6213/#6216); prune the now-empty suppression entries so the frozen baseline stays exact - github-skills + usage/call-logs routes: raw toLowerCase().includes() search replaced by matchesSearch() (no-restricted-syntax — Turkish-safe search, behavior covered by tests/unit/call-logs-correlation-substring.test.ts and tests/unit/github-collector.test.ts) - validate-release-green.mjs: run ESLint with --suppressions-location (match the npm run lint contract — frozen debt is not a release red) and raise the lint timeout 15->30min (a full pass takes ~14min alone; the 15min ceiling expired under concurrent suite load and surfaced as 'could not parse eslint json')
This commit is contained in:
@@ -53,7 +53,9 @@ const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
||||
/** Read the committed ratchet baseline value for a metric (null if unknown). */
|
||||
export function baselineValue(metric, root = ROOT) {
|
||||
try {
|
||||
const raw = JSON.parse(readFileSync(join(root, "config/quality/quality-baseline.json"), "utf8"));
|
||||
const raw = JSON.parse(
|
||||
readFileSync(join(root, "config/quality/quality-baseline.json"), "utf8")
|
||||
);
|
||||
const metrics = raw.metrics || raw;
|
||||
const v = metrics?.[metric]?.value;
|
||||
return typeof v === "number" ? v : null;
|
||||
@@ -178,7 +180,13 @@ function main() {
|
||||
const hardCmd = (id, label, cmd, cmdArgs, opts) => {
|
||||
announce(label);
|
||||
const { code, out } = run(cmd, cmdArgs, opts);
|
||||
record({ id, label, kind: "hard", ok: code === 0, detail: code === 0 ? "pass" : firstFailureLine(out) });
|
||||
record({
|
||||
id,
|
||||
label,
|
||||
kind: "hard",
|
||||
ok: code === 0,
|
||||
detail: code === 0 ? "pass" : firstFailureLine(out),
|
||||
});
|
||||
};
|
||||
|
||||
// A ratchet command (check:complexity, check:dead-code, …) exits 1 ONLY on a
|
||||
@@ -189,7 +197,13 @@ function main() {
|
||||
const driftCmd = (id, label, cmd, cmdArgs, okDetail = "within baseline", opts) => {
|
||||
announce(label);
|
||||
const { code, out } = run(cmd, cmdArgs, opts);
|
||||
record({ id, label, kind: "drift", ok: code === 0, detail: code === 0 ? okDetail : firstFailureLine(out) });
|
||||
record({
|
||||
id,
|
||||
label,
|
||||
kind: "drift",
|
||||
ok: code === 0,
|
||||
detail: code === 0 ? okDetail : firstFailureLine(out),
|
||||
});
|
||||
};
|
||||
|
||||
process.stderr.write("🔎 Release-green validation (current working tree)\n\n");
|
||||
@@ -198,14 +212,41 @@ function main() {
|
||||
|
||||
// ESLint: ONE pass → errors (hard) + warnings (drift)
|
||||
{
|
||||
announce("ESLint (errors + warnings — ~3-6min)");
|
||||
const { out } = run("npx", ["eslint", ".", "--format", "json"], { timeout: 15 * 60 * 1000 });
|
||||
announce("ESLint (errors + warnings — ~5-15min)");
|
||||
// Suppressions-aware, matching `npm run lint` (Pacote 4 no-new-warnings): the frozen
|
||||
// pre-existing debt in config/quality/eslint-suppressions.json must not count as
|
||||
// errors here — only NET-NEW violations are release reds. Timeout raised: a full
|
||||
// repo pass takes ~14min alone and this pre-flight often runs alongside test suites.
|
||||
const { out } = run(
|
||||
"npx",
|
||||
[
|
||||
"eslint",
|
||||
".",
|
||||
"--format",
|
||||
"json",
|
||||
"--suppressions-location",
|
||||
"config/quality/eslint-suppressions.json",
|
||||
],
|
||||
{ timeout: 30 * 60 * 1000 }
|
||||
);
|
||||
const parsed = parseEslintJson(out);
|
||||
if (!parsed) {
|
||||
record({ id: "lint", label: "ESLint", kind: "hard", ok: false, detail: "could not parse eslint json" });
|
||||
record({
|
||||
id: "lint",
|
||||
label: "ESLint",
|
||||
kind: "hard",
|
||||
ok: false,
|
||||
detail: "could not parse eslint json",
|
||||
});
|
||||
} else {
|
||||
const { errors, warnings } = eslintCounts(parsed);
|
||||
record({ id: "lint-errors", label: "ESLint errors", kind: "hard", ok: errors === 0, detail: `${errors} error(s)` });
|
||||
record({
|
||||
id: "lint-errors",
|
||||
label: "ESLint errors",
|
||||
kind: "hard",
|
||||
ok: errors === 0,
|
||||
detail: `${errors} error(s)`,
|
||||
});
|
||||
const base = baselineValue("eslintWarnings");
|
||||
const over = isDrift(warnings, base);
|
||||
record({
|
||||
@@ -283,9 +324,20 @@ function main() {
|
||||
driftCmd("complexity", "Cyclomatic complexity (ratchet)", npmCmd, ["run", "check:complexity"]);
|
||||
driftCmd("dead-code", "Dead-code (ratchet)", npmCmd, ["run", "check:dead-code"]);
|
||||
driftCmd("type-coverage", "Type coverage (ratchet)", npmCmd, ["run", "check:type-coverage"]);
|
||||
driftCmd("compression-budget", "Compression budget (ratchet)", npmCmd, ["run", "check:compression-budget"]);
|
||||
driftCmd("openapi-coverage", "OpenAPI route coverage (ratchet)", npmCmd, ["run", "check:openapi-coverage"]);
|
||||
driftCmd("workflow-lint", "Workflow lint (zizmor ratchet)", npmCmd, ["run", "check:workflows", "--", "--ratchet"]);
|
||||
driftCmd("compression-budget", "Compression budget (ratchet)", npmCmd, [
|
||||
"run",
|
||||
"check:compression-budget",
|
||||
]);
|
||||
driftCmd("openapi-coverage", "OpenAPI route coverage (ratchet)", npmCmd, [
|
||||
"run",
|
||||
"check:openapi-coverage",
|
||||
]);
|
||||
driftCmd("workflow-lint", "Workflow lint (zizmor ratchet)", npmCmd, [
|
||||
"run",
|
||||
"check:workflows",
|
||||
"--",
|
||||
"--ratchet",
|
||||
]);
|
||||
driftCmd("codeql-ratchet", "CodeQL alerts (ratchet)", npmCmd, ["run", "check:codeql-ratchet"]);
|
||||
|
||||
// Docs sync + fabricated-docs (strict) is a real-defect gate (invented env vars /
|
||||
@@ -298,15 +350,35 @@ function main() {
|
||||
// with 15 such reds). They run SILENTLY for many minutes; the announce line above + these
|
||||
// hard ceilings keep a long-but-healthy run from being mistaken for a hang (the ceiling also
|
||||
// converts a genuine DB-handle hang into a visible failure instead of an infinite block).
|
||||
hardCmd("unit", "Unit tests (full suite, CI concurrency — runs ~20-35min silently)", npmCmd, ["run", "test:unit:ci"], { timeout: 45 * 60 * 1000 });
|
||||
hardCmd("vitest", "Vitest (MCP / autoCombo / cache — ~3-8min)", npmCmd, ["run", "test:vitest"], { timeout: 15 * 60 * 1000 });
|
||||
hardCmd(
|
||||
"unit",
|
||||
"Unit tests (full suite, CI concurrency — runs ~20-35min silently)",
|
||||
npmCmd,
|
||||
["run", "test:unit:ci"],
|
||||
{ timeout: 45 * 60 * 1000 }
|
||||
);
|
||||
hardCmd(
|
||||
"vitest",
|
||||
"Vitest (MCP / autoCombo / cache — ~3-8min)",
|
||||
npmCmd,
|
||||
["run", "test:vitest"],
|
||||
{ timeout: 15 * 60 * 1000 }
|
||||
);
|
||||
// Integration tests run ONLY on the release PR full CI (PR→main), so an assertion
|
||||
// regression here (e.g. a contributor flipping a Codex fingerprint key order) is
|
||||
// invisible until release — run them in the pre-flight as a HARD gate.
|
||||
hardCmd("integration", "Integration tests (~3-10min)", npmCmd, ["run", "test:integration"], { timeout: 20 * 60 * 1000 });
|
||||
hardCmd("integration", "Integration tests (~3-10min)", npmCmd, ["run", "test:integration"], {
|
||||
timeout: 20 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
if (WITH_BUILD) {
|
||||
hardCmd("pack-artifact", "Package artifact (npm pack policy)", npmCmd, ["run", "check:pack-artifact"], { timeout: 20 * 60 * 1000 });
|
||||
hardCmd(
|
||||
"pack-artifact",
|
||||
"Package artifact (npm pack policy)",
|
||||
npmCmd,
|
||||
["run", "check:pack-artifact"],
|
||||
{ timeout: 20 * 60 * 1000 }
|
||||
);
|
||||
}
|
||||
|
||||
const { releaseGreen, hardFailures, drift } = computeVerdict(results);
|
||||
|
||||
Reference in New Issue
Block a user