Guías
Escribir checks
El contrato del check, los checks incluidos y cómo escribir el tuyo en cualquier lenguaje.
Última actualización
Un check es la parte ejecutable de una BEC — el programita que de verdad inspecciona tus archivos y dice pasa o falla.
La mayoría de las veces no escribes código. Si tu regla es “este texto no
debe aparecer” (una palabra prohibida, un debugger olvidado, una función
vetada), usa el check incluido forbid y listo — salta a
El camino más rápido. Escribir tu propio check
(el resto de esta página) es solo para casos que forbid no puede expresar.
¿Qué contrato debe seguir un check?
- Entrada: la lista de archivos a chequear, una ruta por línea, por stdin.
- Salida: imprime las violaciones por stdout (becwright las muestra bajo “Found in:”).
- Código de salida:
0= pasa, no-cero = falla. - Directorio de trabajo: la raíz del repo, así las rutas de stdin resuelven directo.
Glosario rápido: stdin/stdout son los canales de entrada/salida estándar por los que un programa lee y escribe. El código de salida es el número que devuelve un programa al terminar —
0significa “todo bien”, cualquier otro significa “encontré un problema”. Esa es toda la interfaz: entran archivos, salen los problemas, y sale con0o no-cero.
El camino más rápido: forbid
Para “este regex no debe aparecer” no necesitas escribir código — usa el check genérico incluido:
- id: no-debugger-js
paths: ["**/*.js", "**/*.ts"]
check: "becwright run forbid --pattern '\\bdebugger\\b'"
severity: blocking
forbid acepta --pattern REGEX, --ignore-case y --message TEXT.
Checks incluidos
| Check | Detecta | Lenguaje |
|---|---|---|
forbid | cualquier regex que pases (--pattern) | cualquiera |
require | un regex (--pattern) que debe estar (inverso de forbid) | cualquiera |
max_lines | archivos con más de --max líneas | cualquiera |
filename | nombres de archivo que matchean --forbid o no matchean --require | cualquiera |
hardcoded_secrets | claves AWS, claves privadas, password = "..." | cualquiera |
dangerous_eval | eval() / exec() | cualquiera |
conflict_markers | marcadores de conflicto de merge olvidados (<<<<<<<) | cualquiera |
no_token_in_logs | tokens/credenciales en llamadas de log | Python |
debug_remnants | breakpoint(), pdb.set_trace(), import pdb | Python |
wildcard_imports | from x import * | Python |
redundant_comments | comentarios que repiten lo obvio del código (heurístico) | Python |
Un check propio (cualquier lenguaje)
Cualquier ejecutable que siga el contrato funciona. Ejemplo en Node, marcando TODO:
#!/usr/bin/env node
const fs = require('fs');
const files = fs.readFileSync(0, 'utf8').split('\n').filter(Boolean);
let bad = false;
for (const f of files) {
fs.readFileSync(f, 'utf8').split('\n').forEach((line, i) => {
if (line.includes('TODO')) { console.log(` ${f}:${i + 1}`); bad = true; }
});
}
process.exit(bad ? 1 : 0);
- id: no-todo
paths: ["**/*.js"]
check: "node .bec/checks/no_todo.js"
severity: warning
Un check incluido en Python sigue el mismo esqueleto — ver
src/becwright/checks/dangerous_eval.py.
¿Cómo se ignora un falso positivo?
Un falso positivo —un patrón que aparece como texto, no como violación real—
se puede suprimir con un marcador becwright: ignore en un comentario de esa
línea, en cualquier lenguaje:
result = eval(expr) # becwright: ignore
console.log(x); // becwright: ignore
El marcador exime a la línea de todos los checks incluidos.
La salvedad de la auto-referencia
Un check de texto/regex no puede correr sobre su propio fuente: un check que
prohíbe la cadena eval( matcheará la mismísima línea de su código que define ese
patrón. Cuando el check de una regla escanearía su propio archivo, acota paths
para excluirlo — p.ej. usa src/becwright/*.py (solo el nivel superior) en vez de
src/becwright/**/*.py para saltar el directorio checks/. Para líneas
individuales, el marcador becwright: ignore de arriba es más simple.