saveinmed/start.sh
Tiago Yamamoto aaa304c256 feat: add test/coverage and build verification options to start.sh
- Option 7: Run tests with coverage (go test + vitest)
- Option 8: Verify build for backend, marketplace, and backoffice
- Also accessible via --test/-t and --build/-B CLI flags
2025-12-26 22:39:53 -03:00

582 lines
18 KiB
Bash
Executable file

#!/bin/bash
# SaveInMed Development Startup Script
# Permite iniciar um ou mais serviços do projeto
# Cores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Diretório raiz do projeto
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Função para exibir o banner
show_banner() {
echo -e "${CYAN}"
echo "╔══════════════════════════════════════════════════╗"
echo "║ ║"
echo "║ ███████ █████ ██ ██ ███████ ██ ███ ██ ║"
echo "║ ██ ██ ██ ██ ██ ██ ██ ████ ██ ║"
echo "║ ███████ ███████ ██ ██ █████ ██ ██ ██ ██ ║"
echo "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ║"
echo "║ ███████ ██ ██ ████ ███████ ██ ██ ████ ║"
echo "║ ║"
echo "║ ███ ███ ███████ ██████ ║"
echo "║ ████ ████ ██ ██ ██ ║"
echo "║ ██ ████ ██ █████ ██ ██ ║"
echo "║ ██ ██ ██ ██ ██ ██ ║"
echo "║ ██ ██ ███████ ██████ ║"
echo "║ ║"
echo "║ Development Startup Script ║"
echo "║ ║"
echo "╚══════════════════════════════════════════════════╝"
echo -e "${NC}"
}
# Função para verificar dependências
check_dependency() {
local cmd=$1
local name=$2
if command -v "$cmd" &> /dev/null; then
echo -e " ${GREEN}${NC} $name"
return 0
else
echo -e " ${RED}${NC} $name (não instalado)"
return 1
fi
}
# Função para instalar Go
install_go() {
echo -e "${YELLOW}📦 Instalando Go...${NC}"
curl -fsSL https://go.dev/dl/go1.24.3.linux-amd64.tar.gz -o /tmp/go.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf /tmp/go.tar.gz
export PATH=$PATH:/usr/local/go/bin
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.zshrc
rm /tmp/go.tar.gz
echo -e "${GREEN}✓ Go instalado com sucesso${NC}"
}
# Função para instalar Node.js
install_node() {
echo -e "${YELLOW}📦 Instalando Node.js...${NC}"
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
echo -e "${GREEN}✓ Node.js instalado com sucesso${NC}"
}
# Função para instalar pnpm
install_pnpm() {
echo -e "${YELLOW}📦 Instalando pnpm...${NC}"
npm install -g pnpm
echo -e "${GREEN}✓ pnpm instalado com sucesso${NC}"
}
# Função para instalar Deno
install_deno() {
echo -e "${YELLOW}📦 Instalando Deno...${NC}"
curl -fsSL https://deno.land/install.sh | sh
export DENO_INSTALL="$HOME/.deno"
export PATH="$DENO_INSTALL/bin:$PATH"
echo 'export DENO_INSTALL="$HOME/.deno"' >> ~/.zshrc
echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.zshrc
echo -e "${GREEN}✓ Deno instalado com sucesso${NC}"
}
# Função para instalar tmux
install_tmux() {
echo -e "${YELLOW}📦 Instalando tmux...${NC}"
sudo apt-get update && sudo apt-get install -y tmux
echo -e "${GREEN}✓ tmux instalado com sucesso${NC}"
}
# Função para verificar e instalar dependência
ensure_dependency() {
local cmd=$1
local name=$2
local install_func=$3
if ! command -v "$cmd" &> /dev/null; then
echo -e "${RED}$name não está instalado${NC}"
read -p "Deseja instalar $name agora? (s/n): " install_choice
if [[ "$install_choice" =~ ^[Ss]$ ]]; then
$install_func
return 0
else
echo -e "${RED}Não é possível continuar sem $name${NC}"
return 1
fi
fi
return 0
}
# Função para iniciar o Backend Go
start_backend() {
echo -e "\n${BLUE}🚀 Iniciando Backend Go...${NC}"
# Verificar/instalar Go
ensure_dependency "go" "Go" "install_go" || return 1
cd "$PROJECT_ROOT/backend"
# Carregar variáveis de ambiente se existir .env
if [ -f ".env" ]; then
echo -e "${GREEN} ✓ Carregando variáveis de .env${NC}"
set -a
source .env
set +a
else
echo -e "${YELLOW} ⚠ Arquivo .env não encontrado, usando valores padrão${NC}"
fi
# Baixar dependências se necessário
if [ ! -f "go.sum" ]; then
echo -e "${YELLOW} 📦 Baixando dependências Go...${NC}"
go mod download
fi
echo -e "${GREEN} ▶ Executando: go run ./cmd/api${NC}"
echo -e "${CYAN} 📍 API disponível em: http://localhost:${PORT:-8214}${NC}"
echo -e "${CYAN} 📚 Swagger UI: http://localhost:${PORT:-8214}/swagger/index.html${NC}\n"
go run ./cmd/api
}
# Função para iniciar o Backoffice NestJS
start_backoffice() {
echo -e "\n${PURPLE}🚀 Iniciando Backoffice NestJS...${NC}"
# Verificar/instalar Node.js
ensure_dependency "node" "Node.js" "install_node" || return 1
# Verificar/instalar pnpm
if ! command -v pnpm &> /dev/null; then
read -p "pnpm não encontrado. Deseja instalar? (s/n): " install_choice
if [[ "$install_choice" =~ ^[Ss]$ ]]; then
install_pnpm
fi
fi
cd "$PROJECT_ROOT/backoffice"
# Determinar gerenciador de pacotes (pnpm ou npm)
if command -v pnpm &> /dev/null; then
PKG_MANAGER="pnpm"
else
PKG_MANAGER="npm"
echo -e "${YELLOW} ⚠ pnpm não encontrado, usando npm${NC}"
fi
# Instalar dependências se necessário
if [ ! -d "node_modules" ]; then
echo -e "${YELLOW} 📦 Instalando dependências...${NC}"
$PKG_MANAGER install
fi
# Gerar Prisma client
if [ -f "prisma/schema.prisma" ]; then
echo -e "${YELLOW} 🔧 Gerando Prisma client...${NC}"
$PKG_MANAGER run prisma:generate 2>/dev/null || npx prisma generate
fi
echo -e "${GREEN} ▶ Executando: $PKG_MANAGER run start:dev${NC}"
echo -e "${CYAN} 📍 Backoffice disponível em: http://localhost:3000${NC}"
echo -e "${CYAN} 📚 Swagger: http://localhost:3000/api${NC}\n"
$PKG_MANAGER run start:dev
}
# Função para iniciar o Marketplace React
start_marketplace() {
echo -e "\n${BLUE}🚀 Iniciando Marketplace React...${NC}"
# Verificar/instalar Node.js
ensure_dependency "node" "Node.js" "install_node" || return 1
cd "$PROJECT_ROOT/marketplace"
# Instalar dependências se necessário
if [ ! -d "node_modules" ]; then
echo -e "${YELLOW} 📦 Instalando dependências...${NC}"
npm install
fi
echo -e "${GREEN} ▶ Executando: npm run dev${NC}"
echo -e "${CYAN} 📍 Marketplace disponível em: http://localhost:5173${NC}\n"
npm run dev
}
# Função para iniciar o Website Fresh/Deno
start_website() {
echo -e "\n${GREEN}🚀 Iniciando Website (Fresh/Deno)...${NC}"
# Verificar/instalar Deno
ensure_dependency "deno" "Deno" "install_deno" || return 1
cd "$PROJECT_ROOT/website"
echo -e "${GREEN} ▶ Executando: deno task dev${NC}"
echo -e "${CYAN} 📍 Website disponível em: http://localhost:8000${NC}\n"
deno task dev
}
# Função para resetar e popular o banco de dados
reset_db() {
echo -e "\n${RED}⚠️ ATENÇÃO: Isso irá apagar todo o banco de dados e recriá-lo!${NC}"
echo -e "${YELLOW} Isso inclui: companies, users, products, orders, etc.${NC}"
# Se não for chamado via flag (automático), pede confirmação
if [ "$1" != "--force" ]; then
read -p " Deseja continuar? (s/n): " confirm
if [[ ! "$confirm" =~ ^[Ss]$ ]]; then
echo -e "${YELLOW}Operação cancelada.${NC}"
return 0
fi
fi
echo -e "\n${BLUE}🚜 Iniciando Seeder API...${NC}"
# Verificar/instalar Go
ensure_dependency "go" "Go" "install_go" || return 1
cd "$PROJECT_ROOT/seeder-api"
# Carregar variáveis de ambiente
if [ -f "../backend/.env" ]; then
set -a
source ../backend/.env
set +a
fi
# Usar porta diferente para evitar conflito se o seeder tiver padrão diferente
# O seeder usa PORT env var. Vamos definir uma temporária se não estiver definida
export PORT=${PORT:-8216}
# Iniciar seeder em background
echo -e "${YELLOW} ⏳ Aguardando Seeder API iniciar na porta $PORT...${NC}"
go run main.go &
SEEDER_PID=$!
# Aguardar serviço estar pronto
max_retries=30
count=0
while ! curl -s "http://localhost:$PORT/swagger.json" > /dev/null; do
sleep 1
count=$((count+1))
if [ $count -ge $max_retries ]; then
echo -e "${RED}❌ Timeout aguardando Seeder API${NC}"
kill $SEEDER_PID 2>/dev/null
return 1
fi
echo -n "."
done
echo ""
echo -e "${GREEN} ✓ Seeder API online!${NC}"
echo -e "${YELLOW} 🌱 Executando seed (mode=lean)...${NC}"
# Executar seed
HTTP_CODE=$(curl -s -o /tmp/seed_output.json -w "%{http_code}" -X POST "http://localhost:$PORT/seed?mode=lean")
if [ "$HTTP_CODE" == "200" ]; then
echo -e "${GREEN} ✅ Banco de dados resetado e populado com sucesso!${NC}"
cat /tmp/seed_output.json
echo ""
else
echo -e "${RED} ❌ Falha ao rodar seed. Código HTTP: $HTTP_CODE${NC}"
cat /tmp/seed_output.json
echo ""
fi
# Matar seeder
echo -e "${BLUE} 🛑 Parando Seeder API...${NC}"
kill $SEEDER_PID 2>/dev/null
wait $SEEDER_PID 2>/dev/null
echo -e "${GREEN}✨ Concluído!${NC}\n"
}
# Função para rodar testes e exibir cobertura
run_tests() {
echo -e "\n${BLUE}🧪 Executando Testes...${NC}\n"
# Backend Go Tests
echo -e "${CYAN}━━━ Backend Go ━━━${NC}"
cd "$PROJECT_ROOT/backend"
if [ -f ".env" ]; then
set -a
source .env
set +a
fi
echo -e "${YELLOW} ⏳ Executando go test com cobertura...${NC}"
go test -coverprofile=coverage.out ./... 2>&1
BACKEND_EXIT=$?
if [ $BACKEND_EXIT -eq 0 ]; then
echo -e "${GREEN} ✓ Testes do backend passaram!${NC}"
echo -e "${CYAN} 📊 Cobertura:${NC}"
go tool cover -func=coverage.out | tail -1
echo -e "\n${YELLOW} 💡 Para ver cobertura detalhada: cd backend && go tool cover -html=coverage.out${NC}"
else
echo -e "${RED} ✗ Alguns testes falharam${NC}"
fi
echo ""
# Marketplace Tests
echo -e "${CYAN}━━━ Marketplace React ━━━${NC}"
cd "$PROJECT_ROOT/marketplace"
if [ -d "node_modules" ]; then
echo -e "${YELLOW} ⏳ Executando vitest...${NC}"
npm run test -- --coverage --run 2>&1
MARKET_EXIT=$?
if [ $MARKET_EXIT -eq 0 ]; then
echo -e "${GREEN} ✓ Testes do marketplace passaram!${NC}"
else
echo -e "${RED} ✗ Alguns testes falharam${NC}"
fi
else
echo -e "${YELLOW} ⚠ node_modules não encontrado. Execute: npm install${NC}"
fi
echo -e "\n${GREEN}✨ Testes concluídos!${NC}\n"
}
# Função para verificar build de todos os projetos
run_build_check() {
echo -e "\n${BLUE}🔨 Verificando Build...${NC}\n"
ALL_OK=true
# Backend Go Build
echo -e "${CYAN}━━━ Backend Go ━━━${NC}"
cd "$PROJECT_ROOT/backend"
echo -e "${YELLOW} ⏳ go build ./...${NC}"
if go build ./... 2>&1; then
echo -e "${GREEN} ✓ Build OK${NC}"
else
echo -e "${RED} ✗ Build falhou${NC}"
ALL_OK=false
fi
echo ""
# Marketplace Build
echo -e "${CYAN}━━━ Marketplace React ━━━${NC}"
cd "$PROJECT_ROOT/marketplace"
if [ -d "node_modules" ]; then
echo -e "${YELLOW} ⏳ npm run build${NC}"
if npm run build 2>&1; then
echo -e "${GREEN} ✓ Build OK${NC}"
else
echo -e "${RED} ✗ Build falhou${NC}"
ALL_OK=false
fi
else
echo -e "${YELLOW} ⚠ node_modules não encontrado. Execute: npm install${NC}"
fi
echo ""
# Backoffice Build (if exists)
if [ -d "$PROJECT_ROOT/backoffice" ]; then
echo -e "${CYAN}━━━ Backoffice NestJS ━━━${NC}"
cd "$PROJECT_ROOT/backoffice"
if [ -d "node_modules" ]; then
PKG_MANAGER="npm"
command -v pnpm &>/dev/null && PKG_MANAGER="pnpm"
echo -e "${YELLOW}$PKG_MANAGER run build${NC}"
if $PKG_MANAGER run build 2>&1; then
echo -e "${GREEN} ✓ Build OK${NC}"
else
echo -e "${RED} ✗ Build falhou${NC}"
ALL_OK=false
fi
else
echo -e "${YELLOW} ⚠ node_modules não encontrado${NC}"
fi
echo ""
fi
if [ "$ALL_OK" = true ]; then
echo -e "${GREEN}✨ Todos os builds passaram!${NC}\n"
else
echo -e "${RED}❌ Alguns builds falharam. Verifique os erros acima.${NC}\n"
fi
}
# Função para exibir o menu
show_menu() {
echo -e "\n${YELLOW}Selecione o serviço para iniciar:${NC}\n"
echo -e " ${BLUE}1)${NC} Backend Go ${CYAN}(porta 8214)${NC}"
echo -e " ${BLUE}2)${NC} Backoffice NestJS ${CYAN}(porta 3000)${NC}"
echo -e " ${BLUE}3)${NC} Marketplace React ${CYAN}(porta 5173)${NC}"
echo -e " ${BLUE}4)${NC} Website Fresh/Deno ${CYAN}(porta 8000)${NC}"
echo -e ""
echo -e " ${GREEN}5)${NC} Iniciar Todos os Serviços"
echo -e ""
echo -e " ${PURPLE}6)${NC} Resetar DB (Seed) ${RED}(Destrutivo)${NC}"
echo -e " ${YELLOW}7)${NC} Rodar Testes ${CYAN}(com cobertura)${NC}"
echo -e " ${YELLOW}8)${NC} Verificar Build ${CYAN}(frontend + backend)${NC}"
echo -e ""
echo -e " ${RED}0)${NC} Sair"
echo -e ""
}
# Função para iniciar todos os serviços em terminais separados
start_all_services() {
echo -e "\n${GREEN}🚀 Iniciando todos os serviços...${NC}\n"
# Verificar/instalar tmux
ensure_dependency "tmux" "tmux" "install_tmux" || return 1
# Matar sessão anterior se existir
tmux kill-session -t saveinmed 2>/dev/null || true
tmux new-session -d -s saveinmed -n backend "cd $PROJECT_ROOT && ./start.sh --backend"
tmux new-window -t saveinmed -n backoffice "cd $PROJECT_ROOT && ./start.sh --backoffice"
tmux new-window -t saveinmed -n marketplace "cd $PROJECT_ROOT && ./start.sh --marketplace"
tmux new-window -t saveinmed -n website "cd $PROJECT_ROOT && ./start.sh --website"
echo -e "${GREEN}✓ Serviços iniciados em sessão tmux 'saveinmed'${NC}"
echo -e "${CYAN} Use 'tmux attach -t saveinmed' para acessar${NC}"
echo -e "${CYAN} Use Ctrl+B + número para trocar de janela${NC}\n"
tmux attach -t saveinmed
}
# Processar argumentos de linha de comando
if [ $# -gt 0 ]; then
case "$1" in
--backend|-b|1)
start_backend
exit 0
;;
--backoffice|-o|2)
start_backoffice
exit 0
;;
--marketplace|-m|3)
start_marketplace
exit 0
;;
--website|-w|4)
start_website
exit 0
;;
--seed|-s|6)
reset_db "--force"
exit 0
;;
--all|-a|5)
show_banner
start_all_services
exit 0
;;
--test|-t|7)
show_banner
run_tests
exit 0
;;
--build|-B|8)
show_banner
run_build_check
exit 0
;;
--help|-h)
show_banner
echo "Uso: $0 [OPÇÃO]"
echo ""
echo "Opções:"
echo " --backend, -b, 1 Iniciar Backend Go (porta 8214)"
echo " --backoffice, -o, 2 Iniciar Backoffice NestJS (porta 3000)"
echo " --marketplace, -m, 3 Iniciar Marketplace React (porta 5173)"
echo " --website, -w, 4 Iniciar Website Deno (porta 8000)"
echo " --seed, -s, 6 Resetar DB e rodar Seed (com --force)"
echo " --all, -a, 5 Iniciar todos os serviços"
echo " --test, -t, 7 Rodar testes com cobertura"
echo " --build, -B, 8 Verificar build de todos os projetos"
echo " --help, -h Mostrar esta ajuda"
echo ""
exit 0
;;
*)
echo -e "${RED}Opção inválida: $1${NC}"
echo "Use --help para ver as opções disponíveis"
exit 1
;;
esac
fi
# Menu interativo
show_banner
echo -e "${YELLOW}Verificando dependências...${NC}"
echo ""
check_dependency "go" "Go"
check_dependency "node" "Node.js"
check_dependency "npm" "npm"
check_dependency "pnpm" "pnpm (opcional, usa npm como fallback)"
check_dependency "deno" "Deno"
check_dependency "tmux" "tmux (para iniciar todos)"
echo ""
while true; do
show_menu
read -p "Opção: " choice
case $choice in
1)
start_backend
break
;;
2)
start_backoffice
break
;;
3)
start_marketplace
break
;;
4)
start_website
break
;;
6)
reset_db
break
;;
7)
run_tests
break
;;
8)
run_build_check
break
;;
5)
start_all_services
break
;;
0)
echo -e "\n${GREEN}👋 Até logo!${NC}\n"
exit 0
;;
*)
echo -e "${RED}Opção inválida. Tente novamente.${NC}"
;;
esac
done