O GitLab CI/CD é uma plataforma de integração e entrega contínua integrada diretamente ao GitLab. Diferente de ferramentas de CI externas que exigem configuração separada e webhooks, o GitLab CI/CD lê um único arquivo .gitlab-ci.yml do seu repositório e executa pipelines automaticamente a cada push. Essa integração estreita significa que seu código, issues, merge requests e pipelines de deploy vivem em um único lugar.
Este guia percorre a configuração de pipelines do zero — stages, jobs, runners, cache, artefatos, variáveis, environments e estratégias de deploy que funcionam em produção.
Pré-requisitos
- Uma conta GitLab (gitlab.com ou instância self-hosted)
- Um repositório Git hospedado no GitLab
- Conhecimento básico de sintaxe YAML
- Docker instalado (para runners com executor Docker)
- Familiaridade com conceitos de CI/CD (build, test, deploy)
Entendendo a Estrutura de Pipeline do GitLab CI/CD
Um pipeline consiste em stages que rodam sequencialmente e jobs dentro de cada stage que rodam em paralelo. Esta é a estrutura fundamental:
# .gitlab-ci.yml
stages:
- build
- test
- deploy
build-app:
stage: build
image: node:20
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 hour
unit-tests:
stage: test
image: node:20
script:
- npm ci
- npm run test:unit
coverage: '/Lines\s+:\s+(\d+\.?\d*)%/'
integration-tests:
stage: test
image: node:20
services:
- postgres:15
variables:
POSTGRES_DB: test_db
POSTGRES_USER: runner
POSTGRES_PASSWORD: testing
DATABASE_URL: "postgresql://runner:testing@postgres:5432/test_db"
script:
- npm ci
- npm run test:integration
deploy-staging:
stage: deploy
script:
- ./scripts/deploy.sh staging
environment:
name: staging
url: https://staging.example.com
rules:
- if: $CI_COMMIT_BRANCH == "develop"
O stage build roda primeiro. Quando passa, ambos os jobs de teste rodam em paralelo (estão no mesmo stage). Somente se todos os testes passarem o deploy prossegue.
Configurando GitLab Runners
Runners executam os jobs do seu pipeline. Você tem duas opções:
Runners Compartilhados (Início Rápido)
O GitLab.com fornece runners compartilhados gratuitamente. Estão disponíveis imediatamente — sem nenhuma configuração. Navegue até Settings → CI/CD → Runners para verificar se estão habilitados.
Runners Self-Hosted (Produção)
Para melhor desempenho e controle, instale seu próprio runner:
# Instalar GitLab Runner no Ubuntu
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runner
# Registrar o runner
sudo gitlab-runner register \
--url "https://gitlab.com/" \
--registration-token "YOUR_TOKEN" \
--executor "docker" \
--docker-image "alpine:latest" \
--description "production-runner" \
--tag-list "docker,linux" \
--run-untagged="true"
Comparação de Executores de Runner
| Executor | Isolamento | Velocidade | Caso de Uso |
|---|---|---|---|
| Docker | Alto (container por job) | Rápido | Escolha padrão para a maioria dos projetos |
| Shell | Nenhum (roda no host) | Mais rápido | Scripts simples, apps legados |
| Docker Machine | Alto + autoscaling | Variável | Runners com autoscaling em nuvem |
| Kubernetes | Alto (pod por job) | Médio | Deployments nativos em Kubernetes |
| VirtualBox | VM completa | Lento | Necessidade de isolamento total de OS |
Configuração Avançada de Pipeline
Cache de Dependências
O cache evita o download repetido de dependências a cada execução do pipeline:
variables:
NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm"
cache:
key:
files:
- package-lock.json
paths:
- .npm/
- node_modules/
policy: pull-push
A diretiva key.files gera uma chave de cache a partir do package-lock.json. Quando as dependências mudam, o cache é invalidado automaticamente.
Artefatos Entre Stages
Passe outputs de build de um stage para o próximo:
build:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
- coverage/
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
expire_in: 1 week
Regras de Pipeline e Execução Condicional
Controle quando os jobs rodam com rules:
deploy-production:
stage: deploy
script:
- ./deploy.sh production
environment:
name: production
url: https://example.com
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
when: manual
- when: never
Este job só aparece em tags de versão (v1.2.3) e requer aprovação manual.
Jobs em Matriz Paralela
Teste em múltiplas versões simultaneamente:
test:
stage: test
image: node:${NODE_VERSION}
parallel:
matrix:
- NODE_VERSION: ["18", "20", "22"]
DATABASE: ["postgres", "mysql"]
script:
- npm ci
- npm run test
Isso cria 6 jobs paralelos (3 versões do Node × 2 bancos de dados).
Variáveis de CI/CD e Segredos
Armazene valores sensíveis com segurança:
deploy:
stage: deploy
script:
- echo "$DEPLOY_KEY" > key.pem
- chmod 600 key.pem
- scp -i key.pem dist/* user@server:/var/www/
after_script:
- rm -f key.pem
Cenário real: Seu time implanta uma aplicação Node.js em três environments — desenvolvimento, staging e produção. Cada environment tem credenciais de banco de dados, chaves de API e endereços de servidor diferentes. Você armazena esses dados como variáveis GitLab CI/CD com escopo por environment. O mesmo YAML do pipeline gerencia todos os deploys; apenas as variáveis diferem. Quando um desenvolvedor faz push para develop, o pipeline faz deploy automático para staging. O deploy de produção só é disparado em tags, com aprovação manual do líder técnico.
Tipos e Escopo de Variáveis
| Escopo | Configurado Em | Disponível Para |
|---|---|---|
| Projeto | Settings → CI/CD → Variables | Todos os pipelines do projeto |
| Grupo | Group → Settings → CI/CD | Todos os projetos do grupo |
| Instância | Admin → CI/CD → Variables | Todos os projetos da instância |
| Environment | Settings → CI/CD → Variables (filtro de env) | Jobs direcionados a esse environment |
| Job | variables: no .gitlab-ci.yml | Apenas aquele job específico |
Marque variáveis como Protected (disponíveis apenas em branches/tags protegidas) e Masked (ocultas nos logs de job) para credenciais.
Environments de Deploy e Estratégias
Review Apps (Environments Dinâmicos)
Crie um environment temporário para cada merge request:
review:
stage: deploy
script:
- deploy_review_app "$CI_MERGE_REQUEST_IID"
environment:
name: review/$CI_MERGE_REQUEST_IID
url: https://$CI_MERGE_REQUEST_IID.review.example.com
on_stop: stop-review
rules:
- if: $CI_MERGE_REQUEST_IID
stop-review:
stage: deploy
script:
- teardown_review_app "$CI_MERGE_REQUEST_IID"
environment:
name: review/$CI_MERGE_REQUEST_IID
action: stop
rules:
- if: $CI_MERGE_REQUEST_IID
when: manual
Deploy de Produção com Rollback
deploy-production:
stage: deploy
script:
- ./deploy.sh production
environment:
name: production
url: https://example.com
auto_stop_in: never
rules:
- if: $CI_COMMIT_TAG
when: manual
allow_failure: false
GitLab CI/CD vs Outras Plataformas de CI
| Recurso | GitLab CI/CD | GitHub Actions | Jenkins | CircleCI |
|---|---|---|---|---|
| Arquivo de Config | .gitlab-ci.yml | .github/workflows/*.yml | Jenkinsfile | .circleci/config.yml |
| Registry Embutido | Sim (container + pacotes) | Sim (container) | Não | Não |
| Opção Self-hosted | Sim (GitLab completo) | Sim (apenas runners) | Sim | Não |
| Review Apps | Nativo | Configuração manual | Manual | Manual |
| Pipelines DAG | Sim (keyword needs) | Sim (nativo) | Sim | Sim |
| Auto DevOps | Sim | Não | Não | Não |
| Minutos Gratuitos de CI | 400 min/mês | 2.000 min/mês | Ilimitado (self-host) | 6.000 min/mês |
| Curva de Aprendizado | Média | Baixa | Alta | Baixa |
O GitLab CI/CD se destaca quando você quer tudo integrado — código, CI, registry de container, environments e monitoramento em uma única plataforma. O GitHub Actions se sobressai pela amplitude do ecossistema com seu marketplace.
Armadilhas e Casos Especiais
-
Âncoras YAML não funcionam com
include: Se você usar âncoras YAML (&anchor/*anchor) em arquivos incluídos, elas não serão resolvidas entre os limites dos arquivos. Use a keywordextendsno lugar. -
O cache não é garantido: Os caches do GitLab são por melhor esforço. Runners podem não compartilhar caches. Sempre projete pipelines que funcionem sem cache (apenas mais lentamente).
-
Rede entre services: Containers de service (como
postgres:15) são acessíveis pelo nome da imagem como hostname. Usepostgres, nãolocalhost. Isso confunde muitos desenvolvedores. -
only/exceptvsrules: A sintaxe legadaonly/exceptconflita comrules. Nunca os misture no mesmo job. Prefirarules— é mais poderoso e a abordagem recomendada. -
Timeout padrão de job é 1 hora: Jobs de longa duração como testes E2E ou builds grandes falham silenciosamente no timeout. Defina
timeout: 2hexplicitamente para jobs sabidamente longos. -
Variáveis de branch protegida: Variáveis marcadas como “Protected” não estão disponíveis em feature branches. Se um job precisa de credenciais em branches não protegidas, use uma variável separada sem a flag de proteção.
Solução de Problemas
| Problema | Causa | Solução |
|---|---|---|
| Pipeline travado em “Pending” | Nenhum runner disponível com as tags correspondentes | Verifique as tags do runner ou defina tags: [] para usar qualquer runner |
| ”Cache not found” na primeira execução | O cache ainda não foi criado | A primeira execução baixa tudo; o cache é populado para a próxima |
| Services inacessíveis | Hostname errado na string de conexão | Use o nome da imagem do service como hostname (ex.: postgres, não localhost) |
| “Variable is not set” nos jobs | Variável é protegida, branch não é | Desmarque “Protected” ou faça push para branch protegida |
| Artefatos ausentes no próximo stage | artifacts.paths não corresponde ao output | Verifique os caminhos exatos; use ls -la no script para depurar |
Resumo
- GitLab CI/CD lê
.gitlab-ci.ymldo seu repositório e executa pipelines automaticamente — sem configuração de ferramenta externa - Stages rodam sequencialmente enquanto jobs dentro de um stage rodam em paralelo, oferecendo ordenação e velocidade
- Runners self-hosted com executor Docker oferecem o melhor desempenho e controle para times em produção
- Cache de dependências e passagem de artefatos entre stages reduz drasticamente o tempo de execução do pipeline
- Variáveis de ambiente com mascaramento, proteção e escopo por environment mantêm segredos seguros entre deploys
- Review apps criam environments temporários por merge request, permitindo revisão visual antes do merge