177 lines
4.9 KiB
Bash
Executable File
177 lines
4.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# galaxis-agent 배포 스크립트
|
|
# Usage: ./deploy.sh [--dry-run]
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
cd "$SCRIPT_DIR"
|
|
|
|
DRY_RUN=false
|
|
if [[ "${1:-}" == "--dry-run" ]]; then
|
|
DRY_RUN=true
|
|
echo "[DRY-RUN] Docker 명령은 실행하지 않고 출력만 합니다."
|
|
echo ""
|
|
fi
|
|
|
|
HEALTH_URL="${HEALTH_URL:-http://localhost:8100}"
|
|
HEALTH_RETRY_INTERVAL=5
|
|
HEALTH_MAX_WAIT=60
|
|
|
|
# 색상
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
error() { echo -e "${RED}[ERROR]${NC} $*"; }
|
|
|
|
# ── Pre-flight 체크 ────────────────────────────────────
|
|
|
|
info "Pre-flight 체크 시작..."
|
|
|
|
# 1. Docker
|
|
if ! command -v docker &>/dev/null; then
|
|
error "Docker가 설치되어 있지 않습니다."
|
|
echo " 설치: https://docs.docker.com/engine/install/"
|
|
exit 1
|
|
fi
|
|
info "Docker: $(docker --version)"
|
|
|
|
# 2. Docker Compose
|
|
if ! docker compose version &>/dev/null; then
|
|
error "Docker Compose가 설치되어 있지 않습니다."
|
|
echo " 설치: https://docs.docker.com/compose/install/"
|
|
exit 1
|
|
fi
|
|
info "Docker Compose: $(docker compose version --short)"
|
|
|
|
# 3. .env 파일 (docker compose config보다 먼저 확인 — env_file 의존)
|
|
if [[ ! -f .env ]]; then
|
|
error ".env 파일이 없습니다."
|
|
echo " cp .env.example .env 후 값을 설정하세요."
|
|
exit 1
|
|
fi
|
|
info ".env 파일 OK"
|
|
|
|
# 4. 필수 환경변수 검증 (grep 기반 — 셸 환경 오염 방지)
|
|
REQUIRED_VARS=(
|
|
ANTHROPIC_API_KEY
|
|
GITEA_TOKEN
|
|
GITEA_WEBHOOK_SECRET
|
|
DISCORD_TOKEN
|
|
DISCORD_CHANNEL_ID
|
|
FERNET_KEY
|
|
AGENT_API_KEY
|
|
)
|
|
|
|
MISSING=()
|
|
for var in "${REQUIRED_VARS[@]}"; do
|
|
if ! grep -qE "^${var}=.+" .env; then
|
|
MISSING+=("$var")
|
|
fi
|
|
done
|
|
|
|
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
|
error "필수 환경변수가 설정되지 않았습니다:"
|
|
for var in "${MISSING[@]}"; do
|
|
echo " - $var"
|
|
done
|
|
echo " .env 파일을 확인하세요."
|
|
exit 1
|
|
fi
|
|
info "필수 환경변수 OK (${#REQUIRED_VARS[@]}개 확인)"
|
|
|
|
# 5. docker-compose.yml 유효성
|
|
if ! docker compose config --quiet 2>/dev/null; then
|
|
error "docker-compose.yml 유효성 검증 실패."
|
|
echo " docker compose config 으로 상세 에러를 확인하세요."
|
|
exit 1
|
|
fi
|
|
info "docker-compose.yml 유효성 OK"
|
|
|
|
# 6. galaxis-net 네트워크
|
|
if ! docker network inspect galaxis-net &>/dev/null; then
|
|
warn "galaxis-net 네트워크가 없습니다. 생성합니다."
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
echo " [DRY-RUN] docker network create galaxis-net"
|
|
else
|
|
docker network create galaxis-net
|
|
fi
|
|
fi
|
|
info "galaxis-net 네트워크 OK"
|
|
|
|
echo ""
|
|
info "Pre-flight 체크 완료!"
|
|
echo ""
|
|
|
|
# ── 배포 ────────────────────────────────────────────────
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
echo "[DRY-RUN] 실행될 명령:"
|
|
echo " docker compose build"
|
|
echo " docker compose up -d"
|
|
echo " Health check: ${HEALTH_URL}/health (${HEALTH_RETRY_INTERVAL}초 간격, 최대 ${HEALTH_MAX_WAIT}초)"
|
|
echo ""
|
|
info "Dry-run 완료. 실제 배포는 --dry-run 없이 실행하세요."
|
|
exit 0
|
|
fi
|
|
|
|
info "galaxis-agent 이미지 빌드 중..."
|
|
docker compose build
|
|
|
|
info "서비스 시작 중..."
|
|
docker compose up -d
|
|
|
|
# ── Health check ────────────────────────────────────────
|
|
|
|
info "Health check 시작 (${HEALTH_RETRY_INTERVAL}초 간격, 최대 ${HEALTH_MAX_WAIT}초)..."
|
|
|
|
ELAPSED=0
|
|
HEALTHY=false
|
|
|
|
while [[ $ELAPSED -lt $HEALTH_MAX_WAIT ]]; do
|
|
if curl -sf "${HEALTH_URL}/health" | grep -q '"status".*"ok"' 2>/dev/null; then
|
|
HEALTHY=true
|
|
break
|
|
fi
|
|
sleep "$HEALTH_RETRY_INTERVAL"
|
|
ELAPSED=$((ELAPSED + HEALTH_RETRY_INTERVAL))
|
|
echo " 대기 중... (${ELAPSED}초)"
|
|
done
|
|
|
|
if [[ "$HEALTHY" != true ]]; then
|
|
error "Health check 실패: ${HEALTH_URL}/health 가 ${HEALTH_MAX_WAIT}초 내에 응답하지 않았습니다."
|
|
echo ""
|
|
echo " 로그 확인: docker compose logs"
|
|
echo " 수동 롤백:"
|
|
echo " docker compose down"
|
|
echo " git checkout <이전_커밋>"
|
|
echo " ./deploy.sh"
|
|
exit 1
|
|
fi
|
|
|
|
# 개별 health check
|
|
ENDPOINTS=("/health" "/health/gitea" "/health/discord" "/health/queue" "/health/costs")
|
|
ALL_OK=true
|
|
|
|
echo ""
|
|
for ep in "${ENDPOINTS[@]}"; do
|
|
if curl -sf "${HEALTH_URL}${ep}" >/dev/null 2>&1; then
|
|
info " ${ep} ... OK"
|
|
else
|
|
warn " ${ep} ... FAIL"
|
|
ALL_OK=false
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
if [[ "$ALL_OK" == true ]]; then
|
|
info "배포 성공! 모든 health check 통과."
|
|
else
|
|
warn "배포 완료. 일부 health check가 실패했습니다."
|
|
echo " 로그 확인: docker compose logs"
|
|
fi
|