Close

Entrega contínua superpotente com o Git

Agora que o Git resolveu o problema de merge, os fluxos de trabalho de branches ficaram muito mais atraentes.

Foto de rosto de Sarah Goff-Dupont
Sarah Goff-Dupont

Escritora principal


Todos já ouvimos o dizer “cuidado com um código escrito por apenas uma pessoa” e sabemos os benefícios de criar software em equipe: há diferentes maneiras de pensar, diferentes conhecimentos e experiências... e quando essas diferenças ajudam na resolução dos problemas, o resultado é um software melhor. O software fica mais sustentável, com mais qualidade e acaba atendendo melhor às necessidades do usuário.

Colaboração em equipe | Atlassian CI/CD

Mas também sabemos que desenvolver em equipe pode ser confuso!

Você está tentando entender em quais partes do código cada um está trabalhando, tentando garantir que as alterações não entrem em conflito, tentando encontrar defeitos antes dos clientes e tentando manter todos que estão conectados ao projeto atualizados sobre o andamento das coisas. Como se vê, cada um desses problemas é solucionado pelos branches do Git ou pela entrega contínua.

Espero convencê-lo de que, combinando os dois (talvez colocando algumas ferramentas incríveis na mistura só de brincadeira), você vai ter uma receita de sucesso superpoderosa.

O poder dos fluxos de trabalho baseados em ramificações


Na verdade, não é que o Git por si só seja tão perfeito para entrega contínua. É que os fluxos de trabalho de branches são ótimos para implementação contínua e o Git é ótimo para os fluxos de trabalho de branches. Além de ser o maior aliado da implementação contínua, um fluxo de trabalho de branch e merge permite solucionar bugs complexos, experimentar novas tecnologias ou apenas começar a codificar um novo recurso do zero sem o risco de que as alterações impeçam o avanço das tarefas dos colegas de equipe.

Diagrama de fluxo de trabalho básico | Atlassian CI/CD

O Subversion e outros sistemas tradicionais de controle de versão também permitem usar branches. Mas vamos fazer uma pausa e conhecer o gêmeo malvado das branches: o merge.

Os sistemas tradicionais de controle de versão como o Subversion não são tão bons em acompanhar versões de arquivos que residem em diferentes branches. Quando chega a hora do merge, o Subversion tem que parar e pedir um monte de instruções. (Sabe aquele pequeno pop-up perguntando “Você quer essa linha ou aquela na versão do merge?”) O grande volume de interação humana necessária durante os merges leva as equipes a estabelecer congelamentos de código, para que quem estiver realizando o merge não seja interrompido pelas novas alterações chegando em uma daos ramificações. E os congelamentos de código são caros: são períodos bastante improdutivos.

O Git, por outro lado, é muito bom em acompanhar as alterações em diferentes versões de arquivos que residem em branches diferentes e sempre sabe como era o ancestral comum do arquivo. Ele tem um GPS integrado que permite navegar nos merges sem ter que parar e pedir instruções o tempo todo.

Com o Git, você está livre para explorar o poder dos branches de uma forma que seria impraticável com o Subversion. A sobrecarga envolvida nos branches e merges é tão trivial que os branches que duram apenas um dia ou dois não são só viáveis, mas também benéficos.

Ok, tudo bem. Mas, afinal, por que os branches são tão poderosos para entrega contínua?

As ramificações mantêm o branch principal limpo e pronto para ser lançado

Estabelecemos que as ramificações de curta duração são uma ótima maneira para os desenvolvedores colaborarem em um projeto ou recurso sem atrapalhar o trabalho dos outros. Mas o mais importante para a implementação contínua é que isolar todo o trabalho em andamento nos branches de desenvolvimento mantém o branch principal e todas as ramificações das versões estáveis em condições limpas para que você possa lançar à vontade.

