Melhores práticas de CI/CD

Integração, entrega e implantação contínuas são práticas de desenvolvimento de software que nasceram do movimento DevOps. Elas tornam o processo de criação, teste e lançamento de código mais eficiente e colocam o produto funcional nas mãos dos usuários mais rapidamente do que os métodos tradicionais. Se bem feito, um pipeline de compilação permite que as equipes entreguem software funcional no ritmo e obtenham feedback oportuno sobre suas últimas alterações.

A construção de um pipeline de CI/CD não deve ser um exercício do tipo "disparar e esquecer". Assim como o software que está em desenvolvimento, vale a pena adotar uma abordagem iterativa para suas práticas de CI/CD: continue analisando os dados e ouvindo o feedback para refinar seu processo de CI/CD. Neste artigo, exploraremos as melhores práticas de integração contínua/entrega contínua que você deve considerar aplicar ao seu pipeline.

Faça commit cedo e com frequência

Garantir que todo o seu código-fonte, arquivos de configuração, scripts, bibliotecas e executáveis estejam no sistema de controle de versões é uma primeira etapa fundamental para implementar a integração contínua, e vai permitir que você possa manter um controle de todas as alterações.

A ferramenta sozinha, no entanto, não é suficiente: é a maneira como você a usa que conta. A integração contínua busca tornar o processo de integração de alterações realizadas por vários contribuidores mais fácil ao compartilhar atualizações menores com mais frequência.

Cada commit dispara um conjunto de testes automatizados para fornecer feedback imediato sobre a alteração. Realizar commits com regularidade vai garantir que sua equipe esteja sempre trabalhando sobre as mesmas fundações, facilitando a colaboração e reduzindo a probabilidade de conflitos dolorosos durante o merge, ao integrar mudanças grandes e complexas.

Para colher os benefícios da integração contínua, é fundamental que todos compartilhem suas alterações com o resto de sua equipe fazendo push para o branch principal (master) e atualizando sua cópia de trabalho para que ela receba as alterações de todos os outros. Como regra geral, tente fazer commit para o branch principal (master) pelo menos uma vez ao dia.

Fazer push das alterações para o branch principal com frequência pode ser incômodo para equipes acostumadas a trabalhar com branches de longa duração. Isto pode ser devido ao medo de uma análise crítica por outras pessoas ou talvez porque o tamanho de uma tarefa seja grande demais para ser concluída num único dia.

Criar uma cultura de colaboração em equipe, em vez de uma cultura de julgamento, é fundamental e, como acontece com qualquer mudança nas práticas de trabalho, vale a pena discutir como você trabalha em equipe. Trabalhar como uma equipe para dividir as tarefas em pedaços menores e discretos pode ajudar os participantes na adoção dessa prática.

Quando branches de longa duração são usados para hospedar novos recursos que não estão prontos para lançamento, uma opção alternativa é usar feature flags. Isso permite que você controle a visibilidade de uma funcionalidade específica em diferentes configurações, de modo que as alterações de código possam ser mescladas e incluídas na compilação para garantia de qualidade sem estarem disponíveis para os usuários finais.

Mantenha os builds sempre verdes

Ao construir a solução e executar um conjunto de testes automatizados cada vez que se faz commit de uma alteração, um pipeline de CI/CD fornece feedback rápido aos desenvolvedores sobre suas alterações.

O objetivo é evitar construir sobre bases ruins e manter o código num estado que possa ser lançado a qualquer momento. Além de ser muito mais eficiente resolver os problemas assim que eles surgem, isto também permite que uma correção seja implementada e colocada em execução rapidamente, se algo der errado no sistema em produção.

Se um build falhar por qualquer motivo, a prioridade da equipe deve ser fazer com que volte a funcionar. Pode ser tentador culpar a pessoa que fez a última alteração e deixar a tarefa de consertar o problema para ela. No entanto, quando o foco da sua equipe é encontrar um culpado, ela dificilmente produzirá uma cultura de equipe construtiva e terá mais dificuldades em descobrir a causa subjacente de um problema. Ao fazer com que a equipe inteira seja responsável por lidar com uma compilação com falha e tentar entender o que levou à falha, você pode melhorar todo o workflow de CI/CD. É claro que isto é mais fácil de falar que fazer quando a equipe está sob pressão e as tensões estão elevadas; desenvolver uma cultura DevOps também é um exercício de melhoria contínua!

