gatefile
Por Rene Turcios. Extrae las puertas de contribución ocultas de un repositorio (asignación primero, reclamo primero, DCO, aval) de su documentación a un contribution-gates.json legible por máquina. CLI y servidor MCP con herramientas extract_gates, validate_gates, gates_badge.
Documentación
gatefile
Compuertas de contribución ocultas, extraídas en un archivo que las máquinas pueden leer.
Cada repositorio oculta sus reglas reales para contribuidores externos: comenta antes de empezar, espera a que te asignen, firma tus commits, consigue un aval, firma un CLA. Hoy descubres esas reglas cuando tu PR se cierra automáticamente. gatefile las extrae de la documentación del propio repositorio en contribution-gates.json, un formato legible por máquinas que las herramientas (como Greenlight) y el CI pueden consumir.
El problema
Un contribuidor elige un issue, escribe el código, abre el PR, y un bot lo cierra: "no estabas asignado", "autores sin aval se cierran automáticamente", "falta Signed-off-by". Las reglas siempre estuvieron en CONTRIBUTING.md, enterradas en prosa, diferentes en cada repositorio. Los mantenedores repiten las mismas correcciones; los contribuidores pierden las mismas noches.
Qué hace gatefile
- extraer: lee CONTRIBUTING.md, plantillas de PR e issues, archivos de flujo DCO/CLA, hooks de lefthook y archivos CLA (desde la API de GitHub o un directorio local) y emite las compuertas que encuentra, cada una con una línea citada real como evidencia.
- validar: compara un
contribution-gates.jsonconfirmado contra una extracción nueva e informa desviaciones (STALE, MISSING, SEVERITY_CHANGED). Código de salida 1 en caso de desviación, para que el CI pueda aplicarlo. - insignia: genera un fragmento de README que informa a los humanos sobre las compuertas en lenguaje sencillo.
El formato contribution-gates.json
{
"version": 1,
"repo": "shadcn-labs/pdfcn",
"generatedFrom": ["CONTRIBUTING.md"],
"gates": [
{
"id": "claim_first",
"kind": "claim_first",
"severity": "blocker",
"evidence": "Comment before starting work, and check the thread first in case someone else is already working on it.",
"source": "CONTRIBUTING.md"
}
],
"conventions": {
"branchNaming": "Name your branch feat/block-name",
"prTitleFormat": "PR titles should follow Conventional Commits",
"requiredChecks": []
}
}
Tipos de compuerta
| tipo | severidad | significado |
|---|---|---|
claim_first | bloqueante | Comenta en el issue antes de empezar a trabajar |
assignment_required | bloqueante | Espera a que te asignen antes de abrir un PR |
discuss_first | bloqueante | Abre una discusión o issue antes de codificar |
issue_first | bloqueante | Cada PR debe estar vinculado a un issue |
vouch_required | bloqueante | Un miembro existente debe avalarte |
collaborators_only | bloqueante | Solo los colaboradores del repositorio pueden abrir PRs |
no_direct_prs | bloqueante | No se aceptan PRs directos |
dco_required | advertencia | Los commits necesitan un aviso Signed-off-by (DCO) |
cla_required | advertencia | Debe firmarse un Acuerdo de Licencia de Contribuidor |
Severidad: las compuertas blocker pueden hacer que un PR se cierre o rechace antes de la revisión. Las compuertas warn pueden corregirse después de abrir el PR. La evidencia es siempre una cita real del archivo fuente, recortada a unos 140 caracteres, nunca inventada.
Uso
CLI
# Extract gates from a repo (GitHub API, GITHUB_TOKEN optional)
gatefile extract shadcn-labs/pdfcn
# Extract from a local clone instead (fully offline)
gatefile extract local --local ./pdfcn --out contribution-gates.json
# Validate the committed file against fresh docs, exit 1 on drift
gatefile validate shadcn-labs/pdfcn --file contribution-gates.json
# Print a README snippet for humans
gatefile badge shadcn-labs/pdfcn
Servidor MCP
Añade a la configuración de tu cliente MCP:
{
"mcpServers": {
"gatefile": {
"command": "node",
"args": ["/path/to/gatefile/dist/mcp.js"]
}
}
}
Herramientas:
| herramienta | entradas | lo que devuelve |
|---|---|---|
extract_gates | repo o localPath | el objeto contribution-gates.json completo |
validate_gates | recorded, repo o localPath | { ok, drift[] } |
gates_badge | repo o localPath | fragmento de markdown para README |
Ejemplo de CI
Mantén el archivo de compuertas honesto en un flujo de trabajo de GitHub Actions:
name: gates
on:
pull_request:
paths: ["CONTRIBUTING.md", ".github/**", "contribution-gates.json"]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npx -y gatefile extract ${{ github.repository }} --out /tmp/fresh.json
- run: npx -y gatefile validate ${{ github.repository }} --file contribution-gates.json
Desarrollo
npm install
npm test # tsx --test, offline, 23 tests
npm run build # tsc to dist/
npm run dev -- extract owner/repo --json
TypeScript ESM, Node 20+, zod para esquemas, fetch nativo para la API de GitHub. Las pruebas usan fixtures del mundo real en test/fixtures/ modelados según casos documentados (comentar-antes-de-empezar más DCO más issue-primero; asignación-primero; solo-aval; permisivo).
Licencia
MIT, Rene Turcios 2026.