Versionamento semântico: um passo além do Git

Jessica Temporal
Operação Serenata de Amor
5 min readAug 14, 2017

--

“No mundo de gerenciamento de software existe algo terrível conhecido como inferno das dependências (“dependency hell”). Quanto mais o sistema cresce, e mais pacotes são adicionados a ele, maior será a possibilidade de, um dia, você encontrar-se neste poço de desespero.” — Versionamento Semântico 2.0

Pacotes, sejam eles escritos em Python, Ruby ou JavaScript, além de terem seu código versionado por sistema como o git, podem possuir mais um nível de controle de versão: o versionamento semântico.

Principalmente se você disponibiliza seu pacote em indexes como o PyPI, o versionamento semântico ajuda o usuário final a entender novas features implementadas, bugs resolvidos e garantir compatibilidade de código sem ter quer ler o código do último pull request.

Dependency Hell: O caso Jarbas

Ocorreu nessa primeira semana de Agosto com o Jarbas.

Nós usamos o PyUP para manter a lista de dependências do Jarbas atualizadas automaticamente. O PyUP lê o arquivo requirements.txt e checa se as bibliotecas ali listadas estão na sua versão mais recente. Caso não estejam, o PyUP abre um pull request no repositório do Jarbas com a atualização das versões do arquivo dependências.

Um pacote que utilizamos, o reprint — que está na lista de dependências — lançou há algumas semanas a versão 0.4.0, e rodando os testes unitários com a versão mais recente do mesmo, todos os testes continuaram passando.

Porém, ao tentar rodar o comando que popula o banco com os dados dos reembolsos, um novo contribuidor se deparou com um erro ao tentar carregar os dados de reembolsos como descrito na issue #223 do Jarbas.

O comando que três dias antes funcionava como esperado não funcionava mais (para nossa surpresa). Duas coisas chamaram atenção nesse momento:

  1. Nenhuma alteração tinha sido feita nesse comando ou em algo que esse comando dependesse nos últimos pull requests aceitos;
  2. O traceback mostrava que o erro acontecia exatamente a linha que usava uma função de uma biblioteca externa;

Depois de um pouco de debugging ficou clara a hipótese de que o que quebrou nosso código foi realmente algo “de fora” do projeto. E, um pouco de busca mostrou que precisamente, o reprint que havia mudado parte do código da função que nós estamos utilizando.

O jeito mais fácil de testar e confirmar a teoria? Reinstalar a versão anterior do pacote e tentar rodar novamente o comando. Feito isso, confirmamos as suspeitas: a versão 0.4.0 quebra o Jarbas.

Se o reprint não versionasse as suas alterações de código — além do tradicional git — seria muito mais difícil voltar a usar a versão 0.3.0. Esse caso torna claro de que ter ocorrido o incremento da versão para acompanhar a mudança no código tornou possível e relativamente fácil de voltar a usar localmente a versão 0.3.0.

Versionamento pra que te quero

Até a issue #34, a versão da Toolbox não sofreu nenhum bump (aumentar o número da versão para indicar mudança no pacote). E ela só foi resolvida quando tivemos o problema de estar utilizando código desatualizado despercebidamente nos nossos ambientes virtuais. Nesse momento se tornou clara a necessidade de atualizar e de fato realizar o versionamento da Toolbox a medida que essa evolui ou passa por melhorias.

E então a grande questão era: Como versionar? Contar as versões do zero a partir daquele momento ou considerar o que já foi feito? Seguir algum padrão e se sim qual?

É também na issue #34 que está documentada a primeira tentativa de formalizar o versionamento da Toolbox e levar em consideração todas as mudanças pelas quais o pacote passou desde o Primeiro commit. Essa primeira tentava seguir as especificações trazidas pelo PEP-440 e praticamente consistiu em olhar todos os pull requests aceitos na Toolbox e identificar o “grau” da mudança que aquele novo código traz para o pacote.

Depois disso a formalização do versionamento ainda sofreu mais algumas mudanças até que chegamos ao que usamos hoje: Versionamento semântico.

O que de fato é versionamento semântico?

Proposto por Tom Preston-Werner, criador do Gravatars e co-fundador do GitHub, o que ele chama de versionamento semântico (SemVer) é um conjunto de regras baseadas no que ele observou de boas práticas e costumes do desenvolvimento de software. E em poucas linhas, a definição do SemVer se resume a:

“… os números de versão e a forma como eles mudam transmitem o significado do código subjacente e o que foi modificado de uma versão para a próxima.” — SemVer

Então num documento disponível online, Preston-Werner define um conjunto de regras que buscam formalizar a forma de fazer os incrementos das versões:

Dado um número de versão MAJOR.MINOR.PATCH, incremente a:1. versão Maior(MAJOR): quando fizer mudanças incompatíveis na API,
2. versão Menor(MINOR): quando adicionar funcionalidades mantendo compatibilidade, e
3. versão de Correção(PATCH): quando corrigir falhas mantendo compatibilidade.
Rótulos adicionais para pré-lançamento(pre-release) e metadados de construção(build) estão disponíveis como extensão ao formato MAJOR.MINOR.PATCH.

Hoje é exatamente esse modelo que a Toolbox segue. Versionar e seguir um padrão conhecido enquanto o faz, ajuda tanto os mantenedores de projetos que dependem do seu pacote quanto os usuários finais, sejam eles contribuidores ou apenas pessoas que querem usar seu pacote sem necessariamente contribuir com ele.

Versionar é uma arte que nem todos praticam, mas todos deveriam.

Para acompanhar o projeto

Para saber mais sobre o que acontece no dia a dia do projeto, nos siga no Facebook e comece por aqui para contribuir com código.

Além disso você pode fazer com que a Operação Serenata de Amor continue à todo vapor. Também estamos aceitando doações pela carteira de Bitcoin 1Gbvfjmjvur7qwbwNFdPSNDgx66KSdVB5b.

--

--

Jessica Temporal
Operação Serenata de Amor

DevRel 🥑 • Author • 🎙Podcaster @pizzadedados • Creator of GitStudyCards.com • GitHub ⭐️ • cross-stitcher & knitter • 🇧🇷 & 🇨🇦 • she/her