Introdução

Com o frequente crescimento do mercado de TI, tornou-se indispensável ser ágil ao produzir software. Porém, mais do que ágil, é preciso ser eficiente. Visando a eficiência e diminuindo os intervalos entre as versões, testes e publicações, surge no mercado um conceito que integra as equipes de negócio, desenvolvimento e infraestrutura: DevOps (Developer Operations).

Este termo surgiu no início dos anos 90, com o nascimento das metodologias ágeis, que propunham uma nova abordagem para desenvolvimento de software. DevOps se propõe a diminuir o gargalo entre a equipe de desenvolvimento (Developers) e a equipe de infraestrutura (Operations).

Dentro deste contexto, temos uma parte que é vital ao processo de DevOps: a “entrega contínua (Continuous Integration) (HUMBLE; FARLEY, 2014)”. Esta metodologia busca quebrar a barreira entre desenvolvedores, testadores, analistas de negócio e infraestrutura, criando uma cultura de cooperação.

Conceitos

Dentro do assunto proposto, existem 3 variações sobre o assunto: Continuous Integrations (CI), Continuous Deployment (CD) e Continuous Delivery (CDE).

Continuous Integration é o processo pelo qual fazemos o trabalho de automação dos desenvolvedores, pegando os vários commit’s feitos pelos desenvolvedores, ao longo do dia, e automatizando o merge dos mesmos e executando testes automatizados e verificações de qualidade.

Continuous Delivery é a automação das builds, tal qual o Continuous Integration, porém a decisão de publicação é humana, ou seja, alguém decide quando publicar a aplicação.

Continuous Deployment, por sua vez, é o processo de automatização da publicação destes artefatos/serviços, uma vez que a versão está devidamente testada, analisada, está pronta para ser publicada.

No gráfico abaixo, podemos ver até onde cada uma das etapas abrange.


Fig 1 – As camadas de integration, delivery e deployment. Fonte: Atlasian – 2019

Vale a pena citar aqui: é importante não confundir CI/CD com DevOps (Developer Operations). Com toda a certeza, o CI/CD faz parte da cultura DevOps, mas não representa o todo, e sim uma parte dessa cultura que envolve toda a equipe de projeto, desde o suporte até o gerente de TI.

GitLab e GitLab CI

O GitLab é um gerenciador de repositórios baseado em Git. Suas ferramentas incluem um wiki, um gerenciador de tarefas e um pipeline de CI/CD, sendo este último o foco deste artigo. O GitLab é similar ao GitHub, porém, por ser open source, pode ser armazenado em infraestrutura própria, além da versão em nuvem do mesmo, podendo ter repositórios públicos e privados.

Iniciando um projeto

Para este artigo, criei um repositório em https://gitlab.com/orlandoburli/hello-gitlab-ci, que será o projeto que usaremos para testar as builds e deploys.

O projeto é simples: uma aplicação spring boot, com uma url que recebe como parâmetro um nome, e retorna uma string com “Hello, nome!”

Fig. 2 – Código fonte da aplicação

Com o projeto pronto, agora vamos falar sobre o arquivo de configuração do CI gitlab, o .gitlab-ci.yml.

Importante: Para explicar um pouco, este arquivo é um arquivo com o formato YAML, que conta com uma formatação específica. Então, tenha atenção com ele. Ao fazer os espaçamentos, nunca use TAB, apenas espaços.

Para que seja acionada a build do GitLab CI, é necessário que este arquivo esteja na raiz do projeto, como mostrado abaixo:

Fig. 4 – Arquivo de configuração do gitlab ci

Configuração da pipeline

Agora, faremos a codificação desta build. A primeira coisa que precisa ser definida é a imagem da build. No nosso caso, definiremos como java 1.8, como mostrado abaixo:

image: java:8

O segundo passo é definirmos os stages, ou passos do nosso pipeline. Iremos definir os passos de test e build, inicialmente (lembre-se de atentar-se aos espaços, 3 espaços para montar a hierarquia de comandos):

stages:
   - test
   - build

Também colocaremos um passo anterior a estes stages, para isso, usando o comando before_script:

before_script:
  - chmod +x mvnw

O objetivo deste passo é preparar as permissões do arquivo mvnw, que é um shell script do maven para executar a build do seu projeto. Se você iniciar o seu projeto pelo starter do spring, por exemplo, já irá criar estes arquivos.

Vamos agora aos comandos da nossa pipeline, efetivamente. Primeiramente, vamos definir o comando de test:

test:
  state: test
  script: ./mvnw test

Aqui, os comandos são bem simples. Primeiro, defino o nome do comando como test. Em seguida, defino o seu estágio de execução como test, e seu script como ./mvnw test, para executar o comando do maven para testes. Caso o teste falhe, a build também falhará neste passo.

Agora, vamos definir o comando build:

build:
  stage: build
  script: ./mvnw package
  artifacts:
    paths:
      - target/hello-0.0.1-SNAPSHOT.jar

Primeiramente, definimos o nome do comando como build. Definimos o stage como build (mais para a frente no artigo isso fará mais sentido), no seu script colocamos o comando ./mvnw package para gerar o jar via maven.

Por último, definimos os artifacts, que são os artefatos gerados por esta build e que devem ser armazenados. Esta feature do gitlab permite que você armazene, junto ao seu repositório, os artefatos, ou versões geradas pelo seu pipeline.

Nosso arquivo completo ficou assim:

image: java:8

stages:
   - test
   - build

before_script:
  - chmod +x mvnw

test:
  state: test
  script: ./mvnw test

build:
  stage: build
  script: ./mvnw package
  artifacts:
    paths:
      - target/hello-0.0.1-SNAPSHOT.jar

executando a pipeline

Feito isso, estamos prontos para testar nossa pipeline. Para testar, vou subir meu commit no gitlab, o que irá disparar automaticamente a build do projeto.

Para ver as builds em execução, vá até a home do seu repositório, e no menu lateral, clique em CI / CD > Pipelines. Você verá suas pipelines em execução, como na figura abaixo:

Fig. 4 – Pipeline em execução, no stage test.

Aqui, vemos a importância das stages, citadas anteriormente neste artigo. Elas separam, de forma clara e visual, qual etapa da sua pipeline está sendo executada, bem como permite ver qual estágio falhou.

Na Fig. 4, vemos que está rodando o estágio test. Na build anterior, veja que a build falhou justamente neste estágio.

Assim, fica fácil visualizar onde você precisa corrigir seu pipeline.

Já na Fig. 5, vemos os estágios concluídos.

Fig. 5 – Build concluída e artefatos disponíveis para download.

Também vemos um botão para baixar os artefatos desta build, uma vez que agora estes artefatos estão armazenados no teu repositório.

Uma vez completo este pipeline, o próximo passo seria a publicação em produção deste artefato, para executá-lo. Mas este assunto ficará para um próximo artigo.

Conclusão

Com este artigo, temos o embasamento teórico sobre integração contínua, e sua utilização com o GitLab CI. Existem, com certeza, várias ferramentas no mercado que se propõem a fazer esta função, e o GitLab é uma ótima alternativa open source a este problema. Espero ter ajudado com esta contribuição, e até a próxima!

Referências

https://docs.gitlab.com/ee/ci/examples/deploy_spring_boot_to_cloud_foundry/index.html

Leia também a versão em inglês desse post.