#!/usr/bin/env bash # Deploy iloom (backend services + frontend) in integrated mode against a running muyu-apiserver stack. # # Prerequisites: # - muyu-apiserver already running (cd ../muyu-apiserver/deploy && docker compose up -d) # - .env present in repo root (copy from .env.example and fill in secrets) # # Usage: ./scripts/deploy.sh [--no-mirror] # --no-mirror Build images against upstream registries (Docker Hub, proxy.golang.org, # official Alpine CDN) instead of the Harbor/Aliyun/goproxy.cn mirrors that # the Dockerfiles use by default. set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT_DIR" MUYU_NETWORK="deploy_default" MUYU_MYSQL_CONTAINER="muyu-mysql" SERVICES=(gateway auth-service purchaser-service textile-service washing-service frontend) COMPOSE_FILE="docker-compose.integrated.yml" NO_MIRROR=false for arg in "$@"; do case "$arg" in --no-mirror) NO_MIRROR=true ;; *) ;; esac done log() { printf '\n==> %s\n' "$1"; } die() { printf '\nERROR: %s\n' "$1" >&2; exit 1; } [ -f .env ] || die ".env not found in $ROOT_DIR. Copy .env.example to .env and fill in real values first." while IFS='=' read -r key value; do [[ -z "$key" || "$key" == \#* ]] && continue export "$key=$value" done < <(grep -v '^\s*#' .env | grep '=') [ -n "${DB_DSN:-}" ] || die "DB_DSN is not set in .env" [ -n "${JWT_SECRET:-}" ] || die "JWT_SECRET is not set in .env" [ -n "${JWT_REFRESH_SECRET:-}" ] || die "JWT_REFRESH_SECRET is not set in .env" [ -n "${INTERNAL_SERVICE_KEY:-}" ] || die "INTERNAL_SERVICE_KEY is not set in .env" if [ "$NO_MIRROR" = true ]; then log "Disabling build mirrors (--no-mirror): using upstream registries" export BASE_REGISTRY="" export GOPROXY="https://proxy.golang.org,direct" export APK_MIRROR="" fi log "Checking muyu-apiserver dependencies" docker network inspect "$MUYU_NETWORK" >/dev/null 2>&1 || \ die "Docker network '$MUYU_NETWORK' not found. Start muyu-apiserver first: cd ../muyu-apiserver/deploy && docker compose up -d" docker inspect -f '{{.State.Running}}' "$MUYU_MYSQL_CONTAINER" 2>/dev/null | grep -q true || \ die "Container '$MUYU_MYSQL_CONTAINER' is not running. Start muyu-apiserver first." for c in muyu-system-rpc muyu-inventory-rpc; do docker inspect -f '{{.State.Running}}' "$c" >/dev/null 2>&1 || die "Container '$c' is not running." done echo "muyu-apiserver stack is up (network '$MUYU_NETWORK' found, mysql/system-rpc/inventory-rpc running)." log "Applying iloom schema to shared muyu_wms database (idempotent)" docker exec -i "$MUYU_MYSQL_CONTAINER" mysql -uroot -p"${MYSQL_ROOT_PASSWORD:?Set MYSQL_ROOT_PASSWORD in .env}" < scripts/init-iloom.sql echo "iloom tables (ilm_*) ensured in muyu_wms." log "Building and starting iloom services: ${SERVICES[*]}" docker compose -f "$COMPOSE_FILE" up -d --build "${SERVICES[@]}" log "Waiting for services to become healthy" port_for() { case "$1" in gateway) echo "${GATEWAY_PORT:-8080}" ;; auth-service) echo "${AUTH_SERVICE_PORT:-8081}" ;; purchaser-service) echo "${PURCHASER_SERVICE_PORT:-8082}" ;; textile-service) echo "${TEXTILE_SERVICE_PORT:-8083}" ;; washing-service) echo "${WASHING_SERVICE_PORT:-8084}" ;; frontend) echo "${FRONTEND_PORT:-3015}" ;; esac } path_for() { case "$1" in frontend) echo "/" ;; *) echo "/health" ;; esac } all_ok=true for svc in "${SERVICES[@]}"; do port="$(port_for "$svc")" path="$(path_for "$svc")" ok=false for _ in $(seq 1 30); do if curl -fsS -o /dev/null "http://localhost:${port}${path}" 2>/dev/null; then ok=true break fi sleep 2 done if [ "$ok" = true ]; then echo " [OK] $svc (http://localhost:${port}${path})" else echo " [FAIL] $svc (http://localhost:${port}${path}) did not become healthy in time" all_ok=false fi done if [ "$all_ok" = true ]; then log "Deploy complete. All services healthy." else log "Deploy finished with failures. Check logs: docker compose -f $COMPOSE_FILE logs -f " exit 1 fi