#!/bin/bash # =================================================================== # TK Factory Services - 원격 배포 스크립트 (맥북에서 실행) # =================================================================== # 사용법: ./scripts/deploy-remote.sh # 설정: ~/.tk-deploy-config # =================================================================== set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" CONFIG_FILE="$HOME/.tk-deploy-config" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' # === 설정 로드 === if [ ! -f "$CONFIG_FILE" ]; then echo -e "${RED}ERROR: 설정 파일이 없습니다: $CONFIG_FILE${NC}" cat <<'EXAMPLE' 다음 내용으로 생성하세요: NAS_HOST=100.71.132.52 NAS_USER=hyungi NAS_DEPLOY_PATH=/volume1/docker_1/tk-factory-services NAS_SUDO_PASS= EXAMPLE exit 1 fi source "$CONFIG_FILE" for var in NAS_HOST NAS_USER NAS_DEPLOY_PATH NAS_SUDO_PASS; do if [ -z "${!var}" ]; then echo -e "${RED}ERROR: $CONFIG_FILE에 $var 가 설정되지 않았습니다${NC}" exit 1 fi done DOCKER="/usr/local/bin/docker" DEPLOY_BRANCH="${DEPLOY_BRANCH:-main}" # === 헬퍼 함수 === ssh_cmd() { ssh -o ConnectTimeout=10 "${NAS_USER}@${NAS_HOST}" "$@" } nas_docker() { ssh_cmd "cd ${NAS_DEPLOY_PATH} && echo '${NAS_SUDO_PASS}' | sudo -S ${DOCKER} $*" 2>&1 } # === Phase 1: Pre-flight 체크 === echo "=== TK Factory Services - 원격 배포 ===" echo "" echo -e "${CYAN}[1/5] Pre-flight 체크${NC}" cd "$PROJECT_DIR" # Working tree clean 확인 if [ -n "$(git status --porcelain)" ]; then echo -e "${RED}ERROR: 로컬에 커밋되지 않은 변경사항이 있습니다${NC}" echo "" git status --short echo "" echo "먼저 커밋하거나 stash하세요." exit 1 fi # 로컬 커밋 정보 LOCAL_HASH=$(git rev-parse HEAD) LOCAL_SHORT=$(git rev-parse --short HEAD) LOCAL_MSG=$(git log -1 --format='%s') LOCAL_BRANCH=$(git rev-parse --abbrev-ref HEAD) # origin 동기화 확인 git fetch origin --quiet ORIGIN_HASH=$(git rev-parse "origin/${LOCAL_BRANCH}" 2>/dev/null || echo "") if [ "$LOCAL_HASH" != "$ORIGIN_HASH" ]; then echo -e "${RED}ERROR: 로컬 커밋이 origin에 push되지 않았습니다${NC}" echo " 로컬: ${LOCAL_SHORT} (${LOCAL_MSG})" echo " 원격: $(git rev-parse --short "origin/${LOCAL_BRANCH}" 2>/dev/null || echo 'N/A')" echo "" echo "먼저 push하세요: git push origin ${LOCAL_BRANCH}" exit 1 fi echo -e " 로컬 HEAD: ${GREEN}${LOCAL_SHORT}${NC} - ${LOCAL_MSG}" echo -e " 브랜치: ${LOCAL_BRANCH}" # === Phase 2: NAS 상태 비교 === echo "" echo -e "${CYAN}[2/5] NAS 배포 상태 확인${NC}" NAS_HASH=$(ssh_cmd "cd ${NAS_DEPLOY_PATH} && git log -1 --format='%H'" 2>/dev/null || echo "") if [ -z "$NAS_HASH" ]; then echo -e "${RED}ERROR: NAS에서 git 정보를 가져올 수 없습니다${NC}" echo " 경로: ${NAS_DEPLOY_PATH}" echo " NAS에 git clone이 완료되었는지 확인하세요." exit 1 fi NAS_SHORT="${NAS_HASH:0:7}" NAS_MSG=$(ssh_cmd "cd ${NAS_DEPLOY_PATH} && git log -1 --format='%s'" 2>/dev/null) if [ "$LOCAL_HASH" = "$NAS_HASH" ]; then echo -e " ${GREEN}이미 최신 버전입니다!${NC} (${NAS_SHORT} - ${NAS_MSG})" exit 0 fi echo -e " NAS 현재: ${YELLOW}${NAS_SHORT}${NC} - ${NAS_MSG}" echo -e " 배포 대상: ${GREEN}${LOCAL_SHORT}${NC} - ${LOCAL_MSG}" # 배포될 커밋 목록 COMMIT_COUNT=$(git log "${NAS_HASH}..${LOCAL_HASH}" --oneline | wc -l | tr -d ' ') echo "" echo "=== 배포될 커밋 (${COMMIT_COUNT}개) ===" git log "${NAS_HASH}..${LOCAL_HASH}" --oneline --no-decorate echo "" read -p "배포를 진행하시겠습니까? [y/N] " confirm if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then echo "배포가 취소되었습니다." exit 0 fi # === Phase 3: 배포 실행 === echo "" echo -e "${CYAN}[3/5] NAS 코드 업데이트${NC}" ssh_cmd "cd ${NAS_DEPLOY_PATH} && git fetch origin && git reset --hard origin/${DEPLOY_BRANCH}" UPDATED_HASH=$(ssh_cmd "cd ${NAS_DEPLOY_PATH} && git log -1 --format='%H %s'" 2>/dev/null) echo -e " ${GREEN}완료${NC}: ${UPDATED_HASH}" echo "" echo -e "${CYAN}[4/5] Docker 컨테이너 빌드 및 재시작${NC}" echo " (빌드에 시간이 걸릴 수 있습니다...)" echo "" nas_docker "compose up -d --build" echo "" echo " nginx 프록시 컨테이너 재시작 (IP 캐시 갱신)..." nas_docker "restart tk-gateway tk-system2-web tk-system3-web" # === Phase 4: 배포 후 검증 === echo "" echo -e "${CYAN}[5/5] 배포 검증${NC} (15초 대기 후 health check)" sleep 15 echo "" echo "=== Container Status ===" nas_docker "compose ps --format 'table {{.Name}}\t{{.Status}}'" || true echo "" echo "=== HTTP Health Check ===" HEALTH_PASS=0 HEALTH_FAIL=0 check_remote() { local name="$1" local path="$2" local status status=$(ssh_cmd "curl -s -o /dev/null -w '%{http_code}' --connect-timeout 5 http://localhost:${path}" 2>/dev/null || echo "000") if [ "$status" -ge 200 ] 2>/dev/null && [ "$status" -lt 400 ] 2>/dev/null; then printf " %-25s ${GREEN}OK${NC} (%s)\n" "$name" "$status" ((HEALTH_PASS++)) else printf " %-25s ${RED}FAIL${NC} (%s)\n" "$name" "$status" ((HEALTH_FAIL++)) fi } check_remote "Gateway" "30000/" check_remote "SSO Auth" "30050/health" check_remote "System 1 API" "30005/api/health" check_remote "System 1 Web" "30080/" check_remote "System 1 FastAPI" "30008/health" check_remote "System 2 API" "30105/api/health" check_remote "System 2 Web" "30180/" check_remote "System 3 API" "30200/api/health" check_remote "System 3 Web" "30280/" check_remote "tkuser API" "30300/api/health" check_remote "tkuser Web" "30380/" check_remote "phpMyAdmin" "30880/" echo "" echo " Health: PASS=${HEALTH_PASS} FAIL=${HEALTH_FAIL}" # === Phase 5: 배포 로그 기록 === TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') ssh_cmd "echo '${TIMESTAMP} | ${LOCAL_SHORT} | ${LOCAL_MSG}' >> ${NAS_DEPLOY_PATH}/DEPLOY_LOG" echo "" if [ "$HEALTH_FAIL" -gt 0 ]; then echo -e "${YELLOW}배포 완료 (일부 서비스 health check 실패)${NC}" echo " 로그 확인: ssh ${NAS_USER}@${NAS_HOST} \"cd ${NAS_DEPLOY_PATH} && echo '...' | sudo -S ${DOCKER} compose logs --tail=50\"" else echo -e "${GREEN}배포 완료!${NC}" fi echo " 버전: ${LOCAL_SHORT} - ${LOCAL_MSG}"