Introdução

A Integração Contínua detecta bugs no momento do merge, não em produção. O custo de um teste falhando no CI é alguns minutos da atenção de um desenvolvedor. O custo do mesmo bug em produção é muito maior. O GitLab CI é integrado ao GitLab, não requer nenhum serviço separado para funcionar e é configurado inteiramente por meio de um arquivo YAML no seu repositório.

O que é Integração Contínua?

Integração Contínua é a prática de mesclar alterações de código em uma branch compartilhada com frequência, com builds e testes automatizados executados a cada merge. O objetivo é detectar problemas de integração cedo, quando são baratos de corrigir, em vez de durante um ciclo de release quando múltiplas mudanças já se acumularam.

Os benefícios práticos: os bugs são detectados próximos ao momento em que são introduzidos, portanto o contexto ainda está fresco; falhas nos testes bloqueiam merges antes que código ruim chegue à branch principal; e as equipes ganham confiança de que a branch principal está sempre em um estado deployável.

GitLab CI

O GitLab CI é o serviço de CI/CD integrado ao GitLab. Ele lê um arquivo .gitlab-ci.yml na raiz do seu repositório e executa os jobs definidos ali a cada push. Você não precisa de um servidor Jenkins separado nem de um serviço de CI externo.

Razões para usá-lo: a configuração do pipeline fica junto ao seu código e evolui com ele, os runners compartilhados do GitLab cuidam do processamento para a maioria dos projetos, e o status do pipeline é visível diretamente nas merge requests.

Configurando o GitLab CI para um Projeto Node.js

Pré-requisitos

  • Uma conta no GitLab.
  • Um projeto Node.js em um repositório GitLab.
  • Familiaridade básica com YAML.

Passo 1: Criar um Arquivo .gitlab-ci.yml

Na raiz do seu projeto, crie .gitlab-ci.yml:

image: node:14

stages:
  - test

test_job:
  stage: test
  script:
    - npm install
    - npm test

A chave image especifica a imagem Docker em que o job é executado. A chave stages define os estágios do pipeline e sua ordem. Cada job especifica a qual estágio pertence e quais comandos executar.

Passo 2: Configurar o GitLab Runner (Opcional)

Os runners compartilhados do GitLab atendem a maioria dos projetos sem nenhuma configuração adicional. Se você precisar que os jobs sejam executados em sua própria infraestrutura, pode instalar e registrar um GitLab Runner auto-hospedado. Para a maioria dos projetos Node.js, os runners compartilhados são suficientes.

Passo 3: Commit e Push

git add .gitlab-ci.yml
git commit -m "Add GitLab CI configuration"
git push origin main

O GitLab detecta o arquivo e inicia o pipeline imediatamente.

Passo 4: Monitorar o Pipeline

Navegue até CI/CD > Pipelines no seu projeto GitLab. Você pode visualizar logs de jobs, baixar artefatos e ver o status do pipeline. Jobs com falha mostram o comando exato que falhou e sua saída.

Configuração Avançada

Cache de Dependências

Fazer cache do node_modules evita reinstalar pacotes a cada execução do pipeline:

cache:
  paths:
    - node_modules/

test_job:
  stage: test
  script:
    - npm install
    - npm test

Múltiplos Ambientes

Faça deploy para staging automaticamente a cada merge para a main:

stages:
  - test
  - deploy

deploy_staging:
  stage: deploy
  script:
    - npm run build
    - scp -r ./build user@staging-server:/var/www/app
  only:
    - main

Testes em Paralelo

Divida uma suite de testes lenta entre múltiplos runners:

test_job:
  stage: test
  script:
    - npm install
    - npm test
  parallel: 4

Variáveis de Ambiente

Armazene segredos nas configurações do projeto GitLab em Settings > CI/CD > Variables e referencie-os no seu pipeline:

script:
  - npm run deploy -- --api-key=$API_KEY

Nunca coloque segredos diretamente no .gitlab-ci.yml. Eles ficariam visíveis no histórico do repositório e para qualquer pessoa com acesso de leitura.

Boas Práticas para GitLab CI com Node.js

Fixe a versão do Node.js para evitar divergências de ambiente entre execuções do pipeline e o desenvolvimento local:

image: node:14.17.0

Adicione um passo de lint para que problemas de formatação e análise estática falhem o pipeline antes da execução dos testes:

script:
  - npm run lint
  - npm test

Restrinja jobs custosos às branches relevantes. Executar a suite de testes completa em cada commit de feature branch geralmente não é necessário:

only:
  - merge_requests
  - main

Declare artefatos de build para que possam ser baixados pela UI do pipeline ou passados entre estágios:

artifacts:
  paths:
    - build/

Resolução de Problemas Comuns

Se o pipeline falhar na instalação de dependências, verifique se todos os pacotes estão declarados no package.json e se não há conflitos de versão. O log do job mostra o erro exato.

Para erros de permissão ao executar scripts, adicione um passo de chmod:

script:
  - chmod +x ./deploy.sh
  - ./deploy.sh

Para variáveis de ambiente ausentes, verifique se estão definidas nas configurações de variáveis de CI/CD do GitLab e se o nome da variável no YAML corresponde exatamente.

Integrando Docker

Para deploys em containers, use Docker-in-Docker para construir e enviar imagens no CI:

image: docker:stable

services:
  - docker:dind

variables:
  DOCKER_DRIVER: overlay2

build_docker_image:
  stage: build
  script:
    - docker build -t my-node-app .
    - docker push my-node-app
  only:
    - main

O serviço docker:dind executa um daemon Docker dentro do container do pipeline, ao qual o script de build se conecta.

Conclusão

Um pipeline GitLab CI para um projeto Node.js leva menos de uma hora para configurar e melhora imediatamente o ciclo de feedback a cada merge. Falhas de lint e falhas de teste aparecem em minutos, em vez de durante a revisão de código ou após o deploy. Com o básico funcionando, adicione cache para acelerar as execuções, restrinja jobs às branches onde eles agregam valor e expanda o pipeline com estágios de deploy conforme o projeto amadurece.

Recursos Adicionais

Glossário

  • Integração Contínua (CI): Uma prática em que os desenvolvedores integram alterações de código com frequência, com builds e testes automatizados.
  • GitLab Runner: A aplicação que executa os jobs de CI definidos no .gitlab-ci.yml.
  • Pipeline: Uma coleção de estágios e jobs executados em uma ordem definida a cada push.