Ou seja, é necessário fazer a bateria completa de testes automatizados nos branches de desenvolvimento para que os desenvolvedores tenham certeza sobre a qualidade do código e possam tomar decisões confiantes sobre quando as alterações estão prontas para o merge. (Se você ainda não está fazendo os testes automatizados, consulte este post da RebelLabs com uma conversa divertida e receitas para escrever os primeiros testes de unidade.)

Também significa usar solicitações pull do Git como uma forma de análise de código para que toda a equipe fique confiante sobre a manutenção e a interoperabilidade do código com outras áreas da base de código. Sim, este é um trabalho mais direto do que os modelos de entrega tradicionais exigem. E sim, vale a pena.

Ver solução

Crie e opere softwares com o Open DevOps

Material relacionado

O que é o pipeline de DevOps?

O sucesso da entrega contínua significa manter os branches da versão limpos

Como exemplo, todas as equipes de desenvolvimento da Atlassian têm um acordo de que nenhum commit é feito direto no branch principal nem nas ramificações estáveis. Todos trabalham em ramificações. Na verdade, a gente gosta tanto das ramificações que acabou criando uma separada para cada item abordado do Jira.

Ou seja, é possível fazer quantos testes quiser e causar a maior bagunça nas ramificações! O branch principal continua sempre em um estado em que possa ser lançado e em que você pode criar outras ramificações sem herdar um monte de códigos errados. Essa é uma vitória para a CD e a produtividade geral do desenvolvedor (sem falar na motivação que ela traz).

Os branches ajudam a aceitar as contribuições de fora da equipe

A facilidade de usar branches do Git, ainda mais na bifurcação de repositórios inteiros, facilita o recebimento de contribuições de pessoas fora da equipe imediata: prestadores de serviço, desenvolvedores de empresas parceiras, desenvolvedores de outras unidades de negócios etc. Você não precisa perder o sono se preocupando com pessoas não familiarizadas com a base de código fazendo alterações em branches críticos e prejudicando a capacidade de lançar um novo código.

Aqui, mais uma vez, os testes automatizados rigorosos nas ramificações ou repositórios bifurcados são a chave para o sucesso da colaboração. É interessante analisar os resultados de build e de teste antes de aprovar qualquer merge na linha de código da ramificação principal.

Dica profissional: gerenciadores de repositórios como o Bitbucket permitem que você use hooks do Git para impor padrões de qualidade. Por exemplo, você pode estabelecer uma regra em que todos os builds do branch precisam ser aprovados para que uma solicitação pull seja aceita e submetida ao merge.

Branches bem feitos = clareza no acompanhamento do projeto


Tendência do momento: criar um branch de desenvolvimento para cada história, correção de bug ou tarefa (ou seja, cada item do Jira) que você implementa. Adotamos esse modelo de branch por item na Atlassian há alguns anos e não nos arrependemos! Ele também se popularizou entre os clientes da Atlassian.

A criação de uma ramificação para cada item facilita a escolha manual de quais alterações são lançadas para produção ou agrupadas em uma versão. Como você não está acumulando alterações no branch principal, você pode escolher o que entra no branch principal — e quando. Você pode lançar um MVP excelente e outro bom, em vez de esperar até que todos os bons estejam prontos. Ou pode lançar uma só correção de bug dentro da estrutura de uma versão regular. Mesmo que a correção seja urgente, você não vai precisar dar conta de suspender outras alterações que ainda não estejam prontas para serem lançadas só para poder lançar essa alteração específica.

E essa facilidade de lançar uma só alteração de código é a essência da entrega contínua.

Com essa abordagem, além de manter o código não comprovado fora do branch principal, quando você inclui a chave do item do Jira relevante e o nome ou as iniciais do desenvolvedor no nome da ramificação, fica muito claro qual é o estado de desenvolvimento de cada item em andamento.

O Bitbucket faz commit da captura de tela do repositório do Git | Atlassian CI/CD