Claro, pode ser frustrante ter que descartar tudo para consertar um build com falha, apenas para descobrir que o problema foi causado por algo trivial, como um erro de sintaxe ou uma dependência perdida. Para evitar coisas assim, é bom que os membros da equipe façam um build e rodem um conjunto inicial de testes localmente antes de compartilharem suas alterações. O ideal é que todos possam usar os mesmos scripts do sistema CI/CD, evitando assim a duplicação de esforços. Além disso, considere implementar ferramenta de CI/CD na sua organização.

Use um único build de cada vez

Um erro comum é criar um novo build para cada etapa.

A reconstrução do código para diferentes ambientes corre o risco de introduzir inconsistências e significa que você não pode ter certeza de que todos os testes anteriores foram aprovados. Em vez disso, o mesmo artefato de compilação deve ser promovido em cada estágio do pipeline de compilação e, finalmente, lançado para uso.

Colocar isso em prática exige que a construção seja independente do sistema. Quaisquer variáveis, parâmetros de autenticação, arquivos de configuração ou scripts devem ser chamados pelo script de implantação, em vez de serem incorporados ao próprio build. Isso permite que a mesma compilação seja implantada em cada configuração para teste, com cada estágio aumentando a confiança da equipe nesse artefato de compilação específico.

Embora seja uma boa prática manter tudo, incluindo o script de build, arquivos de configuração e scripts de implantação no mesmo sistema de controle de versões que o código da aplicação, isto não se aplica ao próprio artefato de build. Por ser um produto derivado dessas entradas, o build não deve ser mantido no sistema de controle de versões. Em vez disso, deve ser versionado e armazenado em um repositório de artefatos central, como o Nexus, do qual pode ser retirado e implantado em cada instância.

Otimize seus testes

Embora a CI/CD dependa muito de testes automatizados para fornecer confiança na qualidade do seu software, isto não significa que você deva testar todas as eventualidades.

Afinal, o objetivo da integração contínua é fornecer feedback rápido e fornecer produtos valiosos aos usuários em um ritmo mais rápido do que os métodos tradicionais. Isto significa que há um equilíbrio a ser alcançado entre a cobertura de testes e o desempenho. Se demorar demais para obter os resultados do teste, as pessoas irão buscar motivos e maneiras de contornar o processo.

Execute os testes que terminam mais rapidamente primeiro para obter feedback o quanto antes e só invista em testes mais longos quando tiver algum grau de confiança no build. Considerando o tempo envolvido na garantia manual de qualidade e a dependência de sua equipe estar disponível para realizar essas verificações, é melhor limitar essa fase até que todos os testes automatizados sejam concluídos com êxito.

A primeira camada de testes automatizados consiste geralmente de testes unitários, que você pode usar para garantir ampla cobertura e para ser alertado sobre quaisquer problemas óbvios introduzidos pela última alteração. Depois dos testes de unidade, você poderá ter uma camada de integração automatizada ou testes de componentes, que irão testar as interações entre diferentes partes do seu código.

Além desses, você talvez invista em testes automatizados mais complexos, tais como testes de GUI, testes de desempenho e carga ou testes de segurança, antes de finalmente dedicar um tempo para testes manuais exploratórios e/ou de aceitação. Para deixar mais eficientes esses testes de execução mais longos, sejam eles automáticos ou manuais, foque nas áreas que representam o maior risco para o seu produto específico e usuários.

Limpe seus ambientes

Para aproveitar ao máximo seu pacote de controle de qualidade, vale a pena reservar um tempo para limpar seus ambientes de pré-produção entre cada implantação.

Quando os ambientes são mantidos em execução por muito tempo, torna-se mais difícil acompanhar todas as mudanças na configuração e atualizações que foram aplicadas a cada um.

Com o tempo, as configurações divergem da configuração original e umas das outras, o que significa que testes aprovados ou reprovados em uma podem não retornar o mesmo resultado em outra. A manutenção de ambientes estáticos também acarreta um custo de manutenção, o que pode retardar o processo de controle de qualidade e atrasar o processo de lançamento.

O uso de contêineres para hospedar ambientes e executar testes facilita a criação e destruição de ambientes para cada nova implantação, usando uma abordagem de infraestrutura como código para fazer o script dessas etapas. Instanciar um novo contêiner a cada execução garante consistência e permite dimensionar ambientes com mais facilidade, para que você possa testar vários builds em paralelo, se necessário.

