Deploy: exdev sync 2026-08-13 13:47:23
This commit is contained in:
+154
-154
@@ -1,154 +1,154 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# exAichatbot_agent — Gitea push → exdev 서버 빌드·배포
|
||||
# 설치: /Volumes/ADATA/git/deploy-exAichatbot_agent.sh
|
||||
# 호출: post-receive (main 브랜치 push)
|
||||
# ==============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
GIT_DIR="${GIT_DIR:-/Volumes/ADATA/gitea/data/gitea-repositories/aidev/exaichatbot_agent.git}"
|
||||
WORK_TREE="${WORK_TREE:-/Users/aidev/dev/exAichatbot_agent}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
DEPLOY_LOG="${DEPLOY_LOG:-/Volumes/ADATA/logs/deploy/exAichatbot_agent.log}"
|
||||
LOG_TAG="[exAichatbot_agent-deploy]"
|
||||
|
||||
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/Applications/Docker.app/Contents/Resources/bin:${PATH:-/usr/bin:/bin}"
|
||||
|
||||
mkdir -p "$(dirname "$DEPLOY_LOG")"
|
||||
exec >> "$DEPLOY_LOG" 2>&1
|
||||
|
||||
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $LOG_TAG $*"; }
|
||||
fail() { log "[ERROR] $*"; exit 1; }
|
||||
|
||||
LOCK_FILE="/tmp/exAichatbot_agent_deploy.lock"
|
||||
if [[ -f "$LOCK_FILE" ]]; then
|
||||
LOCK_PID="$(cat "$LOCK_FILE" 2>/dev/null || echo "")"
|
||||
if [[ -n "$LOCK_PID" ]] && kill -0 "$LOCK_PID" 2>/dev/null; then
|
||||
fail "다른 배포 진행 중 (PID: $LOCK_PID)"
|
||||
fi
|
||||
rm -f "$LOCK_FILE"
|
||||
fi
|
||||
echo $$ > "$LOCK_FILE"
|
||||
DEPLOY_OK=false
|
||||
trap 'rm -f "$LOCK_FILE"; if ! $DEPLOY_OK; then log "[ERROR] 배포 실패"; fi; log "락 해제"' EXIT
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--start-only) START_ONLY=true ;;
|
||||
esac
|
||||
done
|
||||
START_ONLY="${START_ONLY:-false}"
|
||||
|
||||
log "======================================================"
|
||||
log " exAichatbot Agent 2.0 배포 시작"
|
||||
log " GIT_DIR : $GIT_DIR"
|
||||
log " WORK_TREE : $WORK_TREE"
|
||||
log " BRANCH : $BRANCH"
|
||||
log " START_ONLY: $START_ONLY"
|
||||
log "======================================================"
|
||||
|
||||
[[ -d "$GIT_DIR" ]] || fail "GIT_DIR 없음: $GIT_DIR"
|
||||
mkdir -p "$WORK_TREE"
|
||||
|
||||
chmod +x "$WORK_TREE/server-dev/"*.sh 2>/dev/null || true
|
||||
chmod +x "$WORK_TREE/git_fetch_all.sh" 2>/dev/null || true
|
||||
chmod +x "$WORK_TREE/chatbotApp-chatbot2.0-agent/build.sh" 2>/dev/null || true
|
||||
|
||||
sync_worktree_submodules() {
|
||||
local tree="$1"
|
||||
local path ready=0
|
||||
for path in chatbotApp-chatbot2.0-agent chatbotApi-chatbot2.0-agent \
|
||||
exAiChatBot-chatbot2.0-agent kakaoChatbotSkill-chatbot2.0-agent; do
|
||||
if [[ -f "${tree}/${path}/build.gradle" ]] || [[ -f "${tree}/${path}/build.sh" ]] \
|
||||
|| [[ -f "${tree}/${path}/docker/service-slim.Dockerfile" ]]; then
|
||||
ready=$((ready + 1))
|
||||
fi
|
||||
done
|
||||
if [[ ${ready} -ge 4 ]]; then
|
||||
log "submodule 소스 이미 존재 (Gitea/rsync) — 공식 GitHub fetch 생략"
|
||||
if [[ -f "${tree}/server-dev/docker-compose.rag.server.yml" ]]; then
|
||||
cp "${tree}/server-dev/docker-compose.rag.server.yml" \
|
||||
"${tree}/exAiChatBot-chatbot2.0-agent/docker-compose.server.yml" 2>/dev/null || true
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
# 공식 GitHub 는 deploy 경로에서 절대 동기화/push 하지 않음.
|
||||
# 소스가 비어 있으면 로컬 Mac 의 rsync (sync-submodules-rsync.sh) 가 필요.
|
||||
log "[WARN] submodule 소스 부족 (${ready}/4) — 공식 GitHub fetch 안 함. 로컬 rsync 필요"
|
||||
}
|
||||
|
||||
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 컴파일만 검증 — 실패 시 가동 중인 스택을 유지한다.
|
||||
# Gitea post-receive / 비로그인 SSH 는 PATH 에 brew java 가 없고 /usr/bin/java 는 stub 이므로
|
||||
# JAVA_HOME 을 반드시 export 해야 gradlew 부트스트랩이 성공한다.
|
||||
preflight_java_compile() {
|
||||
local java_home dir
|
||||
java_home="$(resolve_java17_home)"
|
||||
export JAVA_HOME="${java_home}"
|
||||
export PATH="${JAVA_HOME}/bin:/opt/homebrew/bin:/opt/homebrew/sbin:${PATH}"
|
||||
log "[Phase 0] Java 사전 컴파일 검증 (Java 17: ${JAVA_HOME})"
|
||||
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}"
|
||||
export JAVA_HOME
|
||||
export PATH="${JAVA_HOME}/bin:${PATH}"
|
||||
./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 미사용"
|
||||
git --work-tree="$WORK_TREE" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
|
||||
rm -f "$WORK_TREE/.git"
|
||||
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
|
||||
cp "$WORK_TREE/server-dev/env.exdev-server.template" "$ENV_FILE"
|
||||
log ".env 생성 (env.exdev-server.template)"
|
||||
fi
|
||||
|
||||
log "[Phase 4] start-all-server.sh (기동)"
|
||||
START_ARGS=(--skip-legacy-stop --no-pull --no-push)
|
||||
if $START_ONLY || [[ -f "$WORK_TREE/chatbotApp-chatbot2.0-agent/public/index.html" ]]; then
|
||||
START_ARGS+=(--no-build)
|
||||
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/"
|
||||
log "======================================================"
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# exAichatbot_agent — Gitea push → exdev 서버 빌드·배포
|
||||
# 설치: /Volumes/ADATA/git/deploy-exAichatbot_agent.sh
|
||||
# 호출: post-receive (main 브랜치 push)
|
||||
# ==============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
GIT_DIR="${GIT_DIR:-/Volumes/ADATA/gitea/data/gitea-repositories/aidev/exaichatbot_agent.git}"
|
||||
WORK_TREE="${WORK_TREE:-/Users/aidev/dev/exAichatbot_agent}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
DEPLOY_LOG="${DEPLOY_LOG:-/Volumes/ADATA/logs/deploy/exAichatbot_agent.log}"
|
||||
LOG_TAG="[exAichatbot_agent-deploy]"
|
||||
|
||||
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/Applications/Docker.app/Contents/Resources/bin:${PATH:-/usr/bin:/bin}"
|
||||
|
||||
mkdir -p "$(dirname "$DEPLOY_LOG")"
|
||||
exec >> "$DEPLOY_LOG" 2>&1
|
||||
|
||||
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $LOG_TAG $*"; }
|
||||
fail() { log "[ERROR] $*"; exit 1; }
|
||||
|
||||
LOCK_FILE="/tmp/exAichatbot_agent_deploy.lock"
|
||||
if [[ -f "$LOCK_FILE" ]]; then
|
||||
LOCK_PID="$(cat "$LOCK_FILE" 2>/dev/null || echo "")"
|
||||
if [[ -n "$LOCK_PID" ]] && kill -0 "$LOCK_PID" 2>/dev/null; then
|
||||
fail "다른 배포 진행 중 (PID: $LOCK_PID)"
|
||||
fi
|
||||
rm -f "$LOCK_FILE"
|
||||
fi
|
||||
echo $$ > "$LOCK_FILE"
|
||||
DEPLOY_OK=false
|
||||
trap 'rm -f "$LOCK_FILE"; if ! $DEPLOY_OK; then log "[ERROR] 배포 실패"; fi; log "락 해제"' EXIT
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--start-only) START_ONLY=true ;;
|
||||
esac
|
||||
done
|
||||
START_ONLY="${START_ONLY:-false}"
|
||||
|
||||
log "======================================================"
|
||||
log " exAichatbot Agent 2.0 배포 시작"
|
||||
log " GIT_DIR : $GIT_DIR"
|
||||
log " WORK_TREE : $WORK_TREE"
|
||||
log " BRANCH : $BRANCH"
|
||||
log " START_ONLY: $START_ONLY"
|
||||
log "======================================================"
|
||||
|
||||
[[ -d "$GIT_DIR" ]] || fail "GIT_DIR 없음: $GIT_DIR"
|
||||
mkdir -p "$WORK_TREE"
|
||||
|
||||
chmod +x "$WORK_TREE/server-dev/"*.sh 2>/dev/null || true
|
||||
chmod +x "$WORK_TREE/git_fetch_all.sh" 2>/dev/null || true
|
||||
chmod +x "$WORK_TREE/chatbotApp-chatbot2.0-agent/build.sh" 2>/dev/null || true
|
||||
|
||||
sync_worktree_submodules() {
|
||||
local tree="$1"
|
||||
local path ready=0
|
||||
for path in chatbotApp-chatbot2.0-agent chatbotApi-chatbot2.0-agent \
|
||||
exAiChatBot-chatbot2.0-agent kakaoChatbotSkill-chatbot2.0-agent; do
|
||||
if [[ -f "${tree}/${path}/build.gradle" ]] || [[ -f "${tree}/${path}/build.sh" ]] \
|
||||
|| [[ -f "${tree}/${path}/docker/service-slim.Dockerfile" ]]; then
|
||||
ready=$((ready + 1))
|
||||
fi
|
||||
done
|
||||
if [[ ${ready} -ge 4 ]]; then
|
||||
log "submodule 소스 이미 존재 (Gitea/rsync) — 공식 GitHub fetch 생략"
|
||||
if [[ -f "${tree}/server-dev/docker-compose.rag.server.yml" ]]; then
|
||||
cp "${tree}/server-dev/docker-compose.rag.server.yml" \
|
||||
"${tree}/exAiChatBot-chatbot2.0-agent/docker-compose.server.yml" 2>/dev/null || true
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
# 공식 GitHub 는 deploy 경로에서 절대 동기화/push 하지 않음.
|
||||
# 소스가 비어 있으면 로컬 Mac 의 rsync (sync-submodules-rsync.sh) 가 필요.
|
||||
log "[WARN] submodule 소스 부족 (${ready}/4) — 공식 GitHub fetch 안 함. 로컬 rsync 필요"
|
||||
}
|
||||
|
||||
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 컴파일만 검증 — 실패 시 가동 중인 스택을 유지한다.
|
||||
# Gitea post-receive / 비로그인 SSH 는 PATH 에 brew java 가 없고 /usr/bin/java 는 stub 이므로
|
||||
# JAVA_HOME 을 반드시 export 해야 gradlew 부트스트랩이 성공한다.
|
||||
preflight_java_compile() {
|
||||
local java_home dir
|
||||
java_home="$(resolve_java17_home)"
|
||||
export JAVA_HOME="${java_home}"
|
||||
export PATH="${JAVA_HOME}/bin:/opt/homebrew/bin:/opt/homebrew/sbin:${PATH}"
|
||||
log "[Phase 0] Java 사전 컴파일 검증 (Java 17: ${JAVA_HOME})"
|
||||
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}"
|
||||
export JAVA_HOME
|
||||
export PATH="${JAVA_HOME}/bin:${PATH}"
|
||||
./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 미사용"
|
||||
git --work-tree="$WORK_TREE" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
|
||||
rm -f "$WORK_TREE/.git"
|
||||
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
|
||||
cp "$WORK_TREE/server-dev/env.exdev-server.template" "$ENV_FILE"
|
||||
log ".env 생성 (env.exdev-server.template)"
|
||||
fi
|
||||
|
||||
log "[Phase 4] start-all-server.sh (기동)"
|
||||
START_ARGS=(--skip-legacy-stop --no-pull --no-push)
|
||||
if $START_ONLY || [[ -f "$WORK_TREE/chatbotApp-chatbot2.0-agent/public/index.html" ]]; then
|
||||
START_ARGS+=(--no-build)
|
||||
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/"
|
||||
log "======================================================"
|
||||
|
||||
@@ -1,86 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# Gitea push 후 chatbot.exdev.co.kr 배포 완료 대기
|
||||
# - UI 응답 또는 배포 로그의 "배포 완료" 확인
|
||||
# - "배포 실패"/컴파일 오류는 즉시 종료 (900s 무의미 대기 방지)
|
||||
set -euo pipefail
|
||||
|
||||
EXDEV_SSH="${EXDEV_SSH:-aidev@chatbot.exdev.co.kr}"
|
||||
DEPLOY_LOG="${DEPLOY_LOG:-/Volumes/ADATA/logs/deploy/exAichatbot_agent.log}"
|
||||
PUBLIC_URL="${PUBLIC_BASE_URL:-https://chatbot.exdev.co.kr}/chatbot/ai/"
|
||||
MAX_WAIT="${DEPLOY_WAIT_SEC:-900}"
|
||||
|
||||
log() { echo "[wait-deploy] $*"; }
|
||||
|
||||
ssh_cmd() {
|
||||
ssh -o BatchMode=yes -o ConnectTimeout=15 "${EXDEV_SSH}" "$@"
|
||||
}
|
||||
|
||||
if ! ssh_cmd "test -f '${DEPLOY_LOG}'" 2>/dev/null; then
|
||||
log "배포 로그 없음 — SSH로 deploy 스크립트 직접 실행"
|
||||
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
|
||||
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 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}" == *"배포 완료"* ]] || [[ "${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 5
|
||||
done
|
||||
|
||||
log "⚠️ 배포 대기 타임아웃 — 로그 확인: ssh ${EXDEV_SSH} tail -50 ${DEPLOY_LOG}"
|
||||
new_log_tail | tail -40
|
||||
exit 1
|
||||
#!/usr/bin/env bash
|
||||
# Gitea push 후 chatbot.exdev.co.kr 배포 완료 대기
|
||||
# - UI 응답 또는 배포 로그의 "배포 완료" 확인
|
||||
# - "배포 실패"/컴파일 오류는 즉시 종료 (900s 무의미 대기 방지)
|
||||
set -euo pipefail
|
||||
|
||||
EXDEV_SSH="${EXDEV_SSH:-aidev@chatbot.exdev.co.kr}"
|
||||
DEPLOY_LOG="${DEPLOY_LOG:-/Volumes/ADATA/logs/deploy/exAichatbot_agent.log}"
|
||||
PUBLIC_URL="${PUBLIC_BASE_URL:-https://chatbot.exdev.co.kr}/chatbot/ai/"
|
||||
MAX_WAIT="${DEPLOY_WAIT_SEC:-900}"
|
||||
|
||||
log() { echo "[wait-deploy] $*"; }
|
||||
|
||||
ssh_cmd() {
|
||||
ssh -o BatchMode=yes -o ConnectTimeout=15 "${EXDEV_SSH}" "$@"
|
||||
}
|
||||
|
||||
if ! ssh_cmd "test -f '${DEPLOY_LOG}'" 2>/dev/null; then
|
||||
log "배포 로그 없음 — SSH로 deploy 스크립트 직접 실행"
|
||||
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
|
||||
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 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}" == *"배포 완료"* ]] || [[ "${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 5
|
||||
done
|
||||
|
||||
log "⚠️ 배포 대기 타임아웃 — 로그 확인: ssh ${EXDEV_SSH} tail -50 ${DEPLOY_LOG}"
|
||||
new_log_tail | tail -40
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user