Conventional Commits e semantic versioning: automação de changelog e release
1. Fundamentos do Conventional Commits
Conventional Commits é uma especificação que estabelece uma convenção para mensagens de commit, criando um formato padronizado que permite a automação de processos como geração de changelog e versionamento semântico. A estrutura básica de uma mensagem de commit segue este padrão:
<tipo>(<escopo opcional>): <descrição>
<corpo opcional>
<rodapé opcional>
Os tipos principais são:
- feat: introduz uma nova funcionalidade
- fix: corrige um bug
- BREAKING CHANGE: indica uma mudança que quebra compatibilidade
Tipos auxiliares incluem docs (documentação), refactor (refatoração sem mudança de comportamento), test (adição de testes) e chore (tarefas de manutenção).
Exemplos práticos:
feat(autenticação): adicionar login com Google OAuth
Implementa fluxo completo de autenticação via Google.
BREAKING CHANGE: endpoint de login agora requer token OAuth
fix(api): corrigir validação de email no cadastro
O campo email aceitava formatos inválidos devido a regex incorreta.
A relação com versionamento semântico é direta: BREAKING CHANGE incrementa MAJOR, feat incrementa MINOR e fix incrementa PATCH.
2. Versionamento Semântico (SemVer) na Prática
SemVer define versões no formato MAJOR.MINOR.PATCH. As regras de incremento são:
- MAJOR: incrementado quando há mudanças incompatíveis na API
- MINOR: incrementado quando novas funcionalidades são adicionadas de forma compatível
- PATCH: incrementado quando correções de bugs compatíveis são aplicadas
Exemplo de aplicação com Conventional Commits:
v1.0.0 → commit feat → v1.1.0
v1.1.0 → commit fix → v1.1.1
v1.1.1 → commit BREAKING CHANGE → v2.0.0
Pré-lançamentos usam sufixos como -alpha.1, -beta.2 ou -rc.1. Metadados de build podem ser adicionados com +build.1234.
3. Ferramentas para Automação de Changelog
standard-version
Ferramenta que automatiza bump de versão e geração de changelog baseada em commits convencionais.
npm install --save-dev standard-version
Configuração no package.json:
{
"scripts": {
"release": "standard-version"
}
}
semantic-release
Pipeline completo que analisa commits, versiona automaticamente e publica pacotes.
npm install --save-dev semantic-release
Configuração mínima no package.json:
{
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/github"
]
}
commit-and-tag-version
Alternativa moderna ao standard-version com suporte a monorepo.
npm install --save-dev commit-and-tag-version
4. Configuração de Pipeline de Release Automatizado
Exemplo de workflow com GitHub Actions:
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm ci
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Os plugins do semantic-release funcionam em sequência:
- commit-analyzer: analisa commits desde último release
- release-notes-generator: gera notas de release em Markdown
- changelog: atualiza arquivo CHANGELOG.md
- github: cria release no GitHub com changelog gerado
5. Automação de Changelog com Scripts Customizados
Script em Node.js para extrair commits convencionais:
const { execSync } = require('child_process');
function generateChangelog() {
const log = execSync('git log --oneline --format="%s"').toString();
const commits = log.split('\n').filter(c => c.match(/^(feat|fix|docs|refactor|test|chore)/));
const sections = {
'Features': commits.filter(c => c.startsWith('feat')),
'Bug Fixes': commits.filter(c => c.startsWith('fix')),
'Documentation': commits.filter(c => c.startsWith('docs'))
};
let changelog = '# Changelog\n\n';
for (const [section, items] of Object.entries(sections)) {
if (items.length > 0) {
changelog += `## ${section}\n`;
items.forEach(item => changelog += `- ${item}\n`);
changelog += '\n';
}
}
return changelog;
}
console.log(generateChangelog());
Script shell para filtrar commits por tipo:
#!/bin/bash
echo "### Features"
git log --oneline --grep="^feat"
echo ""
echo "### Bug Fixes"
git log --oneline --grep="^fix"
echo ""
echo "### Breaking Changes"
git log --oneline --grep="BREAKING CHANGE"
6. Boas Práticas e Validação de Commits
commitlint
Valida mensagens de commit no momento do git commit:
npm install --save-dev @commitlint/cli @commitlint/config-conventional
Configuração commitlint.config.js:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'refactor', 'test', 'chore']],
'subject-case': [2, 'always', 'lower-case']
}
};
husky
Configura hooks para validação automática:
npm install husky --save-dev
npx husky init
Criar hook .husky/commit-msg:
#!/bin/sh
npx --no -- commitlint --edit $1
Para monorepo, configure escopos específicos:
rules: {
'scope-enum': [2, 'always', ['frontend', 'backend', 'shared']]
}
7. Casos Especiais e Resolução de Problemas
Merges e rebases
Após um merge, use --no-ff para preservar histórico. Em rebases, evite squash de commits convencionais com tipos diferentes.
Commits com múltiplos tipos
Priorize o tipo mais significativo. Um commit que adiciona feature e corrige bug deve usar feat se a feature for o foco principal.
Monorepo com versionamento independente
Use commit-and-tag-version com configuração por pacote:
{
"bumpFiles": ["packages/*/package.json"],
"skip": {
"tag": true
}
}
Ou utilize semantic-release com o plugin @semantic-release/monorepo:
{
"plugins": [
"@semantic-release/monorepo",
"@semantic-release/commit-analyzer"
]
}
Conclusão
A adoção de Conventional Commits combinada com versionamento semântico cria um fluxo de desenvolvimento previsível e automatizável. Ferramentas como semantic-release e standard-version eliminam erros manuais, enquanto scripts customizados oferecem flexibilidade para projetos específicos. A validação com commitlint e husky garante consistência desde o início, reduzindo retrabalho e melhorando a documentação automática do projeto.
Referências
- Conventional Commits 1.0.0 — Especificação oficial com exemplos completos de mensagens de commit
- Semantic Versioning 2.0.0 — Documentação oficial do versionamento semântico com regras detalhadas
- semantic-release documentation — Guia completo de configuração do pipeline automatizado de releases
- commitlint documentation — Ferramenta de validação de mensagens de commit com regras configuráveis
- standard-version GitHub repository — Automação de versionamento e changelog baseada em Conventional Commits
- Husky documentation — Configuração de hooks Git para automação de validações
- Conventional Changelog — Conjunto de ferramentas para geração de changelog a partir de commits convencionais