DevOps

Semantic Versioning e Tags de Release Já leu

7 min de leitura

Semantic Versioning e Tags de Release
Imagine receber uma mensagem de um colega dizendo: "o bug está na versão nova". Qual versão nova? Nova em relação a quê

Imagine receber uma mensagem de um colega dizendo: "o bug está na versão nova". Qual versão nova? Nova em relação a quê? Lançada quando?

Sem uma convenção de versionamento, equipes acabam usando nomes arbitrários — "versão de dezembro", "build final", "build final v2", "build final v2 revisado". Em produção, esse caos tem consequências reais: dificuldade em identificar qual código está rodando, impossibilidade de comparar comportamentos entre versões e incapacidade de comunicar claramente o impacto de uma atualização para clientes e parceiros.

O Semantic Versioning — ou SemVer — é a convenção que resolve esse problema. Adotada pela maioria dos projetos de software modernos, ela transforma um número de versão em uma comunicação precisa sobre o que mudou.


A Lógica do SemVer

Um número de versão SemVer tem o formato MAJOR.MINOR.PATCH — por exemplo, 2.4.1.

Cada parte tem um significado definido:

PATCH — incrementado quando são feitas correções de bugs compatíveis com versões anteriores. Quem usa 2.4.0 pode atualizar para 2.4.1 sem preocupação. Nada quebrou, apenas foi corrigido.

MINOR — incrementado quando novas funcionalidades são adicionadas de forma compatível com versões anteriores. Quem usa 2.4.1 pode atualizar para 2.5.0 com segurança — o que já funcionava continua funcionando.

MAJOR — incrementado quando mudanças incompatíveis são introduzidas. Quem usa 2.x precisa ler o changelog antes de atualizar para 3.0.0 — algo pode ter quebrado intencionalmente.

Regras adicionais importantes:

  • Quando MINOR é incrementado, PATCH volta a zero: 2.4.12.5.0
  • Quando MAJOR é incrementado, MINOR e PATCH voltam a zero: 2.5.33.0.0
  • Versões com MAJOR igual a zero (0.x.y) indicam desenvolvimento inicial — a API pública não é considerada estável

Sufixos de Pré-release

Para versões que ainda não estão prontas para produção, o SemVer permite sufixos:

1.0.0-alpha        # primeira fase de testes internos
1.0.0-alpha.2      # segunda iteração do alpha
1.0.0-beta.1       # fase de testes mais ampla
1.0.0-rc.1         # release candidate — candidato a versão final
1.0.0              # versão estável final

Em pipelines de CI/CD, é comum gerar versões de pré-release automaticamente para branches de desenvolvimento, enquanto versões estáveis são geradas apenas a partir de merges na main.


Tags no Git

No Git, uma tag é um ponteiro nomeado para um commit específico. Diferentemente das branches, tags não se movem — elas marcam um ponto fixo no histórico, ideal para representar releases.

# Cria uma tag leve (apenas um ponteiro)
git tag v1.2.0

# Cria uma tag anotada (recomendada — inclui mensagem, autor e data)
git tag -a v1.2.0 -m "Release 1.2.0: adiciona suporte a autenticação OAuth"

# Lista todas as tags
git tag

# Lista tags com filtro
git tag -l "v1.*"

# Mostra detalhes de uma tag anotada
git show v1.2.0

# Cria tag em um commit específico (não necessariamente o mais recente)
git tag -a v1.1.5 abc1234 -m "Hotfix: corrige falha de segurança no login"

Tags precisam ser enviadas explicitamente para o repositório remoto — o git push padrão não as inclui:

# Envia uma tag específica
git push origin v1.2.0

# Envia todas as tags locais
git push origin --tags

Conventional Commits: A Base para Automação

O Semantic Versioning define como nomear versões. O Conventional Commits define como escrever mensagens de commit de forma que ferramentas possam determinar automaticamente qual parte da versão deve ser incrementada.

O formato é simples:

<tipo>[escopo opcional]: <descrição>

[corpo opcional]

[rodapé opcional]

Os tipos mais comuns e sua relação com o SemVer:

# Incrementa PATCH — correção de bug
git commit -m "fix: corrige cálculo incorreto de frete para regiões remotas"

# Incrementa MINOR — nova funcionalidade
git commit -m "feat: adiciona suporte a pagamento via PIX"

