Como construir pipelines de CI/CD para projetos monorepo com Nx e Turborepo
1. Fundamentos do Monorepo e Ferramentas de Build
Monorepo é uma estratégia de gerenciamento de código onde múltiplos projetos (apps, libs, packages) residem em um único repositório. Em pipelines CI/CD, isso oferece vantagens como compartilhamento de dependências, refatoração atômica e visibilidade unificada. No entanto, desafios surgem: builds lentos, execução desnecessária de testes e complexidade de orquestração.
Nx e Turborepo são ferramentas de build modernas que resolvem esses problemas com cache inteligente, paralelismo e execução baseada em dependências. Nx oferece um ecossistema mais completo, com geradores de código e plugins para frameworks específicos. Turborepo foca em simplicidade e desempenho, com cache remoto nativo e integração fácil com monorepos baseados em npm/yarn/pnpm.
Uma estrutura típica de monorepo:
meu-monorepo/
├── apps/
│ ├── web/ # Aplicação React
│ ├── api/ # Backend Node.js
│ └── mobile/ # App React Native
├── libs/
│ ├── shared-ui/ # Componentes compartilhados
│ └── utils/ # Funções utilitárias
├── packages/
│ └── eslint-config/ # Configuração compartilhada
├── nx.json # Configuração Nx
├── turbo.json # Configuração Turborepo
└── package.json
2. Configuração Inicial do Ambiente CI/CD
Vamos usar GitHub Actions como provedor CI/CD. A configuração básica envolve instalar a ferramenta escolhida, configurar cache e definir triggers.
Exemplo de pipeline com Nx no GitHub Actions:
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
setup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
Para Turborepo, a configuração é similar, mas com foco em cache remoto:
name: CI/CD com Turborepo
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npx turbo run build test --filter=[main]
3. Estratégias de Cache e Dependências
O cache é o coração da eficiência em pipelines monorepo. Para dependências, utilizamos o cache nativo do GitHub Actions:
- uses: actions/cache@v3
with:
path: |
node_modules
.npm
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
Para cache de artefatos de build:
Nx:
- uses: actions/cache@v3
with:
path: |
.nx/cache
node_modules/.cache/nx
key: ${{ runner.os }}-nx-${{ hashFiles('package-lock.json') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-nx-
Turborepo:
- uses: actions/cache@v3
with:
path: |
.turbo/cache
node_modules/.cache/turbo
key: ${{ runner.os }}-turbo-${{ hashFiles('package-lock.json') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-
O hashing incremental é automático: Nx e Turborepo calculam hashes dos arquivos de entrada de cada tarefa e reutilizam resultados se nada mudou.
4. Pipeline de Testes e Linting no Monorepo
A execução apenas nos projetos afetados é o diferencial. Com Nx, usamos affected:
jobs:
test-affected:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npx nx affected --target=test --parallel=3 --base=main
- run: npx nx affected --target=lint --parallel=3 --base=main
Com Turborepo, usamos --filter:
test-affected:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npx turbo run test lint --filter=[main]
Para relatórios de cobertura agregados:
- run: npx nx affected --target=test --coverage --parallel=3
- uses: codecov/codecov-action@v3
with:
directory: coverage/
flags: unittests
5. Build e Publicação de Artefatos
Build otimizado com dependências entre projetos:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- run: npm ci
- run: npx nx run-many --target=build --all --parallel=3
- uses: actions/upload-artifact@v3
with:
name: build-artifacts
path: |
dist/
apps/*/dist/
Para versionamento semântico com changesets:
- uses: changesets/action@v1
with:
publish: npm run release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
6. Deploy Contínuo e Ambientes Múltiplos
Estratégia de deploy por ambiente:
deploy-staging:
if: github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
needs: [build, test-affected]
steps:
- uses: actions/download-artifact@v3
with:
name: build-artifacts
- name: Deploy to Vercel (Staging)
run: |
npx vercel --token ${{ secrets.VERCEL_TOKEN }} --prod --scope staging
deploy-production:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: [build, test-affected]
steps:
- uses: actions/download-artifact@v3
with:
name: build-artifacts
- name: Deploy to AWS
run: |
aws s3 sync dist/apps/web s3://meu-bucket-producao/
Para rollback automatizado:
- name: Rollback on failure
if: failure()
run: |
echo "Falha detectada. Iniciando rollback..."
aws s3 sync s3://meu-bucket-backup/last-good/ s3://meu-bucket-producao/
7. Monitoramento e Otimização do Pipeline
Métricas de desempenho podem ser extraídas com comandos específicos:
# Nx: relatório de cache
- run: npx nx report
# Turborepo: estatísticas de execução
- run: npx turbo run build --dry-run
Configuração de timeouts e paralelismo:
jobs:
test:
timeout-minutes: 30
strategy:
matrix:
project: [web, api, mobile]
steps:
- run: npx nx test ${{ matrix.project }} --parallel=2
Boas práticas finais:
- Separe build, teste e deploy em stages independentes
- Use
concurrencypara cancelar execuções antigas no mesmo branch - Configure notificações via Slack ou e-mail com
actions/github-script
- uses: actions/github-script@v6
if: failure()
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Pipeline falhou em ${context.sha}`,
body: 'Verifique os logs do workflow para detalhes.'
})
Referências
- Documentação Oficial do Nx - CI/CD — Guia completo de configuração de pipelines CI/CD com Nx, incluindo cache distribuído e execução paralela.
- Turborepo - Guia de CI/CD — Documentação oficial do Turborepo para integração com GitHub Actions, GitLab CI e CircleCI.
- GitHub Actions - Cache de dependências — Tutorial oficial sobre como configurar cache para acelerar workflows.
- Changesets - Versionamento semântico — Ferramenta para gerenciar versionamento e changelog automatizado em monorepos.
- Monorepo CI/CD com Nx - Artigo Técnico — Artigo da equipe Nrwl sobre estratégias avançadas de CI/CD para monorepos com Nx.
- Turborepo vs Nx - Comparativo — Comparação oficial entre Turborepo e Nx, com diferenças de cache, paralelismo e orquestração.