Versioning workflow

Uma ferramenta de geração automática de versões de código

Davidson Bruno
6 min readApr 27, 2024

Imagine que você vai começar um novo projeto e pretende disponibilizá-lo para que outras pessoas o utilizem: a comunidade de desenvolvimento, seu time, pessoas que estão com você no dia-a-dia, que precisam testar e validar o código que você está construindo. Você decide, então, criar um controle de versões sobre esse código.

Sua equipe tem cinco pessoas. Cada vez que um novo membro de equipe sobe o código para a main , ele precisa verificar qual foi a última tag de versão gerada para criar a próxima release. Cada vez que alguém deseja testar a aplicação no ambiente de homologação, ela precisa gerar uma versão de pré-lançamento. Mas, enquanto ela está trabalhando na versão 0.1.0-rc-2 , o seu outro membro de equipe já havia criado localmente essa versão e percebeu que conflitava com uma tag que já existia no repositório remoto. Então ele precisa manualmente ir no repositório e identificar a última versão gerada para recriar a própria tag e subir o código.

Você poderia dizer "Caramba, quanta perda de tempo. Eu sempre vou testar o último commit, não preciso saber o nome da versão". Eu não vou entrar nos méritos do uso de versões nomeadas do código, mas, posso te garantir que, se você pretende sustentar seu código um dia, vai precisar delas. "Ok, mas, este processo é insustentável" — você poderia dizer. E eu não poderia concordar mais.

É por isso que hoje trago a vocês uma ferramenta que desenvolvi para automatizar o processo de versionamento de código baseado no fluxo de trabalho. Basicamente, são workflows do GitHub Actions que você pode integrar com muita facilidade aos seus projetos. A ferramenta se baseia no conventional commits e em padrões de branches para gerar as versões que, por sua vez, se baseiam no versionamento semântico.

Instalação

Para instalar, é simples: basta copiar os arquivos create-release.yml e create-pre-release.yml do diretório .github/workflows e colar em um diretório de mesmo nome na raiz do seu projeto.

Uso

São dois workflows disponíveis: um de geração de versões de release (oficiais) e outro de versões de pré-release (candidatas). Você pode usar somente o workflow de releases ou combiná-lo com o de pré-release.

Workflow de criação de release

name: Release

on:
push:
branches: ["main"]

jobs:
create_release:
name: Create release
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-release-template.yml@v1
permissions:
contents: write

Essa é a forma mais básica de uso desse workflow. Ele será disparado sempre que mudanças forem percebidas diretamente na branch principal, por meio de pull requests ou commits diretos. As novas versões são geradas a partir da mensagem dos commits na seguinte ordem de precedência:

  1. Commits que iniciam com BREAKING CHANGE: ou <algum_prefixo>!: (note o uso de !) geram novas versões major do código (por exemplo, de 0.1.0 para 1.0.0).
  2. Commits que iniciam com FIRST RELEASE: em versões não públicas do código (versão 0) geram a versão inicial de lançamento do software (versão 1.0.0).
  3. Commits que iniciam com fix: geram novas versões patch do código (por exemplo, de 0.1.0 para 0.1.1).
  4. Commits em qualquer outro padrão geram versões minor do cóldigo (por exemplo, de 0.1.0 para 0.2.0).

Por padrão, main é considerada como a branch principal, mas, você pode modificar isso por meio do parâmetro main_branch:

jobs:
create_release:
name: Create release
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-release-template.yml@v1
permissions:
contents: write
with:
main_branch: "master"

No template do arquivo create-release.yml, você notará que há um job chamado upsert_major_version:

upsert_major_version:
name: Upsert major version
needs: create_release
permissions:
contents: write
uses: davidsonbrsilva/versioning-workflow/.github/workflows/upsert-major-version-template.yml@v1
with:
version: ${{ needs.create_release.outputs.version }}

Esse job é opcional e pode ser removido se você quiser. A cada versão de lançamento, ele gera uma tag v[major_version] (por exemplo, v1) e a mantém atualizada, sempre referenciando a última versão, até que uma nova versão major seja lançada.

Workflow de criação de pré-release

name: Pre-release

on:
pull_request:
branches: ["main"]
types: ["opened", "synchronize", "reopened"]

jobs:
create_release_candidate:
name: Create release candidate
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-pre-release-template.yml@v1
permissions:
contents: write

Essa é a forma mais básica de uso do workflow de pré-release. Ele será disparado em eventos de pull request: na abertura, durante novos commits e na sua reabertura. Cada nova mudança em uma pull request gerará uma versão release candidate (-rc-<number>).

