Configuração de Automação de Repositório
Estruture a stack completa de commits convencionais + release-please + automação de CI em qualquer repositório. Funciona em repositórios vazios e com conteúdo existente.
Visão Geral
Deslocar para a Esquerda: Capture problemas o mais cedo possível. Uma mensagem de commit ruim capturada no momento do PR custa segundos; a mesma mensagem poluindo as notas de lançamento custa credibilidade. Mova a validação para upstream — imponha o formato do commit no título do PR, valide configurações no CI, capture problemas antes que cheguem à branch principal.
Mais Rápido é Mais Seguro: Lotes menores e lançamentos mais frequentes reduzem o risco. Um lançamento com 3 alterações é mais fácil de depurar do que um com 30. Lançamentos automatizados constroem confiança no próprio processo de lançamento.
Esta skill configura o mecanismo de imposição: a validação do título do PR garante que cada merge na branch principal produza um commit significativo e analisável. O release-please transforma esses commits em lançamentos automatizados com changelogs. O CI captura problemas de configuração e código antes do merge.
Quando Usar
- Iniciando um novo repositório e precisa de automação de lançamento desde o primeiro dia
- Repositório existente não possui versionamento automatizado ou geração de changelog
- Migrando de processos de lançamento manuais ou outras ferramentas de lançamento
- Repositório precisa de validação de título de PR e rotulagem automática
Quando NÃO Usar
- Repositório já tem release-please ou equivalente configurado (verifique primeiro)
- Monorepo com ferramentas de lançamento incompatíveis (ex.: Lerna com versionamento independente já funcionando)
- Repositório é um fork onde o upstream controla o processo de lançamento
Processo
Passo 1: Coletar Configuração
Peça ao usuário estes valores antes de gerar qualquer arquivo:
| Parâmetro | Padrão | Descrição |
|---|---|---|
PROJECT_NAME | (obrigatório) | Nome legível do projeto para documentação |
INITIAL_VERSION | 0.1.0 | Versão semântica inicial |
RELEASE_TYPE | simple | simple (pacote único) ou node / python / etc. |
REPO_LAYOUT | single | single (um pacote na raiz) ou monorepo (vários pacotes) |
PACKAGE_PATHS | . | Para monorepo: caminhos separados por vírgula como packages/api,packages/ui |
DEPENDABOT_ECOSYSTEMS | github-actions | Separados por vírgula: github-actions, npm, pip, cargo, etc. |
DEFAULT_BRANCH | main | Branch que aciona lançamentos |
Detecte o RELEASE_TYPE correto automaticamente:
package.jsonexiste → sugiranodesetup.pyoupyproject.tomlexiste → sugirapythonCargo.tomlexiste → sugirarust- Nenhum dos acima → sugira
simple
Passo 2: Detectar Arquivos Existentes
Antes de criar qualquer coisa, verifique conflitos:
for f in .github/workflows/pull-request.yml .github/workflows/main-branch.yml \
.github/release-please-config.json .release-please-manifest.json \
.github/dependabot.yml .github/pull_request_template.md docs/DEVELOPMENT.md; do
[[ -f "$f" ]] && echo "EXISTS: $f"
done
Se arquivos existirem, mostre um diff do que mudaria e pergunte antes de sobrescrever. Não sobrescreva silenciosamente — arquivos existentes podem conter personalizações específicas do projeto.
Passo 3: Criar Arquivos de Configuração
Crie arquivos nesta ordem (as dependências fluem de cima para baixo):
3a. .github/release-please-config.json
Pacote único:
{
"release-type": "{{RELEASE_TYPE}}",
"bump-minor-pre-major": true,
"bump-patch-for-minor-pre-major": false,
"initial-version": "{{INITIAL_VERSION}}",
"packages": {
".": {}
}
}
Monorepo: Substitua packages por uma entrada por caminho:
{
"packages": {
"packages/api": { "release-type": "node" },
"packages/ui": { "release-type": "node" }
}
}
Cada pacote do monorepo recebe seu próprio release-type — pergunte ao usuário por pacote se eles diferirem.
3b. .release-please-manifest.json
Pacote único:
{
".": "{{INITIAL_VERSION}}"
}
Monorepo: Uma entrada por caminho de pacote, cada um com sua própria versão.
3c. .github/workflows/pull-request.yml
name: Validação de Pull Request
on:
pull_request:
types: [opened, edited, synchronize, reopened]
permissions:
pull-requests: write
contents: read
statuses: write
jobs:
validar-titulo-pr:
name: Validar Título do PR
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
docs
chore
refactor
test
ci
requireScope: false
subjectPattern: ^[a-z].+$
subjectPatternError: |
O assunto "{subject}" encontrado no título do pull request "{title}"
não correspondeu ao padrão configurado. Certifique-se de que o assunto
comece com um caractere minúsculo (por commits convencionais).
rotulagem-automatica:
name: Rotular PR Automaticamente
runs-on: ubuntu-latest
steps:
- name: Rotular com base no título do PR
uses: actions/github-script@v8
with:
script: |
const title = context.payload.pull_request.title;
const labelMap = {
'feat': 'enhancement',
'fix': 'bug',
'docs': 'documentation',
'chore': 'chore',
'refactor': 'refactor',
'test': 'test',
'ci': 'ci'
};
for (const [type, label] of Object.entries(labelMap)) {
if (title.startsWith(`${type}:`) || title.startsWith(`${type}(`)) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: [label]
});
break;
}
}
sem-atribuicao-ia:
name: Sem Atribuição de IA
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Escanear mensagens de commit e corpo do PR
env:
PR_BODY: ${{ github.event.pull_request.body }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
# Apenas formas de trailer/rodapé: um commit que meramente menciona Claude ou
# Anthropic em prosa é aceitável. Trailers de Co-authored-by humanos são aceitáveis.
PAT='^[[:space:]]*Co-authored-by:.*(Claude|Anthropic|noreply@anthropic)|Generated with \[?(Claude|Anthropic)'
fail=0
if git log --format='%B' "$BASE_SHA..$HEAD_SHA" | grep -Eiq "$PAT"; then
echo "::error::Atribuição de IA encontrada em uma mensagem de commit nesta branch"
fail=1
fi
if printf '%s' "$PR_BODY" | grep -Eiq "$PAT"; then
echo "::error::Atribuição de IA encontrada na descrição do PR"
fail=1
fi
[ "$fail" -eq 0 ] && echo "Nenhuma atribuição de IA encontrada."
exit $fail
verificacoes-ci:
name: Verificações de CI
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v6
- name: Validar sintaxe YAML
run: |
sudo apt-get update && sudo apt-get install -y yamllint
find . -name "*.yml" -o -name "*.yaml" | while read file; do
echo "Verificando $file"
yamllint -d "{extends: default, rules: {line-length: disable}}" "$file" || true
done
Sem Atribuição de IA já bloqueia desde o primeiro dia — ela não possui superfície de falso positivo para validar (corresponde a formas de trailer e rodapé, não prosa), portanto não passa pelo caminho de graduação abaixo.
Caminho de graduação de verificação de CI:
- Implante com
continue-on-error: true(informativo, não bloqueante) - Valide que as verificações passam em 3-5 PRs reais
- Remova
continue-on-errore adicione às verificações obrigatórias de proteção de branch - Adicione verificações específicas do projeto (lint, teste, build) conforme a base de código cresce
Nenhum portão pode ser pulado. Se o lint falhar, corrija o lint — não desabilite a regra. Se um teste falhar, corrija o código — não pule o teste. Quando o CI falhar, alimente a saída da falha ao seu agente e corrija antes de enviar novamente.
3d. .github/workflows/main-branch.yml
name: Automação de Lançamento
on:
push:
branches:
- {{DEFAULT_BRANCH}}
permissions:
contents: write
pull-requests: write
jobs:
release-please:
name: Release Please
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- uses: googleapis/release-please-action@v4
id: release
with:
config-file: .github/release-please-config.json
manifest-file: .release-please-manifest.json
atualizar-tag-major:
name: Atualizar Tag de Versão Major
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.release-please.outputs.tag_name }}
- name: Atualizar tag de versão major
env:
TAG_NAME: ${{ needs.release-please.outputs.tag_name }}
run: |
MAJOR_TAG=$(echo "$TAG_NAME" | sed 's/^\(v[0-9]*\).*/\1/')
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -fa "$MAJOR_TAG" -m "Atualizar tag $MAJOR_TAG para $TAG_NAME"
git push origin "$MAJOR_TAG" --force
3e. .github/dependabot.yml
Gere uma entrada updates por ecossistema:
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
labels:
- "dependencies"
commit-message:
prefix: "chore"
include: "scope"
A configuração commit-message garante que os PRs do Dependabot estejam em conformidade com commits convencionais automaticamente (ex.: chore(deps): bump actions/checkout from v5 to v6).
3f. .github/pull_request_template.md
## O que mudou
[Descreva as mudanças em detalhes – isso vai para o changelog]
## Por quê
[Contexto e motivação para a mudança]
## Checklist
- [ ] Título do PR segue o formato de commits convencionais (`tipo: descrição`)
- [ ] Descrição explica o que e por quê (não apenas o que)
- [ ] Nenhum segredo no código, logs ou controle de versão
- [ ] Testes passam localmente
A seção "Por quê" é crítica — descrições de PR que dizem apenas o que mudou são redundantes com o diff. O por quê fornece contexto que torna futuros git-blame úteis.
3g. .gitignore (se ausente)
Verifique se um .gitignore existe. Se não, crie um apropriado para o projeto:
# Dependências
node_modules/
# Saída de build
dist/
build/
.next/
# Ambiente
.env
.env.local
*.pem
# IDE
.idea/
# SO
.DS_Store
Thumbs.db
Adapte à stack detectada. Nunca commite node_modules/, .env ou artefatos de build.
3h. docs/DEVELOPMENT.md
Gere um guia de desenvolvimento cobrindo:
- Fluxo de branch — Desenvolvimento baseado em trunk: branches de recurso curtas (1-3 dias), mescle de volta rapidamente. Nomenclatura de branch:
feature/<desc>,fix/<desc>,chore/<desc>. - Disciplina de commit — Commite livremente dentro de branches (qualquer formato). Apenas o título do PR importa — ele se torna a mensagem de commit squash-merge na branch principal e aparece no changelog.
- Formato do título do PR — Tabela de tipos:
feat,fix,docs,chore,refactor,test,ci. Mudanças irreversíveis:feat!:ouBREAKING CHANGE:no corpo. - Dimensionamento de mudanças — Mire ~100 linhas por PR. ~300 aceitável para mudanças lógicas únicas. ~1000+ deve ser dividido. Separe refatoração de trabalho de recurso — são mudanças diferentes.
- Descrições de PR — Primeira linha: curta, imperativa, autônoma. Corpo: o que está mudando e por quê. Anti-padrões: "Corrigir bug", "Atualizar arquivo", "Fase 1".
- Verificações automatizadas — Validação do título do PR (obrigatória, bloqueia merge), rotulagem automática (informativa), verificações de CI (inicialmente não bloqueantes, graduadas para obrigatórias).
- Processo de lançamento — release-please cria PR de lançamento → merge → lançamento do GitHub + tags + changelog. Progressão de versão: pré-1.0 (
feat→ minor,fix→ patch) vs pós-1.0 (feat→ minor,fix→ patch,BREAKING CHANGE→ major). - Solução de problemas — Problemas comuns: validação do título do PR falha (editar título), falhas nas verificações de CI, merge bloqueado (verificar status obrigatórios).
Use {{PROJECT_NAME}} nos cabeçalhos.
Passo 4: Recomendações de Proteção de Branch
Após a criação dos arquivos, apresente estas etapas manuais (não aplicadas automaticamente):
Configurações recomendadas de proteção de branch do GitHub para {{DEFAULT_BRANCH}}:
✓ Exigir pull request antes de mesclar
✓ Exigir verificações de status: "Validar Título do PR"
✓ Exigir que branches estejam atualizadas
✓ Permitir apenas mesclagem squash
✓ Exigir histórico linear
Por que squash merge: O histórico da branch (commits WIP, correções, experimentos) é preservado no PR. A branch principal obtém um log limpo, significativo e linear onde cada commit é um commit convencional. Isso é o que torna o release-please e o git log --oneline úteis.
Passo 5: Habilitar Permissões do Workflow
O release-please precisa de permissão para criar pull requests via GitHub Actions. Isso está desabilitado por padrão em novos repositórios e fará com que o workflow de Automação de Lançamento falhe com:
GitHub Actions não tem permissão para criar ou aprovar pull requests.
Instrua o usuário a habilitar esta configuração:
GitHub repo → Settings → Actions → General → Workflow permissions:
✓ Permissões de leitura e escrita (necessárias para release-please enviar commits de changelog)
✓ Permitir que GitHub Actions crie e aprove pull requests (necessário para PRs de lançamento)
Esta etapa deve ser concluída antes do primeiro push para {{DEFAULT_BRANCH}}, ou o release-please falhará em cada push até que seja habilitada.
Passo 6: Verificar
# Validar sintaxe YAML
yamllint .github/workflows/*.yml .github/dependabot.yml
# Validar JSON
python3 -c "import json; json.load(open('.github/release-please-config.json'))"
python3 -c "import json; json.load(open('.release-please-manifest.json'))"
# Verificar se todos os arquivos foram criados
for f in .github/workflows/pull-request.yml .github/workflows/main-branch.yml \
.github/release-please-config.json .release-please-manifest.json \
.github/dependabot.yml .github/pull_request_template.md docs/DEVELOPMENT.md; do
if [[ -f "$f" ]]; then
echo "OK: $f"
else
echo "FALTANDO: $f"
fi
done
Passo 7: Commit Inicial
git add .
git commit -m "chore: configurar automação de repositório
Configurar convenção de commits convencionais, validação de PR,
release-please, Dependabot e verificações de CI.
"
git push origin {{DEFAULT_BRANCH}}
A mensagem de commit importa. Comece com o exemplo acima. É o primeiro commit convencional do repositório — defina o tom.
Confirmação final: Antes de executar, mostre ao usuário um resumo do que será configurado:
- Stack de automação: commits convencionais + release-please + CI
- Tipo de lançamento: {{RELEASE_TYPE}}
- Estrutura: {{REPO_LAYOUT}}
- Branch padrão: {{DEFAULT_BRANCH}}
- Versão inicial: {{INITIAL_VERSION}}
- Ecossistemas do Dependabot: {{DEPENDABOT_ECOSYSTEMS}}
Lições Aprendidas
Convenções de Commit
Regra geral: Cada commit na branch principal deve ser legível e significativo. O título do PR é a única mensagem de commit que importa para o changelog.
Títulos de commit ruins para squash:
"fix bugs" → Muito vago
"update file" → Sem contexto
"wip" → Sem sentido
"asdfasdf" → Lixo
"various changes" → Sem resumo
Títulos de commit bons para squash (convencionais):
feat: adicionar endpoint de autenticação de usuário
fix: corrigir referência nula no cálculo de preços
chore: atualizar dependências do lodash para 4.17.21
docs: adicionar guia de início rápido ao README
refactor: extrair lógica de validação para módulo separado
test: adicionar testes de unidade para função de formatação de data
ci: configurar validação de título de PR
Formatação de Título de PR
| Tipo | Descrição | Aparece no Changelog |
|---|---|---|
feat: | Nova funcionalidade | Sim (como mudança de recurso) |
fix: | Correção de bug | Sim (como correção de bug) |
docs: | Mudanças de documentação | Sim (como documentação) |
chore: | Tarefas de manutenção | Sim (como tarefa) |
refactor: | Mudanças na estrutura do código | Sim (como refatoração) |
test: | Adicionar ou corrigir testes | Sim (como testes) |
ci: | Mudanças de configuração de CI | Sim (como CI) |
Tratamento de Erros
O release-please pode rejeitar certas configurações. Trate esses erros:
- Tag não encontrada: Se a verificação falhar por uma tag ausente, a saída
release_createdseráfalse. A etapaatualizar-tag-majortem uma condicionalife será ignorada. - Falha de permissão: O release-please requer
contents: writeepull-requests: write. Defina as permissões na raiz do workflow, não apenas no trabalho. - Conflito de merges: Se um PR de lançamento existir com conflitos, delete-o, aplique as alterações manualmente ou use o commit do release-please como base.
- Validação de esquema: Se o JSON da configuração for inválido, o release-please falhará com um erro indicando a linha e o caractere exatos.
Segurança
Nunca commite segredos:
- Chaves de API, tokens, senhas → use segredos do GitHub Actions
- URLs de banco de dados com credenciais → use variáveis de ambiente
- Arquivos
.env→ garantido pelo.gitignore
Validação de PR:
- A validação do título do PR garante que commits convencionais sejam aplicados
- A verificação de atribuição de IA impede que metadados de ferramentas de IA poluam o histórico do repositório
- A verificação de sintaxe YAML captura problemas de configuração
Perguntas Frequentes
P: Preciso realmente de validação de título de PR?
Sim. Sem ela, as mensagens de commit na branch principal serão uma bagunça. Commits convencionais são a base do versionamento semântico e changelogs automatizados.
P: E se eu precisar de um tipo de commit personalizado?
Adicione-o à lista de types no workflow de validação de título de PR. Veja amannn/action-semantic-pull-request para opções.
P: Posso executar o release-please manualmente?
Sim, você pode acionar o workflow manualmente pela aba "Actions" no GitHub, mas geralmente não é necessário — ele é executado automaticamente a cada push na branch padrão.
P: Como faço para ignorar um commit do changelog?
Use chore: como tipo. Commits chore: ainda aparecem no changelog, mas são agrupados em uma seção de manutenção. Para pular completamente, use [skip release] no corpo da mensagem de commit.
P: O que acontece se eu mesclar um PR sem convenção?
O workflow de validação de título de PR o bloqueará (se configurado como verificação obrigatória). Se você mesclar por bypass, esse commit aparecerá no changelog como uma mensagem genérica, exigindo edição manual.
Notas Adicionais
Cobertura inicial de CI: As verificações de CI são implantadas com continue-on-error: true (informativo, não bloqueante). Esta é uma escolha deliberada para evitar bloquear pushes iniciais. Gradualmente, à medida que o projeto amadurece, remova continue-on-error e adicione verificações adicionais.
Modelo de PR: Inclui campos para "o que" e "por quê" — o "por quê" é mais importante. Sem contexto, futuros desenvolvedores (incluindo você) podem não entender por que uma mudança foi feita.
Padrão de commit: O commit inicial usa chore: como tipo. Isso é apropriado para tarefas de configuração que não são novos recursos ou correções de bugs. O corpo do commit explica o que foi configurado.
Manipulação de arquivos: Sempre verifique arquivos existentes antes de sobrescrever. Mostre um diff e peça confirmação. Isto é especialmente importante em repositórios existentes com workflows de CI existentes.