Skip to content

📚 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

  1. Análise de Viabilidade
  2. Soluções Avaliadas
  3. Solução Adotada
  4. Arquitetura do Repositório
  5. Atividades Realizadas
  6. Fluxo de Trabalho
  7. Tooling e Automações
  8. Publicação e Deploy
  9. 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_modules na 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 release para 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 devDependencies necessá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:

  1. npm workspaces para gerenciamento de múltiplos pacotes
  2. Changesets para versionamento semântico e changelogs
  3. Scripts customizados para scaffolding e automações
  4. 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

  1. Independência: Cada pacote é autônomo e publicável
  2. Compartilhamento: Configurações comuns na raiz
  3. Automatização: Scripts para tarefas repetitivas
  4. Qualidade: Linting, testes e formatação obrigatórios
  5. 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.json compartilhado

Fase 3: Tooling e Automações

Sistema de scaffolding

  • Implementação do CLI npm run new:package em tools/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)
  • publishConfig em cada package.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:

  1. Validação do nome do pacote
  2. Criação da estrutura completa em packages/nome-do-pacote/
  3. Geração de package.json com escopo @grupoboticario
  4. Setup de TypeScript, Jest e README
  5. 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

  1. Abrir PR no GitHub
  2. CI/CD roda automaticamente:
  3. ✅ Lint
  4. ✅ Testes
  5. ✅ Build
  6. ✅ DevSecOps checks
  7. Code review
  8. 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.json com escopo @grupoboticario
  • tsconfig.json estendendo configuração base
  • jest.config.ts com preset ESM
  • src/index.ts e src/index.spec.ts
  • README.md completo

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):

  1. GitHub → Settings → Developer settings → Personal access tokens
  2. Criar token com escopo write:packages
  3. 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

  1. Changesets: Excelente para versionamento semântico e changelogs
  2. npm workspaces: Simples e eficiente para monorepo
  3. Script de scaffolding: Acelerou muito a criação de novos pacotes
  4. ESLint flat config: Moderno e mais flexível
  5. GitHub Packages: Integração perfeita com a organização

⚠️ Desafios enfrentados

  1. ESM vs CommonJS: Configuração de Jest com ESM requer atenção
  2. Changesets em CI: Automação de versionamento precisa de testes
  3. Permissões GitHub: Setup de PAT para publicação requer cuidado
  4. Documentação: Manter docs sincronizadas com código

🎯 Recomendações

  1. Mantenha pacotes pequenos
  2. Use changesets religiosamente
  3. Documente inline (JSDoc)
  4. Teste antes de publicar
  5. 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!