📚 Processo de Criação do Monorepo Finopping Core Services
Repositório: plat-eng-finop-finopping-core-services
Organização: Grupo Boticário
Tipo: Monorepo de bibliotecas Node.js
Status: ✅ Produção
📑 Índice
- Análise de Viabilidade
- Soluções Avaliadas
- Solução Adotada
- Arquitetura do Repositório
- Atividades Realizadas
- Fluxo de Trabalho
- Tooling e Automações
- Publicação e Deploy
- Lições Aprendidas
1. 📊 Análise de Viabilidade
Contexto
A equipe de desenvolvedores da Finopping identificou a necessidade de centralizar serviços core reutilizáveis em um único repositório, modularizando esses serviços e melhorando a colaboração entre times.
Prós do Monorepo
✅ Maior visibilidade do processo
- Todo o código core em um único lugar
- Facilita code reviews e colaboração
- Não há necessidade de buscar por múltiplos repositórios
✅ Consistência técnica
- Compartilhamento de configurações (ESLint, Prettier, TypeScript)
- Documentação centralizada e padronizada
- Bibliotecas de utilitários compartilhadas
✅ Gerenciamento de dependências mais seguro
- Dependências compartilhadas em um único
node_modulesna raiz - Redução de duplicação de bibliotecas
- Atualizações coordenadas entre pacotes
✅ Redução de duplicidade
- Global modules compartilhados entre sub-projetos
- Reutilização de código de testes e utilitários
- Build tools e configurações unificadas
Desafios Identificados
⚠️ Complexidade inicial
- Curva de aprendizado para novos desenvolvedores
- Necessidade de tooling adicional (scripts customizados para scaffolding, automações de changeset, validações de CI/CD)
- Tempo investido na criação de ferramentas próprias vs usar solução pronta (como Nx)
⚠️ Publicação independente
- Cada pacote precisa ser versionado e publicado separadamente
- Gerenciamento de changelogs por pacote
- Coordenação de releases entre pacotes com dependências entre si
2. 🔍 Soluções Avaliadas
Opção 1: Nx Monorepo
Ferramentas: Nx CLI + Nx Workspace
Vantagens
- ✅ Generators nativos: Sistema de scaffolding robusto e extensível
- ✅ Nx Release: Comando nativo
nx releasepara versionamento e changelog - ✅ Publicação inteligente: Detecta automaticamente pacotes alterados
- ✅ Gerenciamento de dependências: Força consistência de versões
- ✅ Compiladores agnósticos: Flexibilidade para escolher TypeScript, Webpack, etc.
- ✅ Cache distribuído: Build cache para acelerar CI/CD
- ✅ Dependency graph: Visualização de dependências entre pacotes
Desvantagens
- ❌ Overhead de dependências e configuração
- ❌ Complexidade adicional para times pequenos
- ❌ Curva de aprendizado mais íngreme
Opção 2: Gerenciamento Manual + Changesets (Escolhida ✅)
Ferramentas: npm workspaces + Changesets + Scripts customizados
Vantagens
- ✅ Leveza: Apenas
devDependenciesnecessárias - ✅ Simplicidade: Menos abstrações, mais controle
- ✅ Changesets: Versionamento semântico e changelog automático
- ✅ Flexibilidade: Scripts customizados para necessidades específicas
- ✅ Transparência: Fácil entender o que está acontecendo
- ✅ Manutenibilidade: Menor dependência de ferramentas externas
Desvantagens
- ⚠️ Necessidade de criar tooling próprio (scripts de scaffolding)
- ⚠️ Sem cache de build nativo
- ⚠️ Menos recursos "out of the box"
3. ✅ Solução Adotada
Decisão Final: Gerenciamento Manual com Changesets
A equipe optou por uma solução leve e pragmática, utilizando:
- npm workspaces para gerenciamento de múltiplos pacotes
- Changesets para versionamento semântico e changelogs
- Scripts customizados para scaffolding e automações
- GitHub Actions para CI/CD e publicação automática
Justificativa
- ✅ Simplicidade: Menor overhead para o time
- ✅ Performance: Apenas dependências essenciais no projeto
- ✅ Controle: Scripts customizados atendem perfeitamente às necessidades
- ✅ Escalabilidade: Fácil adicionar novos pacotes via CLI próprio
- ✅ Manutenibilidade: Fácil de entender e modificar
Tooling Adicional Criado
Como optamos por não usar Nx, foi necessário criar ferramentas próprias para suprir as funcionalidades essenciais:
| Ferramenta | Arquivo | Função |
|---|---|---|
| 🎯 CLI de Scaffolding | tools/create-package.ts |
Cria novos pacotes com estrutura completa (substitui nx generate) |
| 📋 Auto Changeset | tools/create-auto-changeset.ts |
Gera changesets automaticamente baseado em git diff |
| ✅ Validação de Changeset | tools/check-changeset-exists.ts |
Valida presença de changeset em PRs |
| 🚀 Commit Changeset | tools/commit-and-push-changeset.ts |
Automatiza commit e push de changesets |
| 📦 Scripts de Build | package.json (root) |
Scripts globais para build/test de todos os pacotes |
Trade-off aceito: Investir tempo criando essas ferramentas nos deu controle total e uma solução muito mais leve que frameworks completos.
4. 🏗️ Arquitetura do Repositório
Visão Geral
finopping-core-services/
│
├── packages/ # Pacotes npm publicáveis
│ └── example-package/ # Template/exemplo
│
├── tools/ # Scripts de automação
│ ├── create-package.ts # CLI para criar novos pacotes
│ ├── create-auto-changeset.ts # Geração automática de changesets
│ ├── commit-and-push-changeset.ts
│ └── check-changeset-exists.ts
│
├── fragments/ # Changesets pendentes
│
├── Configurações raiz
│ ├── package.json # Workspace root + scripts globais
│ ├── tsconfig.base.json # Config TypeScript compartilhada
│ ├── eslint.config.mjs # Linting compartilhado
│ ├── jest.config.ts # Testes compartilhados
│ └── .nvmrc # Node version (24)
│
└── Documentação
├── README.md # Guia principal
└── JSDOC.md # Padrões de documentação
Princípios Arquiteturais
- Independência: Cada pacote é autônomo e publicável
- Compartilhamento: Configurações comuns na raiz
- Automatização: Scripts para tarefas repetitivas
- Qualidade: Linting, testes e formatação obrigatórios
- Versionamento: Changesets para releases controlados
5. 🚀 Atividades Realizadas
Fase 1: Planejamento e Pesquisa
✅ Laboratórios e validações
- Testes com Nx e configurações de monorepo
- Validação do Changesets para versionamento
- Avaliação de estratégias de publicação (npm vs GitHub Packages)
- Criação de repositório de testes a partir do Alquimia Playground
✅ Análise de viabilidade
- Comparação Nx vs implementação manual
- Avaliação de impacto no workflow do time
- Definição de estratégia de publicação (individual vs completa)
Fase 2: Desenho e Arquitetura
✅ Definição da estrutura
- Criação do desenho de arquitetura do repositório
- Definição da estrutura de pastas para cada pacote
- Padronização de nomenclatura e convenções
✅ Configuração inicial
- Inicialização do projeto a partir do template Node Lib (Alquimia Playground)
- Configuração do workspace npm (
"workspaces": ["packages/*"]) - Setup de TypeScript com
tsconfig.base.jsoncompartilhado
Fase 3: Tooling e Automações
✅ Sistema de scaffolding
- Implementação do CLI
npm run new:packageemtools/create-package.ts - Geração automática de estrutura completa (src, testes, configs)
- Templates para
package.json,tsconfig.json,jest.config.ts
✅ Versionamento e changelog
- Configuração do Changesets (
@changesets/cli) - Scripts para criação, validação e commit de changesets
- Integração com Conventional Commits
✅ Qualidade de código
- ESLint 9 com TypeScript ESLint e flat config
- Prettier para formatação automática
- Lint-staged para pre-commit hooks com Husky
- Jest para testes unitários
Fase 4: CI/CD e Publicação
✅ GitHub Actions
- Workflow DevSecOps integrado via
grupoboticario/actions-devsecops-workflows - Pipeline automático em PRs e merges na
main - Publicação automática via Changesets
✅ Configuração de Registry
- Setup do GitHub Packages como registry NPM
- Configuração de token de publicação (PAT)
publishConfigem cadapackage.json
✅ Testes de publicação
- Validação completa de criação de pacotes
- Testes de importação de artefatos do GitHub Registry
- Validação de acesso e permissões
Fase 5: Documentação
✅ Documentação técnica
- README.md completo com guias de uso
- JSDOC.md para padrões de documentação inline
- Snippets VSCode para JSDoc
✅ Consolidação na organização
- Repositório configurado na Organization do Grupo Boticário
- Adequações para fluxos de deploy e publicações corporativas
- Alinhamento com padrões DevSecOps
6. 🔄 Fluxo de Trabalho
1️⃣ Criar Novo Pacote
# Via script de scaffolding
npm run new:package nome-do-pacote "Descrição do pacote"
O que acontece:
- Validação do nome do pacote
- Criação da estrutura completa em
packages/nome-do-pacote/ - Geração de
package.jsoncom escopo@grupoboticario - Setup de TypeScript, Jest e README
- Instalação de dependências
2️⃣ Desenvolver Features
cd packages/nome-do-pacote
# Desenvolvimento
npm run build # Compila TypeScript
npm run test # Roda testes
npm run test:watch # Modo watch
npm run lint # Verifica código
npm run lint:fix # Corrige problemas
3️⃣ Commit e Push
git add .
git commit -m "feat(email-validator): adiciona validação de domínio"
git push origin feature/nova-feature
Hooks automáticos (Husky + Lint-staged):
- ESLint fix automático
- Prettier format automático
- Validação de changeset em branches
4️⃣ Pull Request
- Abrir PR no GitHub
- CI/CD roda automaticamente:
- ✅ Lint
- ✅ Testes
- ✅ Build
- ✅ DevSecOps checks
- Code review
- Merge na
main
5️⃣ Release e Publicação
Automático (CI/CD):
- Merge na
main→ Changesets detecta mudanças - Atualiza versões automaticamente
- Publica no GitHub Packages
7. 🛠️ Tooling e Automações
Script: create-package.ts
Localização: tools/create-package.ts
Funcionalidades:
- ✅ Validação de nome (lowercase, hífens)
- ✅ Verificação de duplicatas
- ✅ Geração de estrutura completa
- ✅ Templates personalizados
- ✅ Instalação de dependências
- ✅ Feedback visual com Chalk
Uso:
npm run new:package meu-pacote "Descrição"
Template gerado:
package.jsoncom escopo@grupoboticariotsconfig.jsonestendendo configuração basejest.config.tscom preset ESMsrc/index.tsesrc/index.spec.tsREADME.mdcompleto
Scripts de Changeset
1. create-auto-changeset.ts
- Detecta pacotes modificados via
git diff - Determina tipo de bump (major/minor/patch) via commits
- Gera changeset automaticamente
2. check-changeset-exists.ts
- Valida se há changeset em branches de feature
- Usado no CI/CD para garantir versionamento
3. commit-and-push-changeset.ts
- Commita e faz push de changesets criados
- Útil para automações
Husky + Lint-staged
.husky/pre-commit:
npx lint-staged
lint-staged (package.json):
{
"lint-staged": {
"*.{js,mjs,ts}": ["eslint --fix", "prettier --write"],
"*.{json,md}": ["prettier --write"]
}
}
Resultado: Código sempre formatado e lintado antes de commit!
8. 📦 Publicação e Deploy
Registry: GitHub Packages
Configuração:
"publishConfig": {
"registry": "https://npm.pkg.github.com",
"access": "public"
}
Autenticação
Personal Access Token (PAT):
- GitHub → Settings → Developer settings → Personal access tokens
- Criar token com escopo
write:packages - Configurar no
.npmrc:
//npm.pkg.github.com/:_authToken=TOKEN_AQUI
@grupoboticario:registry=https://npm.pkg.github.com
CI/CD Workflow
O workflow inclui:
- ✅ Lint e formatação
- ✅ Testes unitários
- ✅ Build de todos os pacotes
- ✅ Security scanning
- ✅ Publicação automática (via Changesets)
Consumo de Pacotes
Instalação:
npm install @grupoboticario/email-validator
Exemplo de uso:
import { validateEmail } from "@grupoboticario/email-validator";
const isValid = validateEmail("user@example.com");
9. 💡 Lições Aprendidas
✅ O que funcionou bem
- Changesets: Excelente para versionamento semântico e changelogs
- npm workspaces: Simples e eficiente para monorepo
- Script de scaffolding: Acelerou muito a criação de novos pacotes
- ESLint flat config: Moderno e mais flexível
- GitHub Packages: Integração perfeita com a organização
⚠️ Desafios enfrentados
- ESM vs CommonJS: Configuração de Jest com ESM requer atenção
- Changesets em CI: Automação de versionamento precisa de testes
- Permissões GitHub: Setup de PAT para publicação requer cuidado
- Documentação: Manter docs sincronizadas com código
🎯 Recomendações
- Mantenha pacotes pequenos
- Use changesets religiosamente
- Documente inline (JSDoc)
- Teste antes de publicar
- Versione com cuidado
📚 Referências
📝 Metadados
Documento criado: Fevereiro 2026
Última atualização: Fevereiro 2026
Autor: Time de Finops (903)
Versão: 1.0.0
Status: ✅ Concluído
🎉 Monorepo Finopping Core Services - Pronto para escalar!