becwright

Guías

Escribir checks

El contrato del check, los checks incluidos y cómo escribir el tuyo en cualquier lenguaje.

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.

El contrato

  • Entrada: la lista de archivos a chequear, una ruta por línea, por stdin.
  • Salida: imprimí 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 — 0 significa “todo bien”, cualquier otro significa “encontré un problema”. Esa es toda la interfaz: entran archivos, salen los problemas, y sale con 0 o no-cero.

El camino más rápido: forbid

Para “este regex no debe aparecer” no necesitás escribir código — usá 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

CheckDetectaLenguaje
forbidcualquier regex que pases (--pattern)cualquiera
no_token_in_logstokens/credenciales en llamadas de logPython
hardcoded_secretsclaves AWS, claves privadas, password = "..."cualquiera
debug_remnantsbreakpoint(), pdb.set_trace(), import pdbPython
dangerous_evaleval() / exec()cualquiera
wildcard_importsfrom x import *Python
redundant_commentscomentarios 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.

Ignorar una línea

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, acotá paths para excluirlo — p.ej. usá 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.