feat: complete Phase 1 foundation scaffold
Some checks failed
CI / Lint (push) Has been cancelled
CI / TypeCheck (push) Has been cancelled
CI / Test (push) Has been cancelled
Deploy / Docker Build & Push (map[context:. dockerfile:apps/api/Dockerfile name:api]) (push) Has been cancelled
Deploy / Docker Build & Push (map[context:. dockerfile:apps/cms/Dockerfile name:cms]) (push) Has been cancelled
Deploy / Docker Build & Push (map[context:. dockerfile:apps/web/Dockerfile name:web]) (push) Has been cancelled
CI / Build (push) Has been cancelled
Deploy / Deploy (push) Has been cancelled

- Monorepo: Turborepo + pnpm workspaces with 7 apps/packages
- Backend: NestJS scaffold with 9 modules (auth, tenant, curriculum, simulation, portfolio, ai-coach, analytics, classroom, gamification)
- Frontend: React 18 + Vite + TailwindCSS + shadcn/ui with 10 pages, 14 UI primitives, 3 Zustand stores
- Database: Prisma schema with 19 models, 13 enums, seed script, multi-tenant ready
- Docker: Dev, production, and Portainer Compose files with Traefik reverse proxy
- Configuration: .env.example (47 vars), Zod validation, frontend-safe env exposure
- i18n: English + Greek locale files (10 files), ICU MessageFormat, react-i18next
- Shared packages: @investplay/types, @investplay/ui, @investplay/i18n, @investplay/utils
- CI/CD: GitHub Actions (lint, typecheck, test, build, deploy, PR checks)
- Documentation: CONTEXT.md, ARCHITECTURE.md (10 Mermaid diagrams), API.md, LOCALIZATION.md, DEVELOPMENT-ROADMAP.md
- Infrastructure: Dockerfiles (dev + prod), nginx configs, backup/healthcheck scripts
- Security: JWT auth guards, role-based access, rate limiting, Helmet, CORS, PII sanitization
This commit is contained in:
Lefteris Notas
2026-06-12 19:32:57 +03:00
parent fa71c60cfc
commit e75f913f1c
226 changed files with 17547 additions and 0 deletions

121
scripts/healthcheck.sh Normal file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/env bash
set -euo pipefail
# ─── Color output ──────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*"; }
header() { echo -e "\n${YELLOW}─── $* ───${NC}"; }
EXIT_CODE=0
# ─── Docker service health ──────────────────────────────────────
header "Docker Container Status"
containers=$(docker ps --format "{{.Names}}" 2>/dev/null || true)
if [ -z "${containers}" ]; then
warn "No running Docker containers found"
else
while IFS= read -r name; do
status=$(docker inspect --format='{{.State.Status}}' "${name}" 2>/dev/null || echo "unknown")
health=$(docker inspect --format='{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "${name}" 2>/dev/null || echo "none")
if [ "${status}" = "running" ]; then
if [ "${health}" = "healthy" ]; then
ok "${name} — running, healthy"
elif [ "${health}" = "unhealthy" ]; then
error "${name} — running but UNHEALTHY"
EXIT_CODE=1
else
warn "${name} — running (no health check)"
fi
else
error "${name}${status}"
EXIT_CODE=1
fi
done <<< "${containers}"
fi
# ─── HTTP health endpoints ───────────────────────────────────────
header "HTTP Health Endpoints"
check_endpoint() {
local name="$1"
local url="$2"
local expected_code="${3:-200}"
if command -v curl &>/dev/null; then
http_code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "${url}" 2>/dev/null || echo "000")
elif command -v wget &>/dev/null; then
http_code=$(wget --server-response --spider --timeout=5 "${url}" 2>&1 | awk '/HTTP\/1.1/{print $2}' | tail -1 || echo "000")
else
warn "Neither curl nor wget available — skipping HTTP checks"
return
fi
if [ "${http_code}" = "${expected_code}" ] || [ "${http_code}" = "000" ]; then
if [ "${http_code}" = "000" ]; then
warn "${name} — could not connect to ${url}"
else
ok "${name}${url} returned ${http_code}"
fi
else
error "${name}${url} returned ${http_code} (expected ${expected_code})"
EXIT_CODE=1
fi
}
check_endpoint "API" "http://localhost:3001/health"
check_endpoint "Web" "http://localhost:80/"
check_endpoint "CMS" "http://localhost:3000/health"
check_endpoint "MinIO (API)" "http://localhost:9000/minio/health/live"
check_endpoint "MinIO (Console)" "http://localhost:9001/"
# ─── Port check ─────────────────────────────────────────────────
header "Port Availability"
check_port() {
local name="$1"
local port="$2"
if command -v nc &>/dev/null; then
if nc -z localhost "${port}" 2>/dev/null; then
ok "${name} — port ${port} is open"
else
error "${name} — port ${port} is CLOSED"
EXIT_CODE=1
fi
else
# Fallback: try connecting with /dev/tcp (bash built-in)
if timeout 1 bash -c "echo >/dev/tcp/localhost/${port}" 2>/dev/null; then
ok "${name} — port ${port} is open"
else
error "${name} — port ${port} is CLOSED"
EXIT_CODE=1
fi
fi
}
check_port "PostgreSQL" 5432
check_port "Redis" 6379
# ─── Summary ────────────────────────────────────────────────────
echo ""
if [ "${EXIT_CODE}" -eq 0 ]; then
echo -e "${GREEN}══════════════════════════════════════════════════════════${NC}"
echo -e "${GREEN} All services are healthy!${NC}"
echo -e "${GREEN}══════════════════════════════════════════════════════════${NC}"
else
echo -e "${RED}══════════════════════════════════════════════════════════${NC}"
echo -e "${RED} Some services have issues (exit code: ${EXIT_CODE})${NC}"
echo -e "${RED}══════════════════════════════════════════════════════════${NC}"
fi
exit "${EXIT_CODE}"