Downstream Pipeline: Simplificando a Integração Contínua entre Projetos ou Subprojetos com GitLab CI/CD
Já imaginou simplificar ainda mais a integração contínua entre projetos e subprojetos em seu ecossistema? Nesse artigo vamos explorar as Downstream Pipelines e seus cenários de uso para simplificar fluxos de trabalho complexos com GitLab CI/CD.
Para reproduzir os cenários abordados neste artigo, você só precisará de uma conta gratuita no GitLab. No entanto, é importante destacar que todas as funcionalidades que exploraremos também estão disponíveis no GitLab Community Edition (CE).
Downstram Pipeline
De uma maneira simples, uma pipeline downstream é aquela que é desencadeada por outra pipeline de CI/CD no GitLab. Essas pipelines downstream são executadas de forma autônoma e paralela à pipeline upstream, ou seja, a pipeline que as originou.
GitLab Trigger
O GitLab Trigger foi inicialmente implementado na versão 8.2, permitindo a execução remota de pipelines por meio de solicitações HTTP. No entanto, ao longo do tempo, essa funcionalidade evoluiu e foi substituída por WebHooks e Triggers genéricos de CI acionados por pipelines.
Assim, embora o GitLab Trigger tenha estado presente em versões antigas do GitLab, a partir da versão 13.4, muitas das funcionalidades que exploraremos neste artigo já estavam disponíveis. Para a elaboração deste artigo, utilizei minha própria conta gratuita no GitLab.com na versão mais recente 16.5.
Multi-project Pipeline
Os projetos com Multi-project Pipeline, são projetos onde são acionadas downstream pipelines de outros projetos, ou seja, um repositório aciona uma ou várias pipelines de outros repositórios.
Vamos criar um cenário hipotético que envolve dois projetos: o Projeto A, uma API RESTful, e o Projeto B, um projeto de automação de testes integrados para o Projeto A. A pipeline do Projeto A segue um fluxo de desenvolvimento padrão, com um de seus passos dedicado à execução de testes, incluindo testes unitários e testes integrados. No entanto, o projeto de automação de testes integrados está em outro repositório com um fluxo de trabalho separado.
Neste contexto, encontramos um caso ideal para a implementação de uma Multi-Project Pipeline, onde a partir da pipeline do Projeto A, podemos acionar o Projeto B por meio de um gatilho (Trigger Project) para executar os testes de automação integrados. O diagrama abaixo ilustra esse processo:
GitLab CI
Para acionar a integração entre os projetos, iremos utilizar a chave ‘trigger’ no job chamado ‘integrated_test’. Este job terá uma dependência com o job ‘deploy_dev’, configurando-se da seguinte maneira:
Na chave trigger:project, é importante referenciarmos o path completo até o projeto que será engatilhado. Outro campo importante é trigger:strategy, onde iremos utilizar o valor ‘depend’, que neste caso aguardará a finalização do downstream pipeline para concluir o job.
Iremos abstrair o restante dos jobs e simplificar o fluxo de trabalho desse projeto hipotético, sendo possível realizar o ‘deploy’ no ambiente de desenvolvimento a partir de qualquer pipeline de forma manual.
Pipeline
Para ilustrar esse cenário, vamos analisar uma pipeline em um Merge Request no Projeto A.
Nesse contexto, é necessário primeiramente realizarmos o deploy no ambiente de desenvolvimento do projeto e em seguida será realizado o gatilho automático ao Projeto B para executar a automação de testes integrados.
Realizado o deploy e a execução do gatilho de testes integrados, podemos observar que nossa pipeline expandiu, agora também exibindo o gatilho para o Projeto B. Ao clicarmos no job de gatilho, somos encaminhados para a Pipeline respectiva no Projeto B.
Por fim, simplificando e deixando de forma transparente o fluxo de trabalho entre projetos. Além disso, é alterada a forma de exibição no Merge Request, indicando o gatilho para outro projeto da seguinte forma:
Projetos
Confira os projetos A e B, com a configuração de CI/CD completa!
Parent-child Pipeline
Os projetos com Parent-child Pipeline, são projetos onde são acionadas downstream pipelines de projetos filhos, ou seja, um repositório aciona uma ou várias pipelines no mesmo repositório.
Vamos criar um novo cenário hipotético que envolve um projeto Front-End White-Label, ou seja, um projeto base de várias marcas, sendo ele o Projeto A, cujas respectivas marcas B e C. A pipeline do Projeto A possui etapas globais para o projeto, mas já os projetos filhos das Marcas B e C possuem variáveis e ambientes totalmente isolados entre si apesar de reutilizarem o mesmo código fonte.
Neste contexto, encontramos um caso ideal para a implementação de uma Parent-Child Pipeline, onde a partir da pipeline do Projeto A, podemos acionar o CI dos projetos filhos das Marcas B e C por meio de um gatilho (Trigger Include) para executar suas etapas de build e deploy com suas respectivas variáveis de ambiente de forma totalmente isolada e independente. O diagrama abaixo ilustra esse processo:
GitLab CI
Para acionar a integração entre os projetos filhos de cada marca, iremos utilizar a chave ‘trigger’ nos respectivos jobs ‘brand_b’ e ‘brand_c’. Estes jobs realizarão o ‘include’ dos respectivos CI com suas sobrescritas de variáveis de ambiente, build e deploy de maneira isolada, configurando-se da seguinte maneira:
Na chave trigger:project, é importante referenciarmos o path completo até o CI do subprojeto que será engatilhado com suas respectivas customizações. Outro campo importante é trigger:strategy, onde iremos utilizar o valor ‘depend’, que neste caso aguardará a finalização do downstream pipeline para concluir o job.
Iremos abstrair o restante dos jobs e simplificar o fluxo de trabalho desse projeto hipotético, sendo possível realizar o ‘deploy’ no ambiente de desenvolvimento a partir de qualquer pipeline de forma manual.
Pipelines
Para ilustrar esse cenário, vamos analisar uma pipeline em um Merge Request no Projeto A.
Nesse contexto, podemos observar as etapas globais do fluxo de trabalho e as respectivas pipelines de cada marca do projeto, onde podemos expandi-las para observarmos suas customizações.
De maneira automática é realizada a etapa de ‘build’ do projeto, ficando disponíveis para execução manual o ‘deploy_dev’ e ‘rollback_dev’ nas respectivas Marcas B e C. Podemos observar também que cada ‘trigger’ das marcas gera um Pipeline totalmente isolada.
Por fim, simplificando e deixando de forma transparente o fluxo de trabalho entre marcas. Além disso, é alterada a forma de exibição no Merge Request, indicando o gatilho para outro projeto da seguinte forma:
Projetos
Confira o Projeto A e suas respectivas Marcas B e C, com a configuração de CI/CD completa!
Conclusão
Tanto o Multi-project Pipeline, quanto Parent-child Pipeline são soluções que resolvem problemas complexos entre relações de projetos de maneira simples, isolada e customizável.
Os cenários que trouxe aqui são apenas um aperitivo das diversas situações e contextos que podemos aplicar ambas soluções, inclusive combinando elas, dessa forma abrindo um mar de possibilidades e casos de uso.
Temos que ter como objetivo final elaborar um fluxo de trabalho com integração continua, de maneira isolada e escalável, mas que no fim consiga ser uma solução simples para projetos complexos! E que claro, faça sentido para seu time 🚀
Obrigado pela sua atenção! E até breve 😄