# Incrementa MAJOR — mudança incompatível (indicada no rodapé)
git commit -m "feat!: remove suporte à API v1

BREAKING CHANGE: os endpoints /api/v1/* foram removidos.
Migre para /api/v2/* conforme documentação."

# Não incrementa versão — mudanças que não afetam o produto
git commit -m "docs: atualiza exemplos de autenticação no README"
git commit -m "chore: atualiza dependências de desenvolvimento"
git commit -m "ci: adiciona cache de dependências no pipeline"
git commit -m "refactor: extrai lógica de validação para módulo separado"
git commit -m "test: adiciona testes para o módulo de pagamento"

Automatizando Releases com GitHub Actions

Com Conventional Commits no histórico, é possível automatizar completamente o processo de versionamento e geração de changelog. A ferramenta Release Please, mantida pelo Google, faz exatamente isso:

# .github/workflows/release.yml
name: Release

on:
  push:
    branches: [ main ]

permissions:
  contents: write
  pull-requests: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: googleapis/release-please-action@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          release-type: node

O que esse workflow faz: a cada push na main, o Release Please analisa os commits desde a última release, determina qual parte do SemVer deve ser incrementada, cria automaticamente um Pull Request com a atualização de versão e o changelog gerado. Quando esse PR é mergeado, uma tag Git e uma GitHub Release são criadas automaticamente.


Criando uma Release no GitHub Manualmente

Para projetos que preferem controle manual sobre o processo de release:

# Garante que a main está atualizada
git checkout main
git pull

# Cria a tag anotada
git tag -a v2.1.0 -m "Release 2.1.0

Novidades:
- Autenticação via OAuth com Google e GitHub
- Dashboard de métricas em tempo real
- Correção de falha em sessões simultâneas"

# Envia a tag
git push origin v2.1.0

No GitHub, navega-se até Releases → Create a release, seleciona-se a tag criada e adiciona-se as notas de release. O GitHub renderiza o markdown e disponibiliza a release publicamente, com download do código-fonte em zip e tar.gz automaticamente.


Um Fluxo Completo de Versionamento

Reunindo tudo em um cenário real:

# Desenvolvimento da funcionalidade
git checkout -b feature/dashboard-metricas
git commit -m "feat: adiciona componente de gráfico de requisições por minuto"
git commit -m "feat: adiciona filtro por intervalo de datas no dashboard"
git commit -m "test: adiciona testes do componente de gráfico"
git push origin feature/dashboard-metricas

# PR criado, revisado e mergeado na main
# O Release Please detecta dois commits 'feat' e propõe incremento MINOR
# Versão atual: 1.4.2 → proposta: 1.5.0

# PR de release mergeado → tag v1.5.0 criada automaticamente
# Changelog gerado automaticamente:

# ## [1.5.0] - 2025-03-10
# ### Features
# - adiciona componente de gráfico de requisições por minuto
# - adiciona filtro por intervalo de datas no dashboard

Referências para Aprofundamento

Especificações

Ferramentas

  • Release Please — GitHub — Ferramenta do Google para automação de releases baseada em Conventional Commits. Documentação completa no repositório.
  • semantic-release — Alternativa ao Release Please, mais configurável e com ecossistema de plugins. Popular em projetos Node.js.
  • git-cliff — Gerador de changelog altamente configurável, escrito em Rust. Suporta templates customizados para o formato de changelog.

Leitura complementar

  • Keep a Changelog — Guia e convenção para escrita manual de changelogs, em português. Explica os princípios por trás de um bom changelog mesmo quando o processo não é automatizado.
Comentários

Mais em DevOps

SSH: Conectando e Gerenciando Servidores Remotos
SSH: Conectando e Gerenciando Servidores Remotos

SSH &mdash;&nbsp;Secure Shell &mdash; &eacute; o protocolo pelo qual administ...

Trabalhando em Equipe com Git Flow
Trabalhando em Equipe com Git Flow

O Git oferece branches, mas n&atilde;o diz como us&aacute;-las. Em uma equipe...

Processos, Serviços e o Comando `systemctl`
Processos, Serviços e o Comando `systemctl`

Cada programa em execu&ccedil;&atilde;o no Linux &mdash; seja um servidor web...