From 8518dade34d4027cf5733e82de8ee8f3dcbafddd Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Sat, 17 Jan 2026 21:33:42 +0700 Subject: [PATCH] feat: Add polyglot support to dev and build scripts for Node.js and .NET services. --- scripts/build/build-all.sh | 64 ++++++++++++++++++++++++++++++- scripts/build/build-service.sh | 59 ++++++++++++++++++++++++---- scripts/dev/start-all.sh | 26 +++++++------ scripts/dev/start-service.sh | 70 ++++++++++++++++++++++++++++++++-- 4 files changed, 196 insertions(+), 23 deletions(-) diff --git a/scripts/build/build-all.sh b/scripts/build/build-all.sh index 80d0768c..f561f02c 100755 --- a/scripts/build/build-all.sh +++ b/scripts/build/build-all.sh @@ -1,11 +1,73 @@ #!/bin/bash +# ============================================================================= +# Build All Services (Polyglot: Node.js & .NET) +# ============================================================================= + set -e +source "$(dirname "$0")/../utils/os-helper.sh" + echo "🔨 Building all services and apps..." +# ----------------------------------------------------------------------------- +# 1. Build Node.js / TypeScript Projects (pnpm workspace) +# ----------------------------------------------------------------------------- +echo "📦 Building Node.js packages..." # EN: Build all packages using pnpm workspace # VI: Build tất cả các package sử dụng pnpm workspace -pnpm build +if command -v pnpm &> /dev/null; then + pnpm build +else + echo "⚠️ pnpm not found. Skipping Node.js build." +fi + +# ----------------------------------------------------------------------------- +# 2. Build .NET Services +# ----------------------------------------------------------------------------- +echo "📦 Building .NET services..." + +if command -v dotnet &> /dev/null; then + # Find all directories in services/ that contain a .sln or .csproj file + # and do NOT contain a package.json (or we can build both if mixed) + + count=0 + + # EN: Iterate over direct subdirectories of services/ + # VI: Duyệt qua các thư mục con trực tiếp của services/ + for service_dir in services/*; do + if [ -d "$service_dir" ]; then + # Check for .NET solution or project files + if compgen -G "$service_dir/*.sln" > /dev/null || compgen -G "$service_dir/*.csproj" > /dev/null || compgen -G "$service_dir/src/*.sln" > /dev/null; then + service_name=$(basename "$service_dir") + + # Optimization: specific check to avoid building node apps again if they were mixed (unlikely here but safety first) + # In this repo, .NET services don't have package.json usually. + + echo " 👉 Building .NET service: $service_name" + # Use dotnet build on the directory (it finds sln/csproj auto) or specific path + if compgen -G "$service_dir/*.sln" > /dev/null; then + dotnet build "$service_dir" -v m + elif [ -d "$service_dir/src" ]; then + # Common pattern: service/src/Service.sln + dotnet build "$service_dir/src" -v m + else + dotnet build "$service_dir" -v m + fi + + count=$((count + 1)) + fi + fi + done + + if [ "$count" -eq 0 ]; then + echo " (No .NET services found to build)" + else + echo " ✅ Built $count .NET services." + fi + +else + echo "⚠️ dotnet SDK not found. Skipping .NET build." +fi echo "✅ Build completed!" diff --git a/scripts/build/build-service.sh b/scripts/build/build-service.sh index bd60c7be..1aa94ef3 100755 --- a/scripts/build/build-service.sh +++ b/scripts/build/build-service.sh @@ -1,5 +1,9 @@ #!/bin/bash +# ============================================================================= +# Build Single Service (Polyglot) +# ============================================================================= + set -e SERVICE=$1 @@ -8,21 +12,62 @@ SERVICE=$1 # VI: Xác thực tham số if [ -z "$SERVICE" ]; then echo "Usage: $0 " - echo "Example: $0 auth-service" + echo "Example:" + echo " $0 auth-service (Node.js)" + echo " $0 mission-service-net (.NET)" exit 1 fi # EN: Check if service exists # VI: Kiểm tra xem service có tồn tại không -if [ ! -d "services/$SERVICE" ]; then - echo "❌ Service $SERVICE not found" +SERVICE_PATH="services/$SERVICE" +if [ ! -d "$SERVICE_PATH" ]; then + echo "❌ Service $SERVICE not found in services/" exit 1 fi echo "🔨 Building $SERVICE..." -# EN: Build specific service using pnpm filter -# VI: Build service cụ thể sử dụng pnpm filter -pnpm --filter "@goodgo/$SERVICE" build +# ----------------------------------------------------------------------------- +# Detect Project Type & Build +# ----------------------------------------------------------------------------- -echo "✅ Build completed!" +BUILT=false + +# 1. Check for Node.js (package.json) +if [ -f "$SERVICE_PATH/package.json" ]; then + echo " 📦 Detected Node.js project" + # EN: Build specific service using pnpm filter + # VI: Build service cụ thể sử dụng pnpm filter + if pnpm --filter "@goodgo/$SERVICE" build; then + BUILT=true + fi +fi + +# 2. Check for .NET (Solution or CSPROJ) +if [ -f "$SERVICE_PATH"/*.sln ] || compgen -G "$SERVICE_PATH/*.sln" > /dev/null || \ + [ -f "$SERVICE_PATH"/*.csproj ] || compgen -G "$SERVICE_PATH/src/*.sln" > /dev/null; then + + # If not already built (or if it's a mixed project, we might want to build both, + # but usually it's one or the other. Let's assume .NET if found). + # If we already built Node, we still try .NET just in case? + # Let's say yes for completeness, though rare. + + echo " 📦 Detected .NET project" + + TARGET_BUILD="$SERVICE_PATH" + if [ -d "$SERVICE_PATH/src" ] && compgen -G "$SERVICE_PATH/src/*.sln" > /dev/null; then + TARGET_BUILD="$SERVICE_PATH/src" + fi + + if dotnet build "$TARGET_BUILD"; then + BUILT=true + fi +fi + +if [ "$BUILT" = true ]; then + echo "✅ Build completed for $SERVICE!" +else + echo "❌ Could not determine how to build $SERVICE (no package.json or .sln/.csproj found)" + exit 1 +fi diff --git a/scripts/dev/start-all.sh b/scripts/dev/start-all.sh index c952e4f0..e066dcad 100755 --- a/scripts/dev/start-all.sh +++ b/scripts/dev/start-all.sh @@ -37,19 +37,23 @@ if [ -z "$DATABASE_URL" ]; then fi fi -# EN: Start infrastructure services (Redis for caching, Traefik for routing) -# VI: Khởi động infrastructure services (Redis cho caching, Traefik cho routing) -echo "📦 Starting infrastructure (Redis, Traefik)... / Khởi động infrastructure (Redis, Traefik)..." +# EN: Start infrastructure services and .NET backends +# VI: Khởi động infrastructure services và .NET backends +echo "📦 Starting Docker containers (Infra + .NET Services)..." cd deployments/local run_compose up -d cd ../.. -# EN: Give Redis time to fully start before starting services -# VI: Cho Redis thời gian để khởi động đầy đủ trước khi khởi động services -echo "⏳ Waiting for Redis to be ready... / Đang chờ Redis sẵn sàng..." -sleep 3 +# EN: Give Redis time to fully start +# VI: Cho Redis thời gian để khởi động đầy đủ +echo "⏳ Waiting for services to stabilize..." +sleep 5 -# EN: Start all microservices using pnpm dev -# VI: Khởi động tất cả microservices sử dụng pnpm dev -echo "🚀 Starting services... / Khởi động services..." -pnpm dev +# EN: Start Node.js apps/services using pnpm dev +# VI: Khởi động Node.js apps/services sử dụng pnpm dev +echo "🚀 Starting Node.js apps (Frontend/BFF)..." +if command -v pnpm &> /dev/null; then + pnpm dev +else + echo "⚠️ pnpm not found. Only Docker services are running." +fi diff --git a/scripts/dev/start-service.sh b/scripts/dev/start-service.sh index 98ff0350..42e57c6b 100755 --- a/scripts/dev/start-service.sh +++ b/scripts/dev/start-service.sh @@ -1,5 +1,9 @@ #!/bin/bash +# ============================================================================= +# Start Single Service (Polyglot) +# ============================================================================= + set -e SERVICE=$1 @@ -16,10 +20,68 @@ echo "🚀 Starting $SERVICE..." # EN: Check if service exists # VI: Kiểm tra xem service có tồn tại không -if [ ! -d "services/$SERVICE" ]; then - echo "❌ Service $SERVICE not found" +SERVICE_PATH="services/$SERVICE" +if [ ! -d "$SERVICE_PATH" ]; then + echo "❌ Service $SERVICE not found in services/" exit 1 fi -cd "services/$SERVICE" -pnpm dev +cd "$SERVICE_PATH" + +STARTED=false + +# 1. Check for Node.js (package.json) +if [ -f "package.json" ]; then + echo " 📦 Starting Node.js service..." + pnpm dev + STARTED=true +fi + +# 2. Check for .NET +# If it's a .NET service, we prefer `dotnet watch run` for hot reload +if [ -f *.sln ] || compgen -G "*.sln" > /dev/null || \ + [ -f *.csproj ] || compgen -G "src/*.sln" > /dev/null; then + + echo " 📦 Starting .NET service with Hot Reload..." + + # Needs env vars? Often yes. + # Load env vars from deployments/local/.env.local if not already set? + # Usually .NET appsettings.Development.json handles this, or we export from .env.local + + # Attempt to load .env.local from root + if [ -f "../../deployments/local/.env.local" ]; then + echo " ℹ️ Loading environment variables from deployments/local/.env.local" + export $(grep -v '^#' ../../deployments/local/.env.local | xargs) + fi + + TARGET_RUN="." + if [ -d "src" ] && compgen -G "src/*.sln" > /dev/null; then + # Usually we want to run the API project specifically, not the solution (dotnet run works on project, or solution if single run project) + # Finding the API project is tricky without hardcoding. + # Assume pattern: ServiceName.API or just src/ + + # Try to find a csproj in src that ends with API.csproj or Service.csproj + API_PROJECT=$(find src -name "*.API.csproj" | head -n 1) + if [ -z "$API_PROJECT" ]; then + API_PROJECT=$(find src -name "*.csproj" | grep -v "Domain" | grep -v "Infrastructure" | head -n 1) + fi + + if [ -n "$API_PROJECT" ]; then + # We need to run from the project directory or pass --project + TARGET_RUN="$API_PROJECT" + else + TARGET_RUN="src" + fi + elif [ -d "src" ]; then + TARGET_RUN="src" + fi + + echo " 👉 Running project: $TARGET_RUN" + dotnet watch run --project "$TARGET_RUN" + STARTED=true +fi + +if [ "$STARTED" = false ]; then + echo "❌ Could not determine how to start $SERVICE (no package.json or .sln found)" + exit 1 +fi