Observe a convenção de nomenclatura usada na figura acima: é a chave exclusiva do item do JIRA que está sendo implementado, além de uma pequena descrição legível sobre o contexto do item. Então, como gerente de versão ou outra parte interessada, você pode olhar para o repositório mostrado acima e saber com rapidez que a história do usuário acompanhada por AMKT-13952 está pronta para ser lançada porque o merge na ramificação principal já ocorreu. Essa é uma ótima capacidade de acompanhamento sem todo aquele esforço manual.

Como funciona o Git somado ao fluxo de trabalho de entrega contínua?


Que bom que você perguntou! Vou falar um pouco disso em linhas gerais, já que outros artigos neste site se aprofundam mais em cada fase.

  • Crie um branch para o item no qual você vai trabalhar. Inclua a chave do item do Jira no nome do branch para que a finalidade do branch fique clara. E se você estiver usando outras ferramentas da Atlassian, como o Bitbucket e Bitbucket pipelines, elas vão usar essa chave do item para criar links entre o item, o branch, todos os commits, os builds, as solicitações pull e as implementações relacionadas àquele item. Em outras palavras, as chaves de item são mágicas.
  • Faça as alterações no branch. Você está sozinho no próprio mundo aqui, então faça o quiser. Experimente coisas novas. Destrua coisas. Não importa, porque você também vai seguir este próximo passo:
  • Coloque o branch na integração contínua. Cabe a você e à equipe decidir se querem executar testes especializados, como testes de carga ou testes baseados em IU de ponta a ponta aqui e se querem fazer o acionamento automático de uma execução de teste sempre que as alterações são enviadas ao branch. Em geral, as equipes da Atlassian realizam testes de nível de integração e de unidade nos branches de desenvolvimento.
  • Atualize o branch com as alterações mais recentes do branch principal com frequência. Para fazer a atualização, você pode usar a opção rebase ou o commit da ramificação. Só depende de você! (Mas não faça rebase em uma ramificação compartilhada com outros desenvolvedores, eles não vão ficar felizes.) De qualquer forma, você vai descobrir conflitos de integração antes de fazer o merge, o que também ajuda a manter o branch principal limpo.
  • Crie uma solicitação pull quando estiver pronto para fazer o merge. A implementação foi concluída, você enviou pull das alterações dos colegas de equipe, resolveu todos os conflitos resultantes e todos os testes no branch foram aprovados.
  • Faça merge e implemente à vontade. Algumas equipes preferem fazer o lançamento automático de cada alteração logo após o merge no branch principal e todos os testes são aprovados nele, ou seja, o modelo de implementação contínua. Outras equipes preferem decidir elas mesmas quais alterações vão ser lançadas e quando. A escolha é sua e da equipe.
Automação da integração contínua do Git | Atlassian CI/CD

Conclusão…


Então é isso. Os fluxos de trabalho de branch simplificam a entrega contínua e o Git elimina a dificuldade dos branches. Continue lendo para se aprofundar e saber como configurar o repositório do Git para ficar compatível com a implementação contínua e como colocar todas essas ideias em prática usando as ferramentas da Atlassian. Vejo você na próxima página!

Sarah Goff-Dupont
Sarah Goff-Dupont

Sarah é uma engenheira de controle de qualidade que virou escritora cujo trabalho foi apresentado na Harvard Business Review, Inc., Huffington Post, bem como em publicações do setor. Ela trabalha de casa em Minnesota e ama cada minuto. Quando ela não está escrevendo, você pode encontrá-la lendo, fazendo snowboard, cozinhando e/ou trocando trocadilhos cringe com os filhos.

Entre em contato com Sarah no LinkedIn


Compartilhe este artigo

Leitura recomendada

Marque esses recursos para aprender sobre os tipos de equipes de DevOps ou para obter atualizações contínuas sobre DevOps na Atlassian.

Ilustração DevOps

Comunidade de DevOps

Ilustração DevOps

Leia o blog

Ilustração do mapa

Comece gratuitamente

Inscreva-se para receber a newsletter de DevOps

Thank you for signing up