gatefile

Por Rene Turcios. Extrai os portões de contribuição ocultos de um repositório (atribuição primeiro, reivindicação primeiro, DCO, aval) de sua documentação para um contribution-gates.json legível por máquina. CLI e servidor MCP com ferramentas extract_gates, validate_gates, gates_badge.

Documentação

gatefile

Portões de contribuição ocultos, extraídos para um arquivo que máquinas podem ler.

Todo repositório esconde suas regras reais para contribuidores externos: comente antes de começar, aguarde ser designado, assine seus commits, seja referendado, assine um CLA. Hoje você descobre essas regras ao ter seu PR fechado automaticamente. O gatefile as extrai da documentação do próprio repositório para contribution-gates.json, um formato legível por máquinas que ferramentas (como Greenlight) e CI podem consumir.

O problema

Um contribuidor escolhe uma issue, escreve o código, abre o PR, e um bot o fecha: "você não foi designado", "autores sem referendo são fechados automaticamente", "Signed-off-by ausente". As regras sempre estiveram no CONTRIBUTING.md, enterradas em prosa, diferentes em cada repositório. Mantenedores repetem as mesmas correções; contribuidores desperdiçam as mesmas noites.

O que o gatefile faz

  1. extrair: lê CONTRIBUTING.md, templates de PR e issue, arquivos de fluxo DCO/CLA, hooks do lefthook e arquivos de CLA (da API do GitHub ou de um diretório local) e emite os portões encontrados, cada um com uma linha real citada como evidência.
  2. validar: compara um contribution-gates.json commitado contra uma extração nova e relata divergências (STALE, MISSING, SEVERITY_CHANGED). Código de saída 1 em caso de divergência, para que o CI possa aplicá-lo.
  3. badge: renderiza um trecho de README que informa aos humanos os portões em linguagem simples.

O 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 portão

tiposeveridadesignificado
claim_firstbloqueadorComente na issue antes de começar o trabalho
assignment_requiredbloqueadorAguarde ser designado antes de abrir um PR
discuss_firstbloqueadorAbra uma discussão ou issue antes de codificar
issue_firstbloqueadorTodo PR deve estar vinculado a uma issue
vouch_requiredbloqueadorUm membro existente deve referendar você
collaborators_onlybloqueadorSomente colaboradores do repositório podem abrir PRs
no_direct_prsbloqueadorPRs diretos não são aceitos
dco_requiredavisoCommits precisam de um trailer Signed-off-by (DCO)
cla_requiredavisoUm Contrato de Licença de Contribuidor deve ser assinado

Severidade: portões blocker podem fazer um PR ser fechado ou rejeitado antes da revisão. Portões warn podem ser corrigidos após a abertura do PR. A evidência é sempre uma citação real do arquivo de origem, reduzida a cerca de 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

Adicione à configuração do seu cliente MCP:

{
  "mcpServers": {
    "gatefile": {
      "command": "node",
      "args": ["/path/to/gatefile/dist/mcp.js"]
    }
  }
}

Ferramentas:

ferramentaentradaso que retorna
extract_gatesrepo ou localPatho objeto contribution-gates.json completo
validate_gatesrecorded, repo ou localPath{ ok, drift[] }
gates_badgerepo ou localPathtrecho de markdown para README

Exemplo de CI

Mantenha o arquivo de portões íntegro em um fluxo de trabalho do 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

Desenvolvimento

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 a API do GitHub. Os testes usam fixtures do mundo real em test/fixtures/ modelados em casos documentados (comentar antes de começar mais DCO mais issue-primeiro; designação-primeiro; somente referendo; permissivo).

Licença

MIT, Rene Turcios 2026.