5.6 Pipeline de Integração Contínua com GitLab CI/CD

Finalmente chegamos no ponto de criarmos nosso primeiro script que irá possibilitar a realização da chamada Integração Contínua.

De maneira geral, a grande maioria das ferramentas possuem um processo semelhante ao do GitLab CI/CD. Algumas, como o Jenkins, oferecem uma interface gráfica para a configuração do pipeline de Integração Contínua, outras, como o GitLab CI/CD, permitem a definição desse pipeline por meio de um arquivo especial, localizado no diretório do projeto.

No caso do GitLab CI/CD o pipeline é definido dentro de um arquivo denominado .gitlab-ci.yml , que segue o formato do YAML, que nada mais é do que uma linguagem de marcação. Este arquivo define a ordem em que se dará a execução do pipeline.

Uma explicação detalhada da estrutura e organização do arquivo .gitlab-ci.yml pode ser encontrada em: https://docs.gitlab.com/ee/ci/yaml/. Abaixo apresentamos os conceitos essenciais para a compreensão do pipeline que desejamos para a construção da nossa aplicação de forma automática e posterior entrega da mesma no ambiente de produção.

Jobs

Um arquivo .gitlab-ci.yml é formado, basicamente, por um conjunto de jobs, na terminologia do GitLab CI/CD. Jobs são os elementos mais básicos dentro do arquivo .gitlab-ci.yml.

Conforme a documentação oficial, jobs são:

  • Definido com restrições informando em que condições devem ser executados;

  • Elementos de nível superior com um nome arbitrário e que devem conter pelo menos a cláusula script.

  • Ilimitados dentro de um arquivo .gitlab-ci.yml.

job1:
  script: "execute-script-for-job1"

job2:
  script: "execute-script-for-job2"

O exemplo acima ilustra uma simples configuração de CI/CD com dois jobs distintos. Cada um executa um comando diferente, especificado nas cláusulas script. Um comando pode executar código diretamente (./configure;make;make install) ou executar um script (test.sh) no repositório.

Os jobs são executados por runners (executores) em um ambiente exclusivo dentro do executor. Além disso, vale ressaltar que os jobs executam de forma independente uns dos outros.

Embora cada job deva ter um nome, existem algumas palavras chaves reservadas e, portanto, não é possível atribuir algum desses nomes para um job. São elas:

  • image

  • services

  • stages

  • types

  • before_script

  • after_script

  • variables

  • cache

  • include

Além disso, um job é definido internamente por uma lista de palavras chaves. Cada uma define um comportamento diferente dentro do job. A seguir são apresentadas algumas delas, as que serão necessárias para compreender o que será apresentado a seguir. Para uma explicação detalhada e conhecimento das demais cláusulas permitidas dentro de um job recomenda-se a leitura da documentação oficial em https://docs.gitlab.com/ee/ci/yaml/.

Lista de algumas palavras chaves (keywords) que definem comportamentos no job:

Keyword

Descrição

Determina o comando ou script que será executado pelo runner.

Permite a execução de um conjunto de comandos após a execução do job ser finalizada.

Lista de arquivos ou diretórios anexados ao job quando sua execução finaliza com sucesso. Tais artefatos ficam disponíveis para download na plataforma. Veja também: artifacts:paths, artifacts:exclude, artifacts:expose_as, artifacts:name, artifacts:untracked, artifacts:when, artifacts:expire_in, e artifacts:reports.

Permite a execução de um conjunto de comandos antes da execução do job.

Lista de arquivos que devem ser mantidos em cache entre execuções subsequentes. Veja também: cache:paths, cache:key, cache:untracked, cache:when, e cache:policy.

Uso de imagens Docker. Veja também: image:name e image:entrypoint.

Limita quando os jobs podem ser criados: only:refs, only:kubernetes, only:variables, e only:changes.

Uso de serviços de imagens Docker. Veja também: services:name, services:alias, services:entrypoint, e services:command.

Define o stage (estágio) de um job (padrão: test).

Define variáveis no nível do job.

Primeiro job no projeto exemplo

Para exemplificar os conceitos acima vamos dar início à definição do pipeline DevOps no projeto exemplo da Loja Virtual. O primeiro passo para isso é criarmos o arquivo .gitlab-ci.yml dentro do GitLab conforme sequência de telas a seguir. Basicamente, estando no repositório do projeto loja-virtual-devops, basta clicar no sinal de "+" e escolher a opção de Novo Arquivo.

Em seguida, basta atribuir um nome (1), digitar o conteúdo do arquivo (2) e confirmar as alterações (3). Trata-se de um arquivo com um único job, denominado maven-package. Esse script de Integração Contínua faz uso da imagem mcr.microsoft.com/java/maven:8-zulu-debian9, para construir nossa aplicação exemplo da loja virtual, conforme ilustrado na Seção 5.3. Por padrão, as imagens são baixadas do Hub Docker mas é possível alterar essa configuração se desejado. Para mais informações sobre como alterar o repositório de contêineres consulte https://docs.gitlab.com/ee/user/packages/container_registry/. Em nosso caso, faremos uso do Hub Docker padrão para a busca e registro de imagens.

