Estratégias de tag e release notes automáticas com release-please

1. Introdução ao release-please e seus princípios fundamentais

O release-please é uma ferramenta open-source mantida pelo Google que automatiza todo o ciclo de versionamento e geração de release notes baseada em Conventional Commits. Diferente de ferramentas como semantic-release ou standard-version, o release-please opera gerando Pull Requests de release em vez de executar diretamente no pipeline de CI/CD. Isso oferece uma camada adicional de controle e revisão antes que uma nova versão seja efetivamente publicada.

O princípio fundamental do release-please é simples: ele analisa o histórico de commits desde a última tag, identifica os tipos de alterações (fix, feat, BREAKING CHANGE) e propõe um novo número de versão seguindo o versionamento semântico (semver). A grande vantagem é que ele não modifica diretamente a branch principal — em vez disso, cria um PR de release que pode ser revisado, ajustado e aprovado pela equipe.

2. Configuração inicial e integração com o repositório

Para começar, você precisa instalar o release-please. A maneira mais comum é via GitHub Action, mas também é possível usar via npm ou CLI.

Instalação via npm (para projetos Node.js):

npm install release-please --save-dev

Estrutura do arquivo de configuração (release-please-config.json):

{
  "packages": {
    ".": {
      "release-type": "node",
      "changelog-path": "CHANGELOG.md",
      "bump-minor-pre-major": true,
      "bump-patch-for-minor-pre-major": false,
      "draft": false,
      "prerelease": false
    }
  },
  "plugins": []
}

Configuração básica para monorepo com múltiplos pacotes:

{
  "packages": {
    "packages/backend": {
      "release-type": "node",
      "changelog-path": "CHANGELOG.md"
    },
    "packages/frontend": {
      "release-type": "node",
      "changelog-path": "CHANGELOG.md"
    }
  },
  "plugins": ["sentence-case"]
}

3. Estratégias de versionamento e tag automática

O release-please segue estritamente o versionamento semântico baseado nos tipos de commit:

  • fix: incrementa o patch (1.0.0 → 1.0.1)
  • feat: incrementa o minor (1.0.0 → 1.1.0)
  • BREAKING CHANGE (no corpo do commit): incrementa o major (1.0.0 → 2.0.0)

Exemplo de commits que geram versões diferentes:

git commit -m "fix: corrige erro de validação no formulário"
# Resultado: 1.0.0 → 1.0.1

git commit -m "feat: adiciona suporte a autenticação OAuth"
# Resultado: 1.0.0 → 1.1.0

git commit -m "feat: nova API de pagamentos

BREAKING CHANGE: a interface de pagamentos foi completamente refatorada"
# Resultado: 1.0.0 → 2.0.0

Para monorepos, use --monorepo-tags para gerar tags específicas por pacote:

release-please release-pr --monorepo-tags --repo-url=meu/repo

Isso produzirá tags como packages/backend-v1.2.0 e packages/frontend-v2.0.1.

4. Geração automática de release notes com templates

O release-please gera automaticamente release notes organizadas em seções. A estrutura padrão inclui:

  • Features: commits do tipo feat
  • Bug Fixes: commits do tipo fix
  • Documentation: commits do tipo docs
  • Miscellaneous: outros tipos de commit

Template personalizado para release notes:

# Changelog

## [{{version}}] - {{date}}

### 🚀 Novas Funcionalidades
{{#each commits}}
{{#if (eq type "feat")}}
- **{{scope}}**: {{subject}}
{{/if}}
{{/each}}

### 🐛 Correções de Bugs
{{#each commits}}
{{#if (eq type "fix")}}
- **{{scope}}**: {{subject}}
{{/if}}
{{/each}}

### 📚 Documentação
{{#each commits}}
{{#if (eq type "docs")}}
- {{subject}}
{{/if}}
{{/each}}

Para monorepos, você pode agrupar por escopo:

### Pacote: {{packageName}}
{{#each commits}}
- **{{type}}**: {{subject}}
{{/each}}

5. Integração com CI/CD (GitHub Actions e GitLab CI)

Workflow completo para GitHub Actions:

name: Release Please

on:
  push:
    branches:
      - main

jobs:
  release-please:
    runs-on: ubuntu-latest
    steps:
      - uses: google-github-actions/release-please-action@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          release-type: node
          package-name: meu-projeto
          monorepo-tags: true
          changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"docs","section":"Documentation","hidden":true}]'

Para ambientes com staging e produção:

name: Release Please Staging

on:
  push:
    branches:
      - develop

jobs:
  release-please-staging:
    runs-on: ubuntu-latest
    steps:
      - uses: google-github-actions/release-please-action@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          release-type: node
          prerelease: true
          prerelease-type: beta

Publicação automática no npm após release:

jobs:
  release-please:
    outputs:
      release_created: ${{ steps.release.outputs.release_created }}
    steps:
      - id: release
        uses: google-github-actions/release-please-action@v4

      - uses: actions/checkout@v4
        if: ${{ steps.release.outputs.release_created }}

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          registry-url: 'https://registry.npmjs.org'
        if: ${{ steps.release.outputs.release_created }}

      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
        if: ${{ steps.release.outputs.release_created }}

6. Estratégias avançadas e boas práticas

Atualização de versão em arquivos de manifesto com extra-files:

{
  "packages": {
    ".": {
      "extra-files": [
        {
          "type": "json",
          "path": "package.json",
          "jsonpath": "$.version"
        },
        {
          "type": "generic",
          "path": "Dockerfile",
          "replacement": "ARG VERSION={{version}}"
        },
        {
          "type": "yaml",
          "path": "chart/Chart.yaml",
          "jsonpath": "$.version"
        }
      ]
    }
  }
}

Controle de versão com múltiplos mantenedores:

Para evitar conflitos em PRs de release, estabeleça uma política clara:

  1. Sempre que um PR de release for aberto, nenhum novo commit deve ser feito na branch principal até que o PR seja aprovado e mergeado.
  2. Use labels como do-not-merge ou release-pending para identificar PRs de release.
  3. Configure proteções de branch para exigir aprovação de pelo menos dois mantenedores.

Estratégias de rollback:

Caso um release precise ser revertido, use o comando:

git revert <tag-da-versão-anterior>
# Ou crie um commit com "fix: reverte alteração problemática"

O release-please reconhecerá o commit de revert e criará um patch adequado.

7. Monitoramento, manutenção e troubleshooting

Interpretação de logs do release-please em CI:

# Log de sucesso
[release-please] Found 12 commits since last tag v1.0.0
[release-please] Bumping version from 1.0.0 to 1.1.0
[release-please] Creating release PR #42

# Log de erro comum
[release-please] No conventional commits found since last release
# Causa: commits não seguem o formato Conventional Commits
# Solução: revise os commits e force um novo push

Erros comuns e soluções:

  1. Commits sem conventional: Configure um hook de pre-commit para validar mensagens:
npm install @commitlint/config-conventional @commitlint/cli
# Adicione .commitlintrc.json com:
{
  "extends": ["@commitlint/config-conventional"]
}
  1. Conflitos de merge no PR de release: Instrua a equipe a não commitar diretamente na branch principal enquanto o PR de release estiver aberto.

  2. Versões puladas: Se um commit importante for feito após a abertura do PR de release, feche o PR, force um novo push e reabra.

Migração entre versões maiores (v3 → v4):

# v3 (obsoleto)
uses: google-github-actions/release-please-action@v3

# v4 (atual)
uses: google-github-actions/release-please-action@v4
# Principais mudanças:
# - Novo formato de configuração (release-please-config.json)
# - Suporte nativo a monorepos
# - Templates mais flexíveis

Referências