🇧🇷GitLab CI – Para Pipelines CI/CD & DevOps
🇬🇧 – To read this article in English click here
Neste artigo, explico sobre CI/CD na prátixa, mais especificamente o GitLab CI/CD. CI/CD é uma prática de desenvolvimento que facilita e automatiza o processo de criação e entrega de software. CI (Continuous Integration) faz com que os desenvolvedores integrem o código com frequência, rodando testes automáticos para garantir que nada quebre. CD (Continuous Delivery ou Continuous Deployment) automatiza o envio de novas versões para produção ou outros ambientes, tornando o processo mais rápido e seguro. Isso significa atualizações mais rápidas e menos erros manuais. Vamos falar sobre build, deploy, segurança, verificações, Runners e muito mais.
Vamos começar:
Criando um ambiente para trabalharmos:
Acesse o meu repositório no github:
https://github.com/GustavoSantanaData/Git-CI-CD
Instalando o gitlab localemnte:
no arquivo install ./04-install-gitlab.sh alterar o endereço ip. (esse passo somente se for usar o gitlab localmente)
#!/bin/bash
sudo mkdir -p /storage/docker-homol/deploy/gitlab/{data,logs,config}
docker run -dit \
-p "2222:22" \
-p "8080:80" \
-p "443:443" \
--name gitlab \
--hostname endereço-server \
-v /storage/docker-homol/deploy/gitlab/data:/var/opt/gitlab \
-v /storage/docker-homol/deploy/gitlab/logs:/var/log/gitlab \
-v /storage/docker-homol/deploy/gitlab/config:/etc/gitlab \
--shm-size 256m \
gitlab/gitlab-ce:14.7.6-ce.0
rode o arquivo no terminal
./04-install-gitlab.sh
acessar
localhost:8080
usuario: root
senha: 123456789
Nesse ponto, o seu gitlab ja estará disponivel localmente. Agora, crie um repositório.
Runner:
Os runners no GitLab são os “executores” dos jobs dos pipelines de CI/CD. Eles rodam em servidores configurados para compilar, testar e fazer deploy dos projetos. Existem dois tipos: shared runners, que são fornecidos pelo GitLab e usados por vários projetos, e specific runners, que você configura para atender às necessidades específicas do seu projeto, como rodar em uma máquina com configurações próprias. Essencialmente, são eles que pegam as tarefas do CI/CD e fazem acontecer.
Dentro do repositório, no menu lateral direito, entre em ci/cd e pegue o token de registro
no arquivo 05-config-runners.sh
rode o primeiro trecho de código acrescentando o token do gitlab para criar o runner
sudo gitlab-runner register -n \
--url http://seu -ip:8080 \
--registration-token GR1348941w5eCWTWhMTxorW_RB4Qu \
--executor shell \
--description "Runner Shell"
rode o arquivo no seu terminal
voltando no site do gitlab o runner vai aparecer verdinho, clicar em alterar e deixar assim
rodar os comandos
sudo systemctl restart gitlab-runner
sudo systemctl enable gitlab-runner
rodar segundo trecho do arquivo para criar o container do runner
docker run -dit \
--name runner-docker \
--restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /opt/gitlab-runner/config:/etc/gitlab-runner \
gitlab/gitlab-runner:ubuntu-v14.9.1
rodar o terceiro código ajustado com o token e o url com endereço ip do runner
docker exec -it runner-docker \
gitlab-runner register -n \
--url http://seu-ip:8080/ \
--registration-token GR1348941w5eCWTWhMTxorW_RB4Qu \
--clone-url http://seu-ip:8080/ \
--executor docker \
--docker-image "docker:latest" \
--docker-privileged
Prontinho, seu ambiente gitlab está configurado e pronto para começarmos a criar nossas pipelines CI/CD
CI:
no repositório, crie um arquivo .gitlab-ci.yml
O arquivo .gitlab-ci.yml é onde você define os pipelines de CI/CD no GitLab. Nele, você especifica os estágios do pipeline, como build, test e deploy, e os comandos que serão executados em cada fase. Esse arquivo fica na raiz do projeto e é lido automaticamente pelo GitLab para orquestrar as tarefas. É totalmente configurável, permitindo definir jobs, variáveis de ambiente, dependências e até em quais máquinas (runners) os jobs devem rodar. Basicamente, o .gitlab-ci.yml é o cérebro que controla todo o processo de automação no GitLab.
criando um job com trigger manual pra iniciar
job1:
when: manual
tags:
- "shell"
scripts:
- echo "Executa somente manual"
Esse código define um job chamado job1 no pipeline de CI/CD do GitLab. Explicação:
- job1:: Nome do job, usado para identificar essa etapa no pipeline.
- when: manual: Especifica que este job deve ser executado manualmente, ou seja, ele não será disparado automaticamente quando o pipeline rodar. Alguém precisará clicar em “play” no GitLab para executá-lo.
- tags:: Define que este job deve ser executado por um runner que tenha a tag “shell”. Isso é útil quando você tem diferentes runners configurados para diferentes tipos de tarefas.
- script:: Lista de comandos que serão executados no job. Neste caso, o job vai apenas rodar o comando echo “Executa somente manual”, que imprime essa mensagem no terminal.
agendando play da pipeline
job2:
when: delayed
start_in: 1 minute
script: echo "execução em 1 muinuto"
Já esse código define um job chamado job2 que será executado com um atraso programado no pipeline de CI/CD do GitLab. explicação:
- job2:: Nome do job, usado para identificar essa etapa no pipeline.
- when: delayed: Indica que o job será executado com um atraso, ou seja, ele não rodará imediatamente quando o pipeline for iniciado.
- start_in: 1 minute: Define o tempo de atraso antes de o job começar a ser executado. Nesse caso, o job vai começar 1 minuto após o início do pipeline.
- script:: Define o comando que será executado. Neste caso, o job vai rodar o comando echo “execução em 1 minuto”, que imprime essa mensagem no terminal.
adicionando estagios(tarefas) para o pipeline
caso a etapa 1 execute com sucesso ele executa um script
na etapa 2 caso a etapa1 falhe ele executa o script da etapa 2. um exemplo pratico disso é envio de email, se der sucesso ele envia um email de sucesso e se der falha faz outra coisa
stages:
- e1
- e2
- e3
Etapa1:
stage: e1
when: on_success
script:
- echo "Etapa1"
Etapa2:
stage: e2
when: on_failure
script:
- echo "Falha na etapa 1"
Etapa3:
stage: e3
when: always
script:
- echo "sempre sera executado"
resultado:
Esse código possui três estágios e três jobs, cada um com condições específicas de execução.
1. Definição dos Estágios
stages:
- e1
- e2
- e3
Aqui, o pipeline é dividido em três estágios: e1, e2 e e3. O GitLab executa os estágios na ordem definida. Cada job é atribuído a um desses estágios.
2. Job Etapa1
Etapa1:
stage: e1
when: on_success
script:
– echo “Etapa1”
- stage: e1: Esse job pertence ao estágio e1.
- when: on_success: O job Etapa1 será executado apenas se o estágio anterior (se houver) for bem-sucedido. Neste caso, ele será executado automaticamente, já que é o primeiro estágio.
- script:: O job executa o comando echo “Etapa1”, imprimindo essa mensagem no terminal.
3. Job Etapa2
Etapa2:
stage: e2
when: on_failure
script:
– echo “Falha na etapa 1”
- stage: e2: Esse job pertence ao estágio e2.
- when: on_failure: O job Etapa2 só será executado se o job anterior (Etapa1) falhar.
- script:: Se for executado, o job imprime a mensagem echo “Falha na etapa 1”.
4. Job Etapa3
Etapa3:
stage: e3
when: always
script:
– echo “sempre sera executado”
- stage: e3: Esse job pertence ao estágio e3.
- when: always: Esse job será executado sempre, independentemente do sucesso ou falha dos estágios anteriores.
- script:: O job imprime a mensagem echo “sempre sera executado”.
===========================================================
timeout:
o timeout define maximo de tempo que uma pipeline pode esperar o script rodar
job3:
timeout: 1m
script:
- sleep 20
- echo "executa com timeout de 1 minuto"
before_script e after_script:
executa algo antes de começar os jobs e depois que os jobs terminam ele executa alguma outra coisa
before_script:
- echo "Antes do script"
after_script:
- echo "Depois do script"
job4:
script:
- echo "executando script"
Only merge_requests, tags e variables
executa os jobs somente em situações específicas
job6:
script:
- echo "Executando quando há uma mesclagem"
only:
- merge_request
job7:
only:
- tags
script:
- echo "Executando quando a tag é criada"
when: manual
job8:
only:
variables:
- $RELEASE == 'staging'
script:
- echo "Executado porque declarou a variavel RELEASE com valor staging"
explicação do código:
Esse código define três jobs no arquivo .gitlab-ci.yml do GitLab, cada um com condições específicas de execução. Vamos detalhar cada job:
1. Job job6
job6:
script:
– echo “Executando quando há uma mesclagem”
only:
– merge_request
- script:: Este job executa o comando echo “Executando quando há uma mesclagem”, que imprime a mensagem no terminal.
- only:: O job será executado apenas em situações de merge requests. Isso significa que ele só será ativado quando houver uma solicitação de mesclagem, ou seja, quando um desenvolvedor solicitar a fusão de uma branch em outra.
2. Job job7
job7:
only:
– tags
script:
– echo “Executando quando a tag é criada”
when: manual
- only:: Este job será executado apenas quando uma tag for criada no repositório. Tags são marcadores usados para identificar versões específicas do código.
- script:: Quando o job for ativado, ele executará echo “Executando quando a tag é criada”, imprimindo essa mensagem.
- when: manual: Isso significa que, mesmo que a tag seja criada, a execução desse job precisará ser iniciada manualmente. O usuário deve clicar em “play” para que o job seja executado.
3. Job job8
job8:
only:
variables:
– $RELEASE == ‘staging’
script:
– echo “Executado porque declarou a variavel RELEASE com valor staging”
- only:: Este job é condicionado a uma variável de ambiente chamada RELEASE. Ele será executado somente se RELEASE tiver o valor staging.
- script:: Se as condições forem atendidas, o job executa o comando echo “Executado porque declarou a variavel RELEASE com valor staging”, imprimindo a mensagem que explica o motivo da execução.
Execução dos jobs
executando job8:
ir em pipeline>executar pipeline e executar com o valor staging o pipeline será criado e executado
executando job7:
ir em repositório>tags>novo tag e criar uma tag. o pipeline será criado e executado
executando job6:
criar nova ramificação no repositório chamada developer
alterar um arquivo exemplo(README) e iniciar uma solicitação de merge request da branch developer para a branch main. apó isso, ao clicar em merge ele irá realizar o job 6 que está com o gatilho only merge request
parallel:
executa jobs em paralelo
job8:
parallel: 3
script: echo "sleep 5"
Cache de arquivos:
Armazena arquivos do repositório em cache e você poderá baixa-los ou realizar uma série de comandos para ele.
job18:
script:
- echo "Exemplo de cache de arquivos."
name: "artefato-exemplo"
artifacts:
expire_in: 2 minutes
paths:
- ./teste.txt
Utilizando os runners Docker e Shell e aprendendo needs:
build_a:
image: alpine
script:
- echo "Executando um build"
- sleep 10
tags:
- docker
teste_a:
needs: [build_a]
script:
- docker run -dit --name teste ubuntu
tags:
- shell
o build_a baixa a imagem no alpine e imprime uma imagem. isso usando o runner de tag docker
o teste_a usa o need para indicar que precisa aguardar o build_a terminar a execução para iniciar. Ele usa o script pra subir uma imagem do ubuntu na minha máquina local. tudo isso utilizando o runner de tag shell
Debug e exibição de todas as variáveis:
Exibe todas as variáveis do job e podem ser utilizadas para algum tipo de gatilho
job12:
script:
- export
resultado:
Variáveis do CI-CD:
criando variaveis dentro do gitlab para chama-las no código de ci/cd
Vá até as configurações>CI/CD>variáveis e criar uma nova variável
job12:
script:
- echo $senha
Esse código mostra o valor da variavel
Variáveis no arquivo .gitlab-ci.yaml:
variables:
VAR1: "teste1"
VAR2: "teste2"
job12_a:
script:
- echo $VAR1
- echo $VAR2
Executando pipeline com condições de User e branch:
se branch main e user root ele inicia um processo de pipeline manual. se branch developer ele não executa nenhuma pipeline
job13:
script:
- echo "Pipeline executada somente na branch main e usuario executor gustavo"
rules:
- if: '$CI_COMMIT_BRANCH == "main" && $GITLAB_USER_LOGIN == "root" '
when: manual
- if: '$CI_COMMIT_BRANCH == "developer" '
when: never
Executando pipeline com except:
Executa a pipeline exceto se estiver com uma mensagem específica
job14:
script:
- echo "Executa a pipeline exceto se tiver com mensagem push-teste"
except:
variables:
- $CI_COMMIT_MESSAGE =~ /push-test/
Âncora:
A âncora pega os comandos do job em que foi declarado, no caso o job10 vai utilizar todos os comandos do job9 que não estão declarados no job10
por exemplo, no job10 temos um comando de script então ele não pega o script do job 9, somente os outros comandos.
job9: &ancora
when: manual
script:
- echo "Executa o job"
job10:
<<: *ancora
script: echo "Pelomenos o script foi substituido"
Ancora somente no only:
Job10 usa a âncora somente para pegar os comandos do only no job1
job1:
only:
variables: &variavel
- $GATILHO == 'valor'
script: echo "Ancora em uma sessao do Job"
job10:
only: *variavel
script: echo "Pelomenos o script foi substituido"
mais exemplos de uso da âncora:
.before-script: &before
- echo "Executa script antes"
.script: &script
- echo "Executa script por segundo"
.after-script: &after
- echo "Execute este script por ultimo"
job1:
before_script:
- *before
script:
- *script
- echo "Execute somente, para este job"
after_script:
- *after
Executar pipeline via API:
Executando por tag:
adicionar novo gatilho em configurações>ci/cd>gatilho de pipeline
pegar curl e substituir pelo token gerado e referenciar
curl -X POST \
--fail \
-F token=TOKEN \
-F ref=0.0.1 \
http://seu-ip:sua-porta/api/v4/projects/2/trigger/pipeline
criar uma nova tag 0.0.1
rodar comando no .git-ci
job1:
script: echo "Executando via API"
e depois, rodar o curl no terminal:
curl -X POST \
--fail \
-F token=TOKEN \
-F ref=0.0.1 \
http://seu-ip:sua-porta/api/v4/projects/2/trigger/pipeline
toda vez que você rodar esse comando no terminal a pipeline vai iniciar automaticamente
Executando com verificação de branch e variável:
incluir código:
job1:
only:
variables:
- $GATILHO == "valor"
script: echo "Executando via API com branch main e variável"
rodar no terminal o seguinte comando passando uma variável com valor “valor” e referênciar a branch main
o gitlab vai receber esses parâmetros e rodar o pipeline utilizando eles na verificação.
docker exec -it runner-docker \
gitlab-runner register -n \
--url http://172.17.0.1:8080/ \
--registration-token GR1348941ig4xM7hguPgAvLL5hkst \
--clone-url http://172.17.0.1:8080/ \
--executor docker \
--docker-image "docker:latest" \
--docker-privileged
Conclusão:
Neste artigo, vimos como criar e configurar o GitLab localmente e exploramos diversos exemplos de comandos de CI/CD. Esses exemplos ajudam a entender como automatizar o fluxo de trabalho de desenvolvimento, utilizando pipelines para integrar e entregar software de forma mais eficiente. Espero que isso tenha esclarecido como aplicar esses conceitos em seus projetos.