Integração contínua, flexibilidade e limpeza de histórico eficiente: conheça o Z-Flow e avance na produtividade com seu time de desenvolvimento!
Por Thauany Moedano – Cloud Architect e Back-End Software Developer da Zappts
O assunto de hoje aqui no blog é Git Workflow e eu vou te apresentar um pouco da solução Z-Flow, desenvolvida pela Zappts. Vamos nessa?
Bom, quando falamos sobre o trabalho em equipe de um time de desenvolvimento, não podemos deixar de citar o uso de uma ferramenta de versionamento.
O nosso amigo git é provavelmente um dos primeiros sistemas de versionamento de código que todo desenvolvedor tem contato quando começa a trabalhar em time, e apesar do git ser poderosíssimo e muito útil, muito ainda se discute a respeito de como utilizá-lo.
Portanto, se você tem essa dúvida, continue lendo este artigo que eu vou compartilhar com você algumas informações importantes sobre o assunto!
Git Workflow
Qual é a melhor forma de trabalhar com git? Como organizo as branches?
Desses questionamentos surgiram os workflows e é a partir deles que podemos encontrar as respostas que tanto procuramos.
Um workflow é um framework para a organização de branches.
O workflow dita como devem ser organizadas e nomeadas as branches e quais movimentações devem ser feitas até a entrega do produto final.
Existem diversos modelos conhecidos e você provavelmente já deve ter esbarrado em algum deles.
Mas, com tantos frameworks já disponíveis e conhecidos, por que criar um novo workflow?
Primeiro, é importante destacar que os modelos mais antigos não levam em consideração nosso cenário atual de integração e entrega contínua (aquelas palavras famosas: CI/CD).
E os modelos mais novos, como o “Github Flow” ou o “Feature Branch Workflow?“
De fato, eles realmente são ótimos para CI/CD (inclusive nos baseamos em alguns conceitos básicos do Github Flow). Porém, eles apresentam uma branch master e homolog (ou release em alguns projetos) muito poluídas, e às vezes, com dezenas ou centenas de milhares de commits, o que impossibilita qualquer expert de entender qual foi a sequência de entregas realizadas.
Essa enormidade de commits passam a não servir para nada (a não ser para confundir), além de tornar muito complexo o processo de rollback (para quem nunca passou por isso, nem queira saber como é ter que fazer git revert e revert de revert para conseguir colocar as coisas em ordem novamente).
Aqui na Zappts já nos deparamos muito com essa situação em projetos próprios e também de clientes. Por isso, pensamos em uma nova forma de organizar a forma de como entregar funcionalidade para produção.
Z-Flow – A solução Zappts de Git Workflow
Vamos lá: tudo o que fazemos quando trabalhamos em desenvolvimento de software está focado em entregas com qualidade, certo?
Com base nessa premissa, nós criamos um modelo de workflow que deixasse nossa branch de desenvolvimento com todos os commits feitos pelos desenvolvedores (eles são importantes ali), e nossa branch de produção com o histórico de entregas e não de commits de desenvolvimento, permitindo também a administração de deploys por entregas específicas e não de um todo.
Assim surgiu o Z-Flow!
O que preciso saber para extrair o máximo deste artigo?
Para que esteja na mesma página que nós e acompanhe as dores que passamos antes de decidirmos pensar no Z-Flow, seria importante que você conhecesse de:
- Git: que já tenha trabalhado em algum projeto que usa git como sistema de versionamento de código. Se já passou pelas dores de gerenciar um git com muitos desenvolvedores, projeto grande, código que “sumiu do nada” da sua branch, melhor ainda.
- GitFlow: parte da premissa que todas as feature branches partem de Dev. Ou seja, Dev precisa estar estável com todas as features que serão publicadas para homologação e posteriormente produção.
- GithubFlow: parte da premissa que todas as feature branches partem de Master e que todas as feature branches podem ser mergeadas em master separadamente. Normalmente, em projetos maiores, existem branches intermediárias (todas provenientes da master), que recebem individualmente a feature branch.
- Delivery Contínuo (CI/CD): usando os commits das branches como source para executar uma pipeline de publicação automática. Quando um commit é submetido (pushed) para uma branch, automaticamente um script é executado, que publica esse novo código para um determinado ambiente.
Atenção: se você trabalha com desenvolvimento de softwares, venha fazer parte do nosso time! Confira as vagas e mande seu currículo hoje mesmo! 😀
Apresentando o Z-Flow
Como dito anteriormente, se você implementar o Z-Flow no seu projeto, terá uma branch de produção MUITO limpa, constando apenas o histórico de entregas e seguindo a cronologia de entrega de cada feature, além de uma branch de desenvolvimento que tenha todos os históricos de commits feitos por todos desenvolvedores.
Branches principais
O Z-Flow possui quatro branches principais:
- master
- develop
- qa
- homolog
A master é a branch de produção e sempre representa uma versão estável do nosso software.
Quanto à develop, é nessa branch que as novas features vão se acumulando e o time de desenvolvimento têm visão de quais features já foram implementadas por outros desenvolvedores.
Por conta da branch de develop ser atualizada recorrentemente, é a branch mais suscetível a instabilidades.
Agora, vamos apresentar duas novas branches que talvez você ainda não conheça: a qa e a homolog.
A branch de qa é dedicada ao time de qualidade. É nela que os testes por parte do time de qualidade são executados.
A branch de qa é mais estável que a branch de develop, uma vez que os desenvolvedores devem garantir a estabilidade da sua feature antes de repassá-la para a fase de testes.
p.s: a branch qa é recomendada, mas não é obrigatória para que o Z-Flow funcione da forma como idealizamos. Se você tem um time ou projeto pequeno, talvez essa branch possa ser dispensada.
E por último, temos a branch de homolog, onde estão todas as features testadas pelo time de QA, mas que ainda precisam ser homologadas pelo time de negócio. Essa é a branch que entrega features para produção.
Importante: em alguns casos específicos de projetos, é necessário incluir a branch Pré-Prod após homolog. Esse caso será tratado mais à frente.
Z-Flow – Transitando entre branches
Para que o desenvolvimento aconteça de maneira paralela e eficiente, usamos as branches secundárias. São elas:
- feature branch
- delivery branch
Lembrando que para cada feature desenvolvida teremos uma feature branch e uma delivery branch.
Para todas as transições entre branches, sejam elas principais ou secundárias, recomendamos que sejam seguidas as boas práticas de git, pelo menos usando ferramentas que suportam merge por Pull Request e designando usuários independentes para fazer code review a cada Pull Request.
Feature Branch
- Deriva de: master
- Recebe o conteúdo: dos comitts feitos pelos desenvolvedores da feature
- Entrega seu conteúdo em: develop (–no–ff), qa (–no–ff)
- Convenção: feature/*
A feature branch é onde o desenvolvedor vai incorporar as novas funcionalidades do sistema.
Ela sempre deriva de master para garantir que estamos trabalhando em cima de uma versão estável de produção.
Todas as implementações da feature devem ser feitas na feature branch, nunca diretamente na develop ou em alguma outra branch.
Uma vez que o desenvolvimento é finalizado, a feature deve ser entregue (mergeada) no modo no-fast-forward em develop para que o desenvolvedor possa fazer testes integrados a outras funcionalidades incorporadas pelos outros times.
Após fazer todas as implementações e alterações na feature branch e garantir a estabilidade da feature em develop, o desenvolvedor pode mergear a feature branch como modo no-fast-forward na branch qa para iniciar a fase de testes. Portanto, o nosso fluxo fica assim:
- git checkout master
- git pull origin master
- git checkout -b feature/minha-feature
- **após implementar alterações (git commits):
- git checkout develop
- git pull origin develop
- git merge –no-ff feature/minha-feature
- git push origin develop
- **quando a feature estiver pronta para fase de testes:
- git checkout qa
- git pull origin qa
- git merge –no-ff feature/minha-feature
- git push origin qa
Delivery branch
- Deriva de: master
- Recebe o conteúdo: da feature branch (–squash)
- Entrega seu conteúdo em: homolog (–no-ff)
- Convenção: delivery/*
Com o intuito de limpar o histórico de commits, a delivery branch serve para diminuir o histórico de commits de uma feature branch pronta para entrega.
Entenda a delivery branch como sendo exatamente a feature branch, com o mínimo de commits possíveis, os commits referentes a cada “entrega” da feature.
Para chegarmos a esse objetivo, a delivery branch recebe a merge squash da sua feature branch equivalente após a aprovação da feature em QA.
Assim, a delivery branch fica com o mesmo conteúdo da feature branch (master + nova funcionalidade), mas apenas com um commit (o resultante do merge squash).
Segue o nosso fluxo:
- git checkout master
- git pull origin master
- git checkout -b delivery/minha-feature
- git merge –squash feature/minha-feature
- git commit -m “delivery da feature minha-feature”
Homolog Branch
- Deriva de: master
- Recebe o conteúdo: da delivery branch (–no-ff)
- Entrega seu conteúdo em: master (–no-ff)
A branch de homolog receberá todas as features que estão testadas e prontas para serem homologadas.
Para entregar o conteúdo de cada feature pronta a ser homologada para homolog, a delivery branch (referente à cada feature) será mergeada em homolog.
O merge aqui acontece no modo “no-ff” para que se crie um histórico de entrega da feature para homologação. Então, atenção: é a delivery branch que deve ser entregue para homologação.
p.s: a branch homolog fica apenas com os commits referentes a cada entrega de feature feita para homologação. Ao usar o Z-Flow, você tem na branch homolog um histórico limpo de todas as entregas de features para homologação!
- git checkout homolog
- git pull origin homolog
- git merge –no-ff delivery/minha-feature
- git push origin homolog
Master Branch
- Recebe o conteúdo: da homolog (–no-ff)
- Entrega seu conteúdo: para criação de novas feature branches e delivery branches
E quando as features são entregues na master?
Consideramos, para este flow, uma entrega para produção como sendo exatamente o que está homologado.
Dessa forma, quando chega o momento certo, a branch master precisa ser uma “cópia” da branch homolog.
Quando um conjunto de features está homologado , basta dar merge no modo “no-ff” de homolog para master para atualizá-la, tornando master uma nova versão estável.
- git checkout master
- git pull origin master
- git merge –no-ff homolog
- git push origin master
Assim, podemos taggear a última versão estável cada vez que entregamos um conjunto de features.
p.s. 1: quando se fizer necessário ter uma branch “pré-prod”, siga os passos descritos aqui como ‘master’. Após pré-prod estar validado, siga novamente esses passos trocando “homolog” por “pré-prod”.
p.s 2: a branch master fica apenas com os commits referentes a cada entrega de feature feita para homologação. Ao usar o Z-Flow, você tem na branch master um histórico limpo de todas as entregas de features para homologação em conjunto de um histórico com todas as entregas feitas para produção.
Por que precisamos de uma delivery branch?
Mas, por que precisamos criar uma branch a mais se poderíamos simplesmente dar merge squash da feature diretamente em homolog?
Realmente, isso pode ser feito deixando o flow bem mais simples. Então, qual a razão da existência da delivery branch?
Nós da Zappts prezamos muito pelo code review e sempre é importante alguém aprovar o nosso código antes de submetermos para uma das branches principais.
Usando o merge squash, por conta da maneira que as ferramentas de code review usam git diff, fica bem difícil entender as diferenças entre um commit e outro.
Logo, o intuito de criar uma branch intermediária, somente para criar um merge squash (um commit único) da feature branch, é para não atrapalhar o code review entre as outras branches.
O processo fica um pouco mais trabalhoso, de fato, mas o esforço compensa: por um pequeno custo (5 comandos de git), se consegue um retorno enorme (imensurável em alguns projetos) de se ter uma branch homolog e master limpas, com poucos commits cronologicamente organizados na forma de entregas.
Nós pagaríamos o dobro (ou mais) por esse resultado 🙂
Lidando com erros
Como tratar no Z-Flow quando nossa feature está com erros?
A regra é simples: erros encontrados localmente (feature) ou nas branches develop e qa são consertados na feature branch e entregues novamente em develop e qa.
Se o erro foi pego na branch homolog deve ser consertado na feature branch, replicado (squashed) para a delivery branch e entregue novamente em homolog.
Entende-se que a delivery branch vai ficar com alguns commits a mais (a primeira entrega e a segunda entrega com o erro corrigido). É exatamente o que se busca: um histórico limpo de entregas.
E quando encontramos um erro que já está em produção? Nesse caso, criamos uma branch específica para tratar o erro, chamada de hotfix.
Hotfix Branch
- Deriva de: master
- Entrega o conteúdo em: delivery/hotfix (–squash)
- Convenção: hotfix/*
A branch de hotfix deve seguir o mesmo fluxo já apresentado na feature branch, mudando apenas a convenção de nomes. Nesse caso:
- git checkout master
- git pull origin master
- git checkout -b hotfix/meu-hotfix
- após implementar alterações (git commits):
- git checkout develop
- git pull origin develop
- git merge –no-ff hotfix/meu-hotfix
- git push origin develop
- **após garantir estabilidade do hotfix:
- git checkout qa
- git pull origin qa
- git merge –no-ff hotfix/meu-hotfix
- git push origin qa
E da mesma forma que para uma feature branch existe uma delivery branch, para o hotfix também existe uma delivery hotfix branch.
Delivery Hotfix Branch
- Deriva de: master
- Recebe o conteúdo: da hotfix (–squash)
- Entrega o conteúdo em: homolog (–no-ff)
- Convenção: delivery/hotfix/*
E o fluxo também segue o mesmo de uma delivery branch, apenas alterando a convenção de nomes:
- git checkout master
- git pull origin master
- git checkout -b delivery/hotfix/meu-hotfix
- git merge –squash hotfix/meu-hotfix
- git commit -m “delivery do hotfix meu-hotfix”
- git push origin delivery/hotfix/meu-hotfix
Vale ressaltar que devido à urgência que o hotfix pode apresentar, é possível pular passos no Z-Flow e entregar diretamente um hotfix em qa ou criar diretamente uma delivery branch para entrega em homolog/master.
Integração Contínua e Deploy Contínuo
O Z-Flow garante integração contínua uma vez que as branches são incorporadas juntas em todas as branches principais.
Com o Z-Flow sempre se está testando features integradas umas às outras. Ao passar pela branch de qa, o Z-Flow garante que uma nova feature não quebra as demais já entregues em produção na branch master.
Há casos que é necessário entregar features prontamente ou antes de um conjunto de funcionalidades. Nestes, alguns passos do Z-Flow podem ser pulados e a delivery branch pode ser mergeada diretamente na master, uma vez que a delivery branch já deriva da master.
Isso garante que todas as delivery branches sempre contenham: master (ambiente de produção estável) + feature (nova funcionalidade).
Logo, o Z-Flow é um modelo flexível que permite tanto a entrega de um conjunto de features já integrados ou a divisão da entregas em pacotes separados.
Branch de produção mais estável
Como a feature branch deve passar pelas branches de develop e qa (e é intensamente testada), dificilmente a branch de produção ficará instável.
Isso ocorre porque somente features que já contém master testadas e prontas são entregues em produção.
Ou seja, o cenário de master + nova implementação já é simulado e testado desde develop e qa.
Histórico mais limpo
Como a delivery delivery sempre é um squash de uma feature branch e ela é entregue em homolog e master, o Z-Flow garante que em branches finais o histórico de commits será muito mais limpo, considerando assim um histórico de entregas e não um histórico de desenvolvimento.
Utilizando as delivery branches, fica fácil entender a cronologia de entregas, uma vez que cada delivery branch geralmente é composta de dois commits (um commit da implementação e um commit do merge).
E já que você chegou até aqui com a gente, deve estar interessado em saber como o Z-Flow funciona na realidade, certo? Então, vamos lá!
Acompanhe na imagem abaixo um exemplo de como o histórico fica mais limpo e claro sobre as entregas nas branches homolog e master e como o histórico fica completo com todos os commits de desenvolvimento nas branches develop e qa, cumprindo os objetivos principais do Z-Flow.
Tem duas formas de analisar esta imagem:
1. Com foco nas branches: faça a análise apenas das branches, de cima para baixo, esquecendo as branches ao lado. Veja como fica o histórico de commits de uma única branch. Entenda o que aconteceu com a branch, evolutivamente. Lembre-se de olhar com uma visão de desenvolvedor para as branches de develop e qa e com a visão de negócio para as branches de homolog e master.
2. Com foco no fluxo: acompanhe o fluxo de merges. Quando o merge é do tipo no-ff, ele arrasta o histórico de commits da branch origem. Quando o merge é do tipo squash, ele resume todos os commits da branch em um único commit.
Conclusão
O Z-Flow é uma alternativa aos modelos de workflow. Ele traz flexibilidade e garante CI/CD ao mesmo tempo que limpa o histórico de commits, além de manter uma branch de produção estável.
E aí, pronto para colocar o Z-Flow no seu catálogo de workflows? Pronto para usar o Z-Flow no seu projeto ?
Se a sua empresa precisa de ajuda para estruturar processos de desenvolvimento, conte com a gente! Vamos acelerar seus resultados com soluções produtivas, como o Z-Flow. Fale agora mesmo com nossos especialistas 😀
E se você é desenvolvedor(a), olha só: que tal vir trabalhar na Zappts?
Aqui, você vai encontrar o MELHOR ambiente para desenvolver suas habilidades, expor ideias e aprender muita coisa legal.
Construímos um espaço incrível de trabalho e diversão, que respeita a diversidade e que dá condições para que todos possam deixar suas marca em nossa história!
Vem conferir as vagas, trabalhar e aprender com a gente 👉 https://zappts.com/trabalhe-conosco/
Até o próximo artigo 👋