DevSecOps

28 mar, 2017

GitLab + Jenkins: uma integração poderosa

Publicidade

Fala, pessoal! Hoje vamos falar um pouco sobre a integração entre o GitLab e o Jenkins, que pode adiantar muito a sua vida. Vamos lá?

O início

Para começar nosso projeto, a primeira coisa que precisamos é ter o Docker instalado, pois é com ele que vamos subir os serviços do GitLab e do Jenkins por meio do docker-compose (vamos falar mais pra frente). Para instalar, verifique qual SO você está usando e Go!Go!Go! É só seguir esse tutorial.

Para a instalação do docker-compose é só seguir a documentação oficial, que vai dar certo, pode confiar.

Docker Compose

Com o docker-compose, podemos criar, configurar e subir todos os serviços que vamos precisar de uma só vez, com um único comando. Para isso, vamos criar um arquivo docker-compose.yml na pasta de sua preferência e copiar todo o conteúdo abaixo para dentro dele. Não se preocupe, vou explicar cada item. Se você quiser saber mais, é só acessar aqui.

version: '2'
 
services:
    ambassador:
      image: cpuguy83/docker-grand-ambassador
      container_name: ambassador
      hostname: ambassador01
      network_mode: "bridge"
      volumes:
        - "/var/run/docker.sock:/var/run/docker.sock"
      command: "-name jenkins -name gitlab "
 
    jenkins:
      image: jenkins:latest
      container_name: jenkins
      hostname: jenkins01
      network_mode: "bridge"
      links:
        - "ambassador:gitlab"
      ports:
        - "8080:8080"
        - "50000:50000"
      volumes:
        - ~/Projects/jenkins_home:/var/jenkins_home
 
    gitlab:
        image: gitlab/gitlab-ce
        container_name: gitlab
        hostname: gitlab
        restart: always
        network_mode: bridge
        links:
          - "ambassador:jenkins"
        ports:
           - "443:443"
           - "8050:80"
           - "22:22"
        volumes:
          - ~/Projects/gitlab/config:/etc/gitlab
          - ~/Projects/gitlab/logs:/var/log/gitlab
          - ~/Projects/gitlab/data:/var/opt/gitlab
  • version ‘2’: Com a versão 2 da sintaxe do docker-compose conseguimos usar todas as novas funcionalidades disponíveis do Compose e do Docker Engine.
  • services: Todos os serviços que serão utilizados no nosso projeto devem estar listados abaixo dele (a estrutura de services só funciona com a versão 2 da sintaxe).
  • nome-do-serviço: Nome para identificar o serviço no docker-compose.
    • image: Imagem docker que será utilizada para o serviço.
    • container_name: Atribui um nome ao container, tornando mais fácil a administração.
    • hostname: Adiciona um nome ao host. Vamos usar os hostnames nas próximas etapas.
    • network_mode: Configurações de rede para o container. O modo bridge sobe todos os containeres na mesma rede.
    • links: Faz o link entre os containeres, para que a comunicação por nome seja possível (falei que o hostname era importante).
    • ports: Você pode definir quais portas serão abertas interna e externamente no container. Todos os padrões para definição de portas podem ser encontrados aqui.
    • volumes: Monta paths ou volumes nomeados, especificando um caminho no host ou não. Todos os tipos de montagem de volume aqui.

Essa é só uma explicação básica da estrutura do YAML para o docker-compose file que vamos utilizar. Caso você queira se aprofundar ainda mais no assunto, a documentação oficial pode ajudar nisso. Você pode acessá-la aqui.

A identação é essencial para o funcionamento do docker-compose.

Agora que o docker-compose.yml foi configurado e entendido, vamos começar com o que realmente interessa.

Serviços

Antes de prosseguir com o projeto, segue uma breve explicação sobre cada serviço que estamos subindo. Voltaremos com a programação normal em seguida, nesse mesmo canal e nesse mesmo horário.

Docker Grand Ambassador

Esse serviço permite a comunicação bidirecional entre containeres. Isso significa que ele criará automaticamente um proxy em todas as portas expostas e também detectará automaticamente as alterações feitas em um container ajustando o servidor proxy de acordo com a necessidade (por exemplo, um container é reiniciado e seu IP muda). Ou seja, ele vai nos poupar o trabalho de fazer um servidor DNS.

Você pode ler mais sobre o Docker Grand Ambassador aqui.

Jenkins

O Jenkins permite a automação dos processos no nosso projeto. Podemos automatizar testes, builds etc, escolhendo quais serão as ações que vão acionar nosso Job.

Vamos ver mais sobre essa integração ainda neste artigo.

GitLab