As versões de release candidate são incrementadas a cada nova alteração (por exemplo, de 0.1.0-rc-1 para 0.1.0-rc-2). Novas versões de release candidate (-rc-1) são geradas levando em consideração o nome das branches de origem e o padrão dos commits, na seguinte ordem de precedência:

  1. Commits que começam com BREAKING CHANGE: ou <algum_prefixo>!: gerarão versões major.
  2. Commits que iniciam com FIRST RELEASE: em versões não públicas do código (versão 0) gerarão a versão inicial de lançamento do software (versão 1.0.0).
  3. Branches que correspondem ao parâmetro feature_branches gerarão versões minor do código.
  4. Branches que correspondem ao parâmetro release_branches também gerarão versões minor do código.
  5. Branches que correspondem ao parâmetro hotfix_branches gerarão versões patch do código.

Se a branch não corresponder a nenhum dos padrões anteriores, a versão automática de pré-release não será gerada.

Assim como no workflow de criação de release, você também pode informar um nome diferente para a branch principal por meio de main_branch. O mesmo vale para branches de feature, release e hotfix:

  1. Para gerar versões minor, o workflow procurará por branches que correspondam ao padrão dos parâmetros feature_branches e release_branches. Se algum dos parâmetros não for informado, o valor feature será considerado como nome padrão para feature_branches e release para release_branches.
  2. Para gerar versões patch, o workflow procurará por branches que correspondam ao padrão do parâmetro hotfix_branches. Se o parâmetro não for informado, o valor hotfix será considerado como nome padrão.
create_release_candidate:
name: Create release candidate
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-pre-release-template.yml@v1
permissions:
contents: write
with:
main_branch: "main"
feature_branches: "feature"
release_branches: "release"
hotfix_branches: "hotfix"

Por fim, você também pode usar mais de um nome de branch para os parâmetros feature_branches, release_branches e hotfix_branches, caso queira. Por exemplo:

create_release_candidate:
name: Create release candidate
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-pre-release-template.yml@v1
with:
feature_branches: "feat feature" # aceitará correspondência da branch de origem tanto para 'feat' quanto para 'feature'
release_branches: "rel release" # aceitará correspondência da branch de origem tanto para 'rel' quanto para 'release'
hotfix_branches: "fix hotfix" # aceitará correspondência da branch de origem tanto para 'fix' quanto para 'hotfix'

Usando o prefixo v para as versões

Algumas ferramentas, como o Github, sugerem o uso de versões que comecem com v como, por exemplo, v1.0.0. Você pode habilitar esse comportamento através da flag use_v_prefix:

Workflow de criação de release

create_release:
name: Create release
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-release-template.yml@v1
permissions:
contents: write
with:
use_v_prefix: true

Workflow de criação de pre release

create_release_candidate:
name: Create release candidate
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-pre-release-template.yml@v1
permissions:
contents: write
with:
use_v_prefix: true

Customizando o nome da release

Por padrão, os nomes das releases geradas recebem o nome usado para gerar a versão. Você pode sobrescrever esse comportamento através da propriedade release_name:

Workflow de criação de release

create_release:
name: Create release
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-release-template.yml@v1
permissions:
contents: write
with:
release_name: "My Amazing Release"

Workflow de criação de pre release

create_release_candidate:
name: Create release candidate
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-pre-release-template.yml@v1
permissions:
contents: write
with:
release_name: "My Amazing Release"

Com essa propriedade, todas as releases criadas receberão o nome “My Amazing Release” ao invés do nome da versão.

Adicionando um prefixo ao nome da release

Você também pode definir um prefixo a ser adotado no nome da release. Isso é útil em casos que você ainda deseja manter a versão gerada no nome da release, mas quiser adicionar um prefixo de nome de sua escolha. Isso pode ser obtido por meio da propriedade release_name_prefix:

Workflow de criação de release

create_release:
name: Create release
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-release-template.yml@v1
permissions:
contents: write
with:
release_name_prefix: "Github"

Workflow de criação de pre release

create_release_candidate:
name: Create release candidate
uses: davidsonbrsilva/versioning-workflow/.github/workflows/create-pre-release-template.yml@v1
permissions:
contents: write
with:
release_name_prefix: "Github"

Neste exemplo, as releases criadas seguirão o padrão “Github 1.0.0”.

Esse é o repositório do projeto. Ficou interessado? Deixe seu feedback. Se tiver qualquer dúvida, é só me chamar. Se tiver vontade de contribuir com algo, não hesite em falar comigo.

--

--

Davidson Bruno

Software Analyst and Developer. Interested in Artificial Intelligence, Compilers and Web Development.