From 4301ebe1b8a998e3d4f39720e284b9a5ee847371 Mon Sep 17 00:00:00 2001 From: Macbook Date: Tue, 11 Aug 2026 15:48:53 +0900 Subject: [PATCH] Deploy: exdev sync 2026-08-11 15:48:53 --- chatbotApi-chatbot2.0-agent | 2 +- exAiChatBot-chatbot2.0-agent | 2 +- server-dev/deploy.sh | 47 ++++++++++++++++++++++++-- server-dev/start-all-server.sh | 8 +++-- server-dev/wait-remote-deploy.sh | 57 ++++++++++++++++++++++++++++---- 5 files changed, 101 insertions(+), 15 deletions(-) diff --git a/chatbotApi-chatbot2.0-agent b/chatbotApi-chatbot2.0-agent index 3972fdc..f4e8a2f 160000 --- a/chatbotApi-chatbot2.0-agent +++ b/chatbotApi-chatbot2.0-agent @@ -1 +1 @@ -Subproject commit 3972fdcbb752d9fc7ef0b6f4bdbf1a9de53e6338 +Subproject commit f4e8a2fe5ffc6a8da00a9130bb5433c6d521a00d diff --git a/exAiChatBot-chatbot2.0-agent b/exAiChatBot-chatbot2.0-agent index d26e7f1..290917c 160000 --- a/exAiChatBot-chatbot2.0-agent +++ b/exAiChatBot-chatbot2.0-agent @@ -1 +1 @@ -Subproject commit d26e7f160f04f604dc52d78a0f25688e063761da +Subproject commit 290917c48fbfe36a1339b801ddcc0bf16fde160b diff --git a/server-dev/deploy.sh b/server-dev/deploy.sh index ae78b26..19def30 100755 --- a/server-dev/deploy.sh +++ b/server-dev/deploy.sh @@ -29,7 +29,8 @@ if [[ -f "$LOCK_FILE" ]]; then rm -f "$LOCK_FILE" fi echo $$ > "$LOCK_FILE" -trap 'rm -f "$LOCK_FILE"; log "락 해제"' EXIT +DEPLOY_OK=false +trap 'rm -f "$LOCK_FILE"; if ! $DEPLOY_OK; then log "[ERROR] 배포 실패"; fi; log "락 해제"' EXIT for arg in "$@"; do case "$arg" in @@ -76,8 +77,42 @@ sync_worktree_submodules() { log "[WARN] submodule 소스 부족 (${ready}/4) — 공식 GitHub fetch 안 함. 로컬 rsync 필요" } -log "[Phase 1] stop-all-server.sh" -"$WORK_TREE/server-dev/stop-all-server.sh" --keep-caddy || true +resolve_java17_home() { + local home="" candidate + for candidate in \ + "/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home" \ + "/usr/local/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home"; do + if [[ -x "${candidate}/bin/java" ]]; then + home="${candidate}" + break + fi + done + if [[ -z "${home}" ]] && /usr/libexec/java_home -v 17 >/dev/null 2>&1; then + home="$(/usr/libexec/java_home -v 17)" + fi + [[ -n "${home}" ]] || fail "Java 17 필요 — brew install openjdk@17" + echo "${home}" +} + +# 서비스 중지 전에 Java 컴파일만 검증 — 실패 시 가동 중인 스택을 유지한다. +preflight_java_compile() { + local java_home dir + java_home="$(resolve_java17_home)" + log "[Phase 0] Java 사전 컴파일 검증 (Java 17)" + for dir in \ + "${WORK_TREE}/kakaoChatbotSkill-chatbot2.0-agent" \ + "${WORK_TREE}/chatbotApi-chatbot2.0-agent"; do + [[ -x "${dir}/gradlew" ]] || fail "gradlew 없음: ${dir}" + log " compileJava: $(basename "${dir}")" + if ! ( + cd "${dir}" + ./gradlew -Dorg.gradle.java.home="${java_home}" compileJava --quiet + ); then + fail "사전 컴파일 실패: $(basename "${dir}") — 기존 서비스는 그대로 유지됨" + fi + done + log " ✅ Java 사전 컴파일 OK" +} if ! $START_ONLY; then log "[Phase 2] checkout (Gitea work tree) — 공식 GitHub 미사용" @@ -86,6 +121,11 @@ if ! $START_ONLY; then sync_worktree_submodules "$WORK_TREE" fi +preflight_java_compile + +log "[Phase 1] stop-all-server.sh" +"$WORK_TREE/server-dev/stop-all-server.sh" --keep-caddy || true + log "[Phase 3] .env 준비" ENV_FILE="$WORK_TREE/exAiChatBot-chatbot2.0-agent/.env" if [[ ! -f "$ENV_FILE" ]]; then @@ -101,6 +141,7 @@ fi "$WORK_TREE/server-dev/start-all-server.sh" "${START_ARGS[@]}" COMMIT="$(git --git-dir="$GIT_DIR" rev-parse --short HEAD 2>/dev/null || echo unknown)" +DEPLOY_OK=true log "======================================================" log " 배포 완료 — $COMMIT" log " UI: https://chatbot.exdev.co.kr/chatbot/ai/" diff --git a/server-dev/start-all-server.sh b/server-dev/start-all-server.sh index ac79a1f..d1b3725 100755 --- a/server-dev/start-all-server.sh +++ b/server-dev/start-all-server.sh @@ -137,12 +137,14 @@ trigger_remote_deploy() { rm -f \"\${WT}/.git\" /tmp/exAichatbot_agent_deploy.lock" sync_submodules_to_server log "원격 deploy (빌드 + 기동)..." - ssh -o BatchMode=yes "${EXDEV_SSH}" \ + # SSH 세션에서 deploy 가 끝나므로, 실패 시 즉시 중단 (wait 900s 방지) + if ! ssh -o BatchMode=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=120 "${EXDEV_SSH}" \ "cp /Users/aidev/dev/exAichatbot_agent/server-dev/deploy.sh /Volumes/ADATA/git/deploy-exAichatbot_agent.sh 2>/dev/null || true; \ chmod +x /Volumes/ADATA/git/deploy-exAichatbot_agent.sh; \ export PATH=\"/opt/homebrew/bin:/Applications/Docker.app/Contents/Resources/bin:\$PATH\"; \ - bash /Volumes/ADATA/git/deploy-exAichatbot_agent.sh --start-only" \ - || warn "원격 deploy 실패" + bash /Volumes/ADATA/git/deploy-exAichatbot_agent.sh --start-only"; then + fail "원격 deploy 실패 — ssh ${EXDEV_SSH} 'tail -80 /Volumes/ADATA/logs/deploy/exAichatbot_agent.log'" + fi } build_chatbot_app_for_deploy() { diff --git a/server-dev/wait-remote-deploy.sh b/server-dev/wait-remote-deploy.sh index f7b2be7..b35ba98 100755 --- a/server-dev/wait-remote-deploy.sh +++ b/server-dev/wait-remote-deploy.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash # Gitea push 후 chatbot.exdev.co.kr 배포 완료 대기 +# - UI 응답 또는 배포 로그의 "배포 완료" 확인 +# - "배포 실패"/컴파일 오류는 즉시 종료 (900s 무의미 대기 방지) set -euo pipefail EXDEV_SSH="${EXDEV_SSH:-aidev@chatbot.exdev.co.kr}" @@ -18,26 +20,67 @@ if ! ssh_cmd "test -f '${DEPLOY_LOG}'" 2>/dev/null; then ssh_cmd "bash /Volumes/ADATA/git/deploy-exAichatbot_agent.sh" || true fi +# 대기 시작 시점의 로그 길이 — 이후 새로 찍힌 줄만 성공/실패 판정에 사용 +LOG_BASE_BYTES="$(ssh_cmd "wc -c < '${DEPLOY_LOG}' 2>/dev/null || echo 0" | tr -d '[:space:]')" +LOG_BASE_BYTES="${LOG_BASE_BYTES:-0}" + log "배포 완료 대기 (최대 ${MAX_WAIT}s) — ${EXDEV_SSH}" start_ts="$(date +%s)" deadline=$((start_ts + MAX_WAIT)) +new_log_tail() { + ssh_cmd "tail -c +$((LOG_BASE_BYTES + 1)) '${DEPLOY_LOG}' 2>/dev/null | tail -80" || true +} + while (( $(date +%s) < deadline )); do - if curl -sf --max-time 5 "${PUBLIC_URL}" 2>/dev/null | grep -q 'data-chatbot-app'; then - log "✅ UI 응답: ${PUBLIC_URL}" - ssh_cmd "tail -8 '${DEPLOY_LOG}'" 2>/dev/null || true - exit 0 + recent="$(new_log_tail)" + + # 신규 로그에 실패 마커가 있으면 즉시 종료 + if echo "${recent}" | grep -qE '\[ERROR\] 배포 실패|ERROR: chatbotApi 컴파일 실패|BUILD FAILED|\[ERROR\] 다른 배포 진행 중'; then + log "⚠️ 원격 배포 실패 감지 — 최근 로그:" + echo "${recent}" | tail -40 + exit 1 fi - if ssh_cmd "grep -q '배포 완료' '${DEPLOY_LOG}'" 2>/dev/null; then + + if curl -sf --max-time 5 "${PUBLIC_URL}" 2>/dev/null | grep -q 'data-chatbot-app'; then + # UI 살아있어도, 이번 배포가 아직 실패로 끝났으면 성공으로 치지 않음 + if echo "${recent}" | grep -qE '\[ERROR\] 배포 실패|ERROR: chatbotApi 컴파일 실패|BUILD FAILED'; then + log "⚠️ UI는 응답하나 이번 배포 로그에 실패가 있습니다" + echo "${recent}" | tail -40 + exit 1 + fi + if echo "${recent}" | grep -q '배포 완료'; then + log "✅ UI 응답 + 배포 완료 로그: ${PUBLIC_URL}" + ssh_cmd "tail -8 '${DEPLOY_LOG}'" 2>/dev/null || true + exit 0 + fi + # start-only 직후 UI 가 이전 빌드로 살아 있을 수 있음 — 신규 성공 로그를 우선 + if echo "${recent}" | grep -q '배포 시작'; then + : + else + log "✅ UI 응답: ${PUBLIC_URL}" + ssh_cmd "tail -8 '${DEPLOY_LOG}'" 2>/dev/null || true + exit 0 + fi + fi + + if echo "${recent}" | grep -q '배포 완료'; then last_line="$(ssh_cmd "tail -1 '${DEPLOY_LOG}'" 2>/dev/null || true)" - if [[ "${last_line}" == *"배포 완료"* ]]; then + if [[ "${last_line}" == *"배포 완료"* ]] || [[ "${last_line}" == *"락 해제"* ]]; then + # 성공 후 trap 이 락 해제를 찍을 수 있음 + if echo "${recent}" | grep -qE '\[ERROR\] 배포 실패|BUILD FAILED'; then + log "⚠️ 배포 실패 로그 감지" + echo "${recent}" | tail -40 + exit 1 + fi log "✅ 배포 로그 확인" ssh_cmd "tail -8 '${DEPLOY_LOG}'" 2>/dev/null || true exit 0 fi fi - sleep 10 + sleep 5 done log "⚠️ 배포 대기 타임아웃 — 로그 확인: ssh ${EXDEV_SSH} tail -50 ${DEPLOY_LOG}" +new_log_tail | tail -40 exit 1