O Gitlab vai ser o nosso gerenciador de repositório. Ele é muito parecido com o GitHub, mas com a vantagem de podermos subir o serviço localmente. Além disso, a integração dele com o Jenkins é muito grande (aliás, esse é o propósito deste artigo). Por meio de um WebHook vamos conseguir a comunicação direta com o Jenkins, eliminando a necessidade de ele ficar checando o repositório constantemente. O GitLab vai informar ao Jenkins quando um evento ocorre (um Merge Request de uma feature branch na branch Develop, por exemplo) e com isso um Job ligado ao Jenkins pelo WebHook é iniciado.

Agora, depois de tanta enrolação explicação, é hora de a mágica acontecer.

Subindo o ambiente

Iniciando os serviços

No diretório em que você criou o arquivo docker-compose.yml, execute o comando:

docker-compose up

A saída deverá ser parecida com essa (pelo menos, eu espero):

def is_valid(email):
  return email and '@' in email

O segundo arquivo serve para automatizar o teste e facilitar nossa vida (é para isso que estamos aqui).

mail_test.py

import unittest
import mail
class MailTest(unittest.TestCase):
  def test_should_return_true_when_email_is_valid(self):
      self.assertTrue(mail.is_valid('iam@gustavohenrique.net'))
  def test_should_return_false_when_email_is_invalid(self):
      self.assertFalse(mail.is_valid('xxxxx'))
if __name__ == '__main__':
  unittest.main()

Fonte dos códigos em Python

Configurando o Jenkins

Vamos precisar do GitLab Plugin para nos conectarmos ao repositório do projeto (lembre-se: são só dois arquivos, mas vamos manter a positividade). Para instalar, vá até [Gerenciar Jenkins]->[Gerenciar Plugins] e clique na aba Disponíveis.

Com o plugin instalado, vamos adicionar uma conexão com o GitLab, seguir alguns passos simples e talvez chegar lá!

Criando um access token

Clique no círculo com sua imagem de perfil, que fica no canto superior direito, e vá em Profile Settings. Clique na aba Access Tokens. Digite um nome fácil de identificar para seu token e clique em Create Personal Access Token.

Após a criação, copie o hash exibido na tela, porque vamos usá-lo no próximo passo.

O token desaparece após atualizar a página, então, guarde em um lugar seguro.

Adicionando a credencial no Jenkins

Na tela inicial do Jenkins, vá até Credentials. Clique na seta do lado de global e selecione Add Credentials.

Na janela a seguir, selecione GitLab API Token e coloque o hash gerado no GitLab no campo API token.

Após clicar em OK, você verá sua credencial criada.

Configurando a conexão Gitlab x Jenkins

Com a nossa credencial criada, vamos em [Gerenciar Jenkins]->[Configurar o sistema]. Desça até a Gitlab e preencha as informações conforme a imagem abaixo. Ao terminar, clique em Test Connection. Se tudo estiver certo, clique em Salvar.

Depois de tantas configurações, vamos em frente!

Criação do Job

No canto esquerdo, clique em Novo Job, escolha Projeto Freestyle, digite um nome para o Job e clique em OK.

Com o Job criado, vamos às configurações.

General

Adicione a conexão que criamos no campo GitLab Connection.

Gerenciamento de código fonte

Selecione a opção Git e adicione as informações do repositório criado no GitLab.

Para adicionar as credencias válidas para o repositório, clique em [Add]->[Jenkins] e adicione um usuário e senha válidos para conexão.

Trigger de Builds

Esse é o primeiro passo para nossa integração entre os dois serviços. Estamos quase lá!

Marque a opção Build when a change is pushed to GitLab e selecione quais ações executadas no GitLab vão acionar o Job no Jenkins. Copie a URL logo após a frase GitLab CI Service URL, pois vamos usá-la mais pra frente.

Build

Adicione um passo no build com a opção Executar shell e adicione o código python mail_test.py. Com isso, os testes que foram adicionados ao repositório serão executados pelo Jenkins.

Clique em Salvar e o Job está finalizado!

Ações de pós-build

Selecione a opção Publish build status to GitLab commit. Agora o Jenkins colocará o feedback de cada build nos commits/merges que acionaram o Job.

Webhook

Como último passo, vamos adicionar o Webhook em nosso repositório no GitLab. Ele vai fornecer as informações para o Jenkins quando houver alguma alteração ou ação no repositório no qual ele foi configurado.

Na página inicial do repositório, clique na engrenagem no canto superior direito e selecione Webhooks.

Cole a URL que o Jenkins forneceu no campo URL e substitua localhost por Jenkins. Selecione as ações que vão acionar o webhook e clique em Add Webhook.

O grand finale

Após tantos passos e configurações, vamos ver nosso projeto rodando. Abra um merge request ou faça um push para o repositório e aguarde o Job ser iniciado. Ao finalizar, ele vai adicionar ao GitLab o feedback do build realizado com as alterações que foram feitas no código. Com isso seu projeto ganha muito mais agilidade e confiabilidade, com testes e feedbacks rápidos e automatizados.

Espero ter ajudado de alguma forma! Ficou alguma dúvida ou tem alguma sugestão? Utilize os campos abaixo!

Até a próxima!