Files
exAichatbot_agent/server-dev/deploy.sh
T
2026-08-13 17:51:39 +09:00

155 lines
5.9 KiB
Bash
Executable File

#!/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 "======================================================"