Git Flow customizado no Github Actions

Neste artigo você vai ver:

Cada empresa, equipe e/ou indivíduo atuando na área de desenvolvimento de software tem uma visão do que é o Git Flow ideal no GitHub Actions. Basicamente, Git Flow é um fluxo de trabalho utilizado por equipes de desenvolvimento de software para auxiliar na organização do versionamento de códigos.

Publicado em 2010, pelo engenheiro de software holandês, Vincent Driessen, o objetivo do Git Flow é melhorar as organizações das branches (ramificações) dentro de repositórios e, dessa forma, dar mais fluidez ao processo de desenvolvimento de novas funcionalidades, correções de bugs e lançamentos de versões.

De uma certa forma, esse conceito de Git Flow ideal “depende” tanto do contexto no qual nosso software está sendo desenvolvido, quanto das diversas etapas definidas no ciclo de vida de um software no nosso ambiente de trabalho.

Git Flow

Quando usamos o conceito de Git Flow, seguimos geralmente um dos três tipos de mapeamento de branches:

1 Feature Branch

Uma Feature branch é o tipo de ramificação mais comum usado no Git Flow. Ele é usado ao adicionar novos recursos ao seu código.

Ao trabalhar em um novo recurso, você iniciará uma Feature Branch fora de sua ramificação de desenvolvimento (develop), em seguida, fará o merge das suas alterações de volta na ramificação de desenvolvimento quando o recurso for concluído e devidamente revisado.

2 Release Branch

Uma Release Branch é usada na preparação de novos lançamentos de produção. Normalmente, o trabalho que executado em Release Branch diz respeito a retoques finais e pequenos bugs específicos para liberação de um novo código, que deve ser tratado separadamente da ramificação principal do desenvolvimento.

3 Hotfix Branch

No Git Flow, uma Hotfix Branch é útil para implementar rapidamente as alterações necessárias em sua ramificação principal.

A base da Hotfix Branch deve sempre ser a sua ramificação principal, depois é feito o merge de volta na ramificação principal e de desenvolvimento. Fazer o merge das alterações de sua Hotfix Branch de volta à ramificação de desenvolvimento é fundamental para garantir que a correção persista na próxima vez que a ramificação principal for lançada.

Imagem personalizada sobre um modelo de ramificação Git bem-sucedido, a explicação do esquema está nos parágrafos anteriores.
Imagem personalizada inspirada por Vincent Driessen em “Um modelo de ramificação Git bem-sucedido”. (Fonte)

Release Candidate

Quando falamos do ciclo de vida ou de lançamento de um software, uma Release candidate (“versão do software candidata a lançamento”), ou simplesmente RC, refere-se a uma versão com potencial para ser o produto final, pronta para ser lançada, a menos que algum defeito (bug) sério apareça e perceba-se em tempo. 

Nesse estágio de estabilização do software, todas as funcionalidades encontram-se especificadas, implementadas e testadas através de uma ou mais fases (SANDBOX, homologação, pré-produção, alpha, etc.) sem a ocorrência de defeitos sérios.

Contexto

Vamos para o nosso contexto de trabalho. Hoje, atuo num produto composto de vários times de engenharia, com oito squads de desenvolvimento, e um time de design / produto.

Tentamos usar Versão semântica, mas enfrentamos alguns desafios devido a mudanças frequentes.

Combinamos então que nosso projeto deveria usar um sistema de versionamento simples para definir e congelar um conjunto de alterações desenhadas pelo time de Design, para que as equipes de Produto e Engenharia possam trabalhar evitando ruídos relacionados a “alterar as alterações” enquanto as equipes ainda estavam trabalhando (temos fluxo de exceções para casos críticos).

O modelo final para o versionamento de nossas entregas ficou assim:

<A>.<B>.<C>.<D>

Onde:

  • A e B são as versões principais e secundárias do Design;
  • C e D são as versões principais e secundárias do Produto/Engenharia.

Seguindo assim, e levando em consideração que trabalhamos com três ambientes (sandbox, qa e production), nosso Git Flow de Engenharia customizado ficou assim:

Cenário 1: Feature Branch

  • No início de cada sprint: criar uma branch release-w.x.y.z a partir da branch main
  • Criar uma branch feature/*** a partir da release-w.x.y.z
  • Abrir Pull Request da branch feature/*** para a release-w.x.y.z
    • Quando fizer o merge dessa PR, subir as atualizações no ambiente de SANDBOX.
  • Validou a funcionalidade em SANDBOX: Abrir PR da release-w.x.y.z para qa
    • Quando fizer o merge dessa PR, subir as atualizações no ambiente de QA.
  • Validou a funcionalidade em QA: Abrir release-w.x.y.z para main
    • Quando fizer o merge dessa PR, gerar uma Release Tag w.x.y.z automaticamente e  subir as atualizações no ambiente de PRODUCTION.

Cenário 2: Hotfix Branch

  • Durante a sprint: Criar a branch hotfix/*** a partir da main
  • Abrir Pull Request para a main
  • Gerar Release Tag manualmente
  • Abrir PR da main para a branch release-w.x.y.z (release candidate em desenvolvimento) para atualização.

Github Actions

Agora que entendemos como nosso Git Flow funciona, precisamos implementá-lo nas nossas pipelines de CI/CD, no Github Actions.

Precisaremos de 4 workflows:

  • deploy em SANDBOX;
  • deploy em QA;
  • deploy em PROD;
  • criação de release / tag.

Workflow Deploy SANDBOX

O primeiro workflow é relativamente simples, ele trigga para cada push feito numa branch começando com o prefixo “release-“.

Com uma regra de concorrência (conforme nosso artigo sobre boas práticas usando Github Action) para garantir que o último evento push sempre prevaleça sobre os demais.

Workflow Deploy QA

O segundo workflow é semelhante ao primeiro, no entanto, ele trigga para cada push feito na branch qa“. Ou seja, ele teria iniciado quando o merge de uma PR da nossa Release Branch para a ramificação de QA fosse feito. 

Workflow Deploy PROD

O terceiro workflow de deploy para nosso ambiente produtivo é um pouco diferente, pois ele inicia apenas quando uma release tag tem sua publicação no nosso repositório GitHub. Implementamos o workflow dessa forma para que ele inicie via criação de release tag MANUAL ou AUTOMÁTICA (conforme os dois cenários detalhados na seção anterior).

Workflow Create Release

Finalmente, o nosso quarto e último workflow é aquele que faz a ligação automática entre o ambiente de QA e PROD ao fazer o merge de uma PR na nossa ramificação principal, a branch main.

Para isso, o workflow inicia a cada PR fechado, mas só cria a release tag respeitando algumas condições. Sendo elas:

  • a Pull Request sair de uma branch contendo “release-“;
  • a Pull Request atualizar a branch main;
  • a Pull Request fechada ter sido aprovada;
  • a realização do merge da Pull Request.

Essas condições são verificadas em uma expressão no IF do job TAG:

if: contains(github.head_ref, 'release-') && contains(github.base_ref, 'main') && github.event.action == 'closed' && github.event.pull_request.merged == true

A partir do momento que essa condição é respeitada, o primeiro job TAG extrai como output a versão da nossa ramificação “release-w.x.y.z” (que seria neste caso W.X.Y.Z) através de um código em Bash:

BRANCH=${{ github.head_ref }}
TAG="${BRANCH//release-/""}"
echo $TAG
echo "tag=$TAG" >> $GITHUB_OUTPUT

Esse output é depois usado num segundo job RELEASE, para criar a tag e publicar uma release usando a versão como nome:

  release:
    needs:
      - TAG
    runs-on: ubuntu-latest
    env:
      TAG: ${{ needs.TAG.outputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Push tag
        uses: mathieudutour/github-tag-action@v6.1
        with:
          custom_tag: ${{ env.TAG }}
          github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}

      - name: Create release
        uses: softprops/action-gh-release@v1
        with:
          name: ${{ env.TAG }}
          tag_name: ${{ env.TAG }}
          token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}

É possível observar aqui que é preciso cadastrar um PERSONAL ACCESS TOKEN como secrets no nosso repositório. 

Isso é mandatório, pois esse workflow de criação de release precisa iniciar nosso workflow de deploy em PROD e isso não pode ser feito sem autenticação, pois o GITHUB_TOKEN (variável base gerada automaticamente em todos os workflows) não tem permissão para isso (a fim de evitar eventuais loops infinitos de trigger entre workflows).

Conclusão

Por hoje é isso! Espero que este artigo tenha deixado mais claro como converter seu Git Flow ao GitHub Actions.

Fiz uma pequena POC num repositório pessoal, caso queira fazer um fork:

Quem quiser se aprofundar no Github Actions para testar o que foi explicado aqui e muito mais, é só criar seu repositório com seus workflows e experimentar, pois o plano FREE da plataforma permite testar seus fluxos de trabalhos em repositórios públicos sem limites de tempo.

Última dica: a documentação do Github Actions em português é muito boa e vale a pena a leitura.

Curtiu o conteúdo? Comente abaixo! Além disso, continue acompanhando nossas publicações no blog, YouTube, redes sociais, Spotify e newsletter para ficar por dentro das novidades de tecnologia.

Referências

Imagem capa do conteúdo sobre "git flow" onde um homem branco segura um ipad, saindo dele um Diagrama de fluxograma de desenvolvimento de software mostrando ramificação, mesclagem, pull request
foto Guillaume Falourd
Back-end Developer
Zupper tentando transformar o complexo em simples através de conteúdos diversificados, com intuito de impactar o mercado de TI e as pessoas ao seu redor da melhor forma possível.

Artigos relacionados

Este site utiliza cookies para proporcionar uma experiência de navegação melhor. Consulte nossa Política de Privacidade.