Desenvolvimento

9 fev, 2017

Entrega contínua com Git (hotfix por padrão)

Publicidade

Recentemente, tem havido uma mudança na maneira como organizamos o código e fazemos lançamentos em um de nossos projetos web do Ruby on Rails. Anteriormente, quando estávamos introduzindo novo recurso principal, estávamos usando bastante o padrão git-flow.

Como usamos git-flow?

Ao usar git flow, geralmente trabalhamos em branches de recursos (por exemplo, /1234-super-cool-stuff) e os iniciamos com base no branch master. Depois que o trabalho na ramificação de recurso dado estiver concluído, ele é mesclado novamente no master. Isso ativa a criação automática em nosso servidor CI. Sempre que o servidor CI comunica uma compilação verde no master, ele automaticamente implementa o código em nosso servidor staging. A história é então testada no staging e aceita/rejeitada. Todo o processo reitera até que todas as histórias da característica épica atual sejam testadas e aceitas.

Neste ponto, estamos prontos para lançar para produção. Isso é feito mesclando o branch master com o branch production e disparando a implantação automática para servidor de produção. Isso acontece nos bastidores, pois usamos git flow release.

O que há de errado com git-flow?

O git-flow funciona muito bem se estivermos desenvolvendo um recurso principal de cada vez. Normalmente, no entanto, estamos desenvolvendo alguns recursos principais simultaneamente. Os recursos são implantados para teste independentemente um do outro, mas, quando queremos liberar para produção, temos que esperar pelo momento em que todos os recursos estejam concluídos, implantados e testados em nosso servidor staging (e branch master).

O cliente não queria isso e queria ver prontos para usar recursos no servidor de produção assim que os tivéssemos prontos. Esse foi um problema que tentamos corrigir.

Começamos a manter um monte de opções / toogles de recursos. Novos recursos seriam desativados no início, para que pudéssemos implementar a produção sem esperar pela conclusão deles. Isso provou ser bastante difícil na vida real e acabamos fazendo um monte de trabalho de manutenção. Os recursos normalmente têm dependências que precisam ser ativadas/desativadas para que o sistema funcione corretamente. Nós também acabamos tendo duas versões de código escolhidas dinamicamente em tempo de execução. Isso significa mais if-clauses e também uma grande base de código desnecessário. Depois de algum tempo, tivemos de fazer limpezas regulares do código de produção de opções / toogles de recursos utilizados anteriormente. Esse processo era bastante propenso a erros também.

Novo modelo de ramificação git

Alguns meses atrás, trouxemos uma nova maneira de organizar e implementar o nosso código Ruby. Nessa fase da vida do projeto, temos de fazer hotfixes muito frequentemente de qualquer maneira e, por isso, decidimos desenvolver a aplicação, principalmente através de hotfixes. Quer se trate de uma correção de bugs ou de um novo recurso, trabalhamos nisso iniciando um branch baseado no branch production. Para testá-lo, nós o mesclamos com master e implantamos no servidor de teste. Se ele passar na verificação de qualidade lá, podemos fundir esse branch de volta para production. O código, então, é liberado para o servidor de produção, sem se preocupar com outros recursos ainda não finalizados.

Recursos maiores, que consistem em um monte de histórias relacionadas, são mantidos em branches de hotfix de longa duração. Nós os combinamos algumas vezes em master antes de eles irem para production. No estado inacabado, no entanto, eles podem ser mesclados somente no master.

O hotfix por fluxo padrão nos permite implantar novos recursos para a produção várias vezes ao dia. Isso também resulta em um feedback mais rápido dos usuários de produção, que chegam a usar novos recursos em uma base diária. Percebemos que, quando fazemos um grande lançamento, bugs são ignorados com mais frequência também. Um recurso menor, implantado na produção, leva menos tempo para verificar manualmente os bugs do que um grande lançamento de recursos não relacionados.

Uma questão em que nós tropeçamos, ao testar essa aproximação, eram commits indesejados em pull requests no GitHub. Isso acontece porque os branches são mesclados separadamente para master e production. Esses dois branches serão diferentes em commits de mesclagem que, em seguida, podem desordenar pedido de tração se compararmos um branch com base na production com o master. A solução para isso é mesclar regularmente a production com master.

Resumo

Depois de quatro meses, podemos dizer que existem algumas vantagens nessa abordagem. Primeiro de tudo, pequenos pedaços de código são implantados para a produção de cada vez. Isso torna os lançamentos menos intimidantes. Além disso, lançamentos frequentes nos permitem obter feedback dos usuários finais mais rápido, para que possamos responder a eles melhor e mais rápido.

Como todas as regras, ocasionalmente decidimos quebrar o nosso novo fluxo git também. Isso acontece, se tivermos uma pilha de recursos relacionados, que realmente precisam ser implantados para produção ao mesmo tempo. Nesses casos, fazemos um sprint ou dois sprints onde voltamos ao git-flow normal.

***

Marcin Nieborak faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://www.amberbit.com/blog/2017/1/30/continous-delivery-with-git/.