Files
OmniRoute/scripts/check/check-tracked-artifacts.mjs
Diego Rodrigues de Sa e Souza ed6a19e05b fix(ci): raise the git ls-files buffer in check:tracked-artifacts (#8844)
* fix(ci): raise the git ls-files buffer in check:tracked-artifacts

`execFileSync` defaults to a 1 MiB stdout buffer and throws ENOBUFS past it.
`git ls-files -s` on this repo is already at 1,042,494 bytes across 11,091
tracked files — 6,082 bytes from the ceiling. Any PR adding roughly sixty files
crosses it.

That matters more than a failing script: the check runs on pre-commit, so once
the listing crosses 1 MiB, committing breaks for everyone working the repo, not
just for the change that happened to cross it. It is not a hypothetical — the
private EE fork hit it this week when a sync landed ~214 translation files and
pushed the listing 504 bytes over; every commit there failed the hook until
this same fix landed.

Both call sites now share a GIT_LS_OPTS with a 64 MiB ceiling — far above any
plausible tree, rather than just above today's, since the listing only grows.

* docs(changelog): add fragment for #8844

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-07-28 10:25:21 -03:00

109 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// scripts/check/check-tracked-artifacts.mjs
// Gate: falha se o git rastreia artefatos de build/artefatos gerados proibidos.
// Guarda contra `git add -A` acidental em worktrees que include node_modules symlinks.
// Incidente registrado 2× neste repo (v3.8.12 / v3.8.13) — Hard Rule #7 extensão.
//
// Artefatos proibidos:
// - node_modules/ — deps de build nunca devem entrar no repo
// - .next/ — output do build Next.js
// - coverage/ — relatórios de cobertura gerados pelo c8
// - quality-metrics.json — saída do collect-metrics.mjs (gerado, não-versionado)
// - symlinks rastreados (mode 120000) — indício de `git add -A` em worktree
import { execFileSync } from "node:child_process";
import { pathToFileURL } from "node:url";
const FORBIDDEN_PREFIXES = ["node_modules/", ".next/", "coverage/"];
const FORBIDDEN_EXACT = new Set([
"quality-metrics.json", // legacy root location (still forbidden if a stale run writes it)
"config/quality/quality-metrics.json", // current generated location (collect-metrics.mjs)
]);
/**
* Verifica se algum caminho na lista de arquivos rastreados corresponde a um
* artefato proibido. Também aceita uma lista separada de symlinks rastreados.
*
* @param {string[]} trackedFiles - saída de `git ls-files` (caminhos relativos)
* @param {string[]} trackedSymlinks - caminhos com mode 120000 (saída de git ls-files -s)
* @returns {string[]} lista de violações (strings descritivas)
*/
export function checkTrackedArtifacts(trackedFiles, trackedSymlinks = []) {
const violations = [];
for (const file of trackedFiles) {
if (FORBIDDEN_EXACT.has(file)) {
violations.push(`forbidden tracked artifact: ${file}`);
continue;
}
for (const prefix of FORBIDDEN_PREFIXES) {
if (file.startsWith(prefix)) {
violations.push(`forbidden tracked artifact (${prefix}*): ${file}`);
break;
}
}
}
for (const sym of trackedSymlinks) {
violations.push(`forbidden tracked symlink (mode 120000): ${sym}`);
}
return violations;
}
/**
* `execFileSync` defaults to a 1 MiB stdout buffer and throws ENOBUFS past it.
* This check runs on pre-commit, so crossing that line breaks committing for
* the whole repo, not just the change that crossed it. `git ls-files -s` is
* already at ~1.04 MB here and only grows, so the ceiling is set far above any
* plausible tree instead of just above today's.
*/
const GIT_LS_OPTS = { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 };
function getTrackedFiles() {
const output = execFileSync("git", ["ls-files"], GIT_LS_OPTS);
return output
.split("\n")
.map((l) => l.trim())
.filter(Boolean);
}
function getTrackedSymlinks() {
// git ls-files -s prints: <mode> <hash> <stage>\t<path>
// mode 120000 = symlink
const output = execFileSync("git", ["ls-files", "-s"], GIT_LS_OPTS);
const symlinks = [];
for (const line of output.split("\n")) {
if (line.startsWith("120000")) {
const parts = line.split("\t");
if (parts[1]) symlinks.push(parts[1].trim());
}
}
return symlinks;
}
function main() {
const trackedFiles = getTrackedFiles();
const trackedSymlinks = getTrackedSymlinks();
const violations = checkTrackedArtifacts(trackedFiles, trackedSymlinks);
if (violations.length === 0) {
console.log("[tracked-artifacts] OK — no forbidden artifacts tracked by git");
process.exit(0);
}
console.error(
`[tracked-artifacts] FAIL — ${violations.length} forbidden artifact(s) tracked by git:`
);
for (const v of violations) {
console.error(`${v}`);
}
console.error(
"\n → Run: git rm --cached <path> to untrack the artifact." +
"\n → Add the path to .gitignore to prevent re-tracking."
);
process.exit(1);
}
if (import.meta.url === pathToFileURL(process.argv[1] || "").href) main();