Pipelines de integração contínua e entrega contínua (CI/CD) automatizam processos críticos no desenvolvimento de software, mas gargalos de desempenho podem atrasar o ciclo de lançamento. Descrevo aqui técnicas que reduzi o tempo de execução da minha pipeline de 45 minutos para 10 minutos.
Identificação de Gargalos
Antes de otimizar, é essencial analisar as causas da lentidão. Fatores comuns incluem scripts ineficientes, processos redundantes, alocação de recursos inadequada e falta de paralelismo em tarefas. Utilizei logs de pipeline e ferramentas de profiling para localizar as áreas problemáticas, como testes que consumiam a maior parte do tempo e builds de container otimizáveis.
Estratégias de Otimização
1. Paralelização de Tarefas
Executei testes e builds de forma concorrente para aproveitar melhor os recursos. A configuração no GitHub Actions foi ajustada para definir jobs independentes:
jobs:
verificacao-codigo:
runs-on: ubuntu-latest
steps:
- name: Rodar Testes Unitários
run: npm test
empacotamento-aplicativo:
runs-on: ubuntu-latest
steps:
- name: Gerar Build da Aplicação
run: npm run build
2. Cache de Dependências
Implementei cache para módulos do Node.js, evitando reinstalações repetidas. A ação de cache do GitHub Actions foi configurada com base em hashes do arquivo de lock:
- name: Armazenar Cache de Dependências
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }}
Esta medida reduziu significativamente o tempo de instalação de dependências.
3. Refinamento de Testes
Em vez de executar toda a suíte de testes em cada commit, dividi os testes em lotes focados. Usei opções como o seletor de testes do Jest para direcionar apenas código modificado:
jest --changedSince=main
Além disso, ajustei a cobertura de testes para evitar redundâncias.
4. Simplificação de Builds de Container
Adotei multi-stage builds no Docker para reduzir o tamanho das imagens e acelerar o processo. O Dockerfile foi reestruturado para separar compilação e implantação:
# Etapa de compilação
FROM node:18 AS compilador
WORKDIR /projeto
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
# Etapa de produção
FROM nginx:stable-alpine
COPY --from=compilador /projeto/dist /usr/share/nginx/html
5. Utilização de Runners na Nuvem
Migrei para runners gerenciados na nuvem, permitindo escalonamento dinâmico de recursos. Com runners baseados em nuvem, como os da AWS, obtive maior desempenho sem sobrecarregar infraestrutura local. Optei por instâncias spot para controlar custos.
Desafios e Soluções
A otimização encontrou obstáculos, como o aumento de custos com runners na nuvem, mitigado pelo uso de instâncias econômicas. Ferramentas de CI com suporte limitado a cache foram complementadas com soluções de terceiros. Além disso, a paralelização exigiu cuidado com dependências entre jobs para evitar falhas.
Resultados Alcançados
Após as otimizações, os métricos melhoraram drasticamente:
- Tempo total da pipeline reduzido de 45 para 10 minutos.
- Execução de testes acelerada em 70%.
- Tempo de build de container reduzido em 50%.
Esses ganhos proporcionaram ciclos de desenvolvimento mais rápidos e feedback mais imediato para a equipe.