Faça com que seja a única maneira de implantar o serviço em produção

Depois de investir na construção de um pipeline de CI/CD confiável, rápido e seguro que lhe dá confiança na qualidade dos seus builds, você não quer por a perder todo esse esforço permitindo que alguém contorne esse processo por qualquer motivo.

Normalmente, a solicitações para contornar o processo de lançamentos são feitas quando a alteração é pequena ou urgente (ou ambas), mas ceder a tais demandas é uma falsa economia.

Ao ignorar os estágios da garantia de qualidade automatizada, corre-se o risco de introduzir problemas evitáveis, enquanto a reprodução e a depuração problemas são muito mais difíceis, pois a compilação não está prontamente disponível para implantação em uma instância de teste.

É provável que, em algum momento, você seja solicitado a pular o processo, "só desta vez". Quando acontecer, você provavelmente estará no modo de apagar incêndios, mas vale a pena usar uma retrospectiva ou post-mortem para entender a motivação por trás do problema. Será que o processo está sendo percebido como excessivamente lento? Talvez existam melhorias ou refinamentos de desempenho que possam ser feitos. Há algum mal-entendido sobre quando ele deve ser usado? Comunicar os benefícios de um pipeline de CI/CD pode ajudar a envolver as partes interessadas no processo e evitar esse tipo de demanda na próxima vez que a casa estiver caindo.

Monitore e meça sua pipeline

Como parte da configuração do seu pipeline de CI/CD, você provavelmente implementou o monitoramento para o seu ambiente de produção, com a finalidade de alertá-lo sobre eventuais problemas o quanto antes.

Assim como o produto que você está lançando, seu processo de criação também se beneficiará de um ciclo de feedback.

Ao analisar as métricas coletadas por sua ferramenta de CI/CD, você poderá identificar possíveis problemas e áreas que podem ser melhoradas.

  • Comparar o número de builds disparados por semana, dia ou hora fornece um insight útil sobre como sua infraestrutura de pipeline é usada, se você precisa aumentá-la ou diminuí-la e quando o pico de carga tende a ocorrer.
  • Acompanhar a velocidade das implantações ao longo do tempo e monitorar para saber se elas tendem a demorar mais, pode indicar quando é hora de investir em otimizações de desempenho.
  • As estatísticas de testes automatizados podem ajudar a determinar as áreas que poderiam se beneficiar de uma paralelização.
  • Analisar os resultados do controle de qualidade para encontrar aqueles que são rotineiramente ignorados pode identificar o potencial para simplificar sua cobertura de garantia de qualidade.

Faça com que seja um esforço de equipe

A criação de um workflow de CI/CD eficaz tem tanto a ver com a cultura organizacional e de equipe quanto com os processos e ferramentas que você utiliza.

Integração, entrega e implantação contínuas são práticas DevOps. Eles contam com a eliminação dos silos tradicionais entre desenvolvedores, engenheiros de controle de qualidade e operações e incentivam a colaboração interdiciplinar.

A eliminação de silos dá às equipes mais visibilidade do workflow de ponta a ponta e a oportunidade de colaborar e se beneficiar de diferentes áreas de especialização. Manter o pipeline nunca deve ser tarefa de uma única pessoa. A implementação de uma plataforma de CI/CD também pode ajudar a melhorar suas práticas operacionais.

Ao criar um senso de responsabilidade compartilhada para a entrega do seu software, você estimula todos os membros da equipe a contribuir, seja pondo as mãos na massa para consertar o build, reservando um tempo para instalar ambientes em contêineres ou automatizando uma tarefa manual que não é realizada com a frequência que deveria.

A promoção de uma cultura de confiança, onde os membros da equipe são capazes de experimentar e compartilhar ideias, beneficia não apenas as pessoas, mas também a empresa como um todo e o software que você distribui. Se algo der errado, em vez de apontar um culpado entre os membros de sua equipe, o objetivo deve ser aprender com o erro; compreender a causa subjacente e como ela poderia ser evitada no futuro.

Aproveite a oportunidade para melhorar sua prática de CI/CD e torná-la mais robusta e eficaz. Ao permitir que os membros da equipe experimentem e inovem sem medo de recriminações, você criará um círculo virtuoso de melhoria contínua.