Dentro dessa imagem existe uma instalação do Maven e, portanto, o comando mvn clear package, dentro da cláusula script do job, será executado pelo runner sem problemas. O último detalhe é que esse job foi associado ao stage deploy. Se fosse omitida essa cláusula, ele estaria associado, por padrão, ao stage test, conforme documentado acima. Falaremos mais sobre stages a seguir.

image: mcr.microsoft.com/java/maven:8-zulu-debian9

maven-package:
  stage: deploy
  script:
    - mvn clean package

Observe que assim que confirmar as alterações, o GitLab detecta que criamos um arquivo de integração contínua e dá início a execução do mesmo, conforme ilustrado na figura abaixo por meio do círculo azul semi completo.

Ao clicar sobre esse círculo destacado na figura acima é possível consultar o andamento das atividades em execução no pipeline. No exemplo abaixo é possível ver que o job maven-package, associado ao stage Deploy, está em execução. Nessa tela, no canto superior, é possível também verificar que é possível cancelar ou apagar a execução desse pipeline.

Um clique sobre o nome do job permite visualizar o status de sua execução e acompanhar o passo a passo do script que está executando, no caso, o mvn clean package.

Ao terminar da execução, o job encerrando com sucesso, define que o pipeline aprovou último commit realizado. Se houver falha na execução do script, o job é reprovado e, consequentemente, o pipeline acusa uma falha.

Detalhando o Pipeline de Integração Contínua

Como observamos acima, criamos um pipeline de CI com apenas um job que, ao final, em caso de sucesso, gera o arquivo lojavirtualdevops.war. Entretanto, em geral, o processo de construção de uma aplicação passa por diferentes estágios, até que a mesma seja finalmente empacotada para a distribuição.

O próprio construtor da aplicação que utilizamos, o Maven, possui vários objetivos que são executados um a um até que o arquivo .war final seja produzido. Desse modo, é possível então detalhar o pipeline CI para que possamos observar mais detalhadamente o que acontece em cada um desses estágios da construção da aplicação.

O GitLab permite que isso seja feito por meio da definição de estágios (stages) dentro de nosso arquivo de configuração.

Mas o que são os stages?

stages são usados para definir etapas que contém jobs associados. Os stages são definidos de forma global para o pipeline.

Com a especificação de stages passamos a ter pipelines multiestágios, e não de estágio único como no exemplo anterior no qual tínhamos apenas o estágio Deploy. A ordem dos elementos dentro de stages define a ordem em que os jobs serão executados:

  1. Jobs dentro do mesmo stage são executados em paralelo;

  2. Jobs do próximo stage só iniciam sua execução após todos os jobs de um stage anterior finalizarem com sucesso.

Desse modo, vamos considerar a alteração abaixo em nosso arquivo de configuração do pipeline:

image: mcr.microsoft.com/java/maven:8-zulu-debian9

stages:
  - build
  - test
  - package

maven-build:
  stage: build
  script: 
    - mvn clean compile test-compile

maven-test:
  stage: test
  script: 
    - mvn test

maven-package:
  stage: package
  script: 
    - mvn package

Na linha 3 fazemos uso de stages e definimos três estágios: build, test, e package. Cada um deles está diretamente relacionado a um job que executa uma tarefa do Maven.

O comportamento definido para a execução de cada job passa a ser o seguinte:

  1. Primeiro, todos os jobs de build são executados em paralelo;

  2. Se todos os jobs de build finalizarem com sucesso, os jobs de test iniciam a execução em paralelo.

  3. Se todos os jobs de test finalizarem com sucesso, os jobs de package iniciam a execução em paralelo.

  4. Se todos os jobs de package finalizarem com sucesso, o commit é marcado como passed; e

  5. Se algum dos jobs anteriores falhar, o commit é marcado como failed e nenhum job subsequente é executado.

Há ainda duas particularidades com stages:

  1. Se não há uma definição global de stages no arquivo .gitlab-ci.yml, então, os estágios build, test e deploy podem ser utilizados nos jobs por padrão;

  2. Se um job não especificar a qual stage, ele é associado ao estágio test por padrão.

Para verificar se a alteração acima funciona corretamente, basta editarmos nosso arquivo .gitlab-ci.yml e, ao confirmar essa mudança, o pipeline entra em execução, conforme ilustrado a seguir.

Ao clicar sobre o círculo azul, é possível acompanhar a execução de cada job, associado a cada estágio do pipeline. Se desejar ter informações detalhadas sobre a saída produzida pelos scripts em execução em cada job, basta clicar sobre o nome do respectivo job e são exibidos detalhes do processo encerrado ou em andamento.

No exemplo acima, todos os estágios finalizaram com sucesso de modo que o pipeline foi aprovado.

Dessa forma, de maneira geral, pode-se dizer que o processo para a criação de pipelines com o GitLab CI/CD não é uma tarefa muito complicada mas exige que se conheça a documentação de como escrever corretamente o arquivo de configuração do pipeline.

Existem muitas outras opções que podem ser utilizadas e exploraremos mais algumas delas no capítulo a seguir, mas recomendo fortemente que, aqueles interessados em fazer uso profissional da tecnologia, leiam atentamente toda a documentação da mesma para compreender suas capacidades e limitações.

Last updated