Some checks failed
CD Pipeline / deploy (push) Failing after 59s
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml) - 部署模式: rsync Python 檔案至 188 → docker restart (volume mount) - Dockerfile/requirements 變動時自動重建 Docker image - 部署通知: Telegram (開始/成功/失敗) - 健康檢查: https://mo.wooo.work/health (最多 5 次重試) - 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
276 lines
8.8 KiB
Bash
Executable File
276 lines
8.8 KiB
Bash
Executable File
#!/bin/bash
|
||
# =============================================================================
|
||
# WOOO TECH - Momo Pro System
|
||
# UAT Docker 一鍵部署腳本
|
||
# =============================================================================
|
||
|
||
set -e
|
||
|
||
# 顏色定義
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
PURPLE='\033[0;35m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 配置
|
||
UAT_HOST="192.168.0.110"
|
||
UAT_USER="wooo"
|
||
UAT_PATH="/home/wooo/momo_pro_system"
|
||
LOCAL_PATH="/Users/ogt/momo_pro_system"
|
||
IMAGE_NAME="wooo/momo-pro-system"
|
||
CONTAINER_NAME="momo-pro-system"
|
||
|
||
# 函數:打印帶顏色的訊息
|
||
print_header() {
|
||
echo ""
|
||
echo -e "${PURPLE}=============================================================================${NC}"
|
||
echo -e "${PURPLE} $1${NC}"
|
||
echo -e "${PURPLE}=============================================================================${NC}"
|
||
}
|
||
|
||
print_step() {
|
||
echo -e "${CYAN}▶ $1${NC}"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
}
|
||
|
||
print_info() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
# 檢查 SSH 連線
|
||
check_ssh() {
|
||
print_step "檢查 SSH 連線..."
|
||
if ssh -o ConnectTimeout=5 -o BatchMode=yes ${UAT_USER}@${UAT_HOST} "echo ok" 2>/dev/null; then
|
||
print_success "SSH 連線正常(免密碼)"
|
||
return 0
|
||
else
|
||
print_warning "需要 SSH 密碼驗證"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 主要部署流程
|
||
deploy() {
|
||
print_header "WOOO TECH - UAT Docker 部署"
|
||
echo -e "${CYAN}目標主機: ${UAT_USER}@${UAT_HOST}${NC}"
|
||
echo -e "${CYAN}部署時間: $(date '+%Y-%m-%d %H:%M:%S')${NC}"
|
||
echo ""
|
||
|
||
# 步驟 1: 同步配置檔案
|
||
print_header "步驟 1/6: 同步 Docker 配置檔案到 UAT"
|
||
|
||
print_step "上傳 Dockerfile..."
|
||
scp "${LOCAL_PATH}/Dockerfile" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳 docker-compose.yml..."
|
||
scp "${LOCAL_PATH}/docker-compose.yml" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳 .dockerignore..."
|
||
scp "${LOCAL_PATH}/.dockerignore" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳 docker/ 目錄..."
|
||
scp -r "${LOCAL_PATH}/docker" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳 requirements.txt..."
|
||
scp "${LOCAL_PATH}/requirements.txt" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳核心 Python 檔案..."
|
||
scp "${LOCAL_PATH}/app.py" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
scp "${LOCAL_PATH}/auth.py" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
scp "${LOCAL_PATH}/config.py" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
scp "${LOCAL_PATH}/scheduler.py" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳 HTML 模板..."
|
||
scp "${LOCAL_PATH}"/*.html ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/ 2>/dev/null || true
|
||
|
||
print_step "上傳 services/ 目錄..."
|
||
scp -r "${LOCAL_PATH}/services" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳 database/ 目錄..."
|
||
scp -r "${LOCAL_PATH}/database" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳 utils/ 目錄..."
|
||
scp -r "${LOCAL_PATH}/utils" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳 static/ 目錄..."
|
||
scp -r "${LOCAL_PATH}/static" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_step "上傳 web/ 目錄..."
|
||
scp -r "${LOCAL_PATH}/web" ${UAT_USER}@${UAT_HOST}:${UAT_PATH}/
|
||
|
||
print_success "檔案同步完成"
|
||
|
||
# 步驟 2: 停止現有服務
|
||
print_header "步驟 2/6: 停止現有服務"
|
||
|
||
print_step "停止 systemd momo 服務..."
|
||
ssh ${UAT_USER}@${UAT_HOST} "sudo systemctl stop momo 2>/dev/null || echo '服務未運行'"
|
||
|
||
print_step "停止並刪除舊的 Docker 容器..."
|
||
ssh ${UAT_USER}@${UAT_HOST} "docker stop ${CONTAINER_NAME} 2>/dev/null || true"
|
||
ssh ${UAT_USER}@${UAT_HOST} "docker rm ${CONTAINER_NAME} 2>/dev/null || true"
|
||
|
||
print_success "服務已停止"
|
||
|
||
# 步驟 3: 建置 Docker Image
|
||
print_header "步驟 3/6: 建置 Docker Image"
|
||
print_info "這可能需要幾分鐘,請耐心等候..."
|
||
|
||
ssh ${UAT_USER}@${UAT_HOST} "cd ${UAT_PATH} && docker build -t ${IMAGE_NAME}:latest ."
|
||
|
||
print_success "Docker Image 建置完成"
|
||
|
||
# 步驟 4: 啟動 Docker 容器
|
||
print_header "步驟 4/6: 啟動 Docker 容器"
|
||
|
||
ssh ${UAT_USER}@${UAT_HOST} "cd ${UAT_PATH} && docker run -d \
|
||
--name ${CONTAINER_NAME} \
|
||
-p 5000:5000 \
|
||
-v ./data:/app/data \
|
||
-v ./logs:/app/logs \
|
||
-v ./config:/app/config \
|
||
-v ./backups:/app/backups \
|
||
--env-file .env \
|
||
--restart unless-stopped \
|
||
${IMAGE_NAME}:latest"
|
||
|
||
print_success "Docker 容器已啟動"
|
||
|
||
# 步驟 5: 等待服務啟動
|
||
print_header "步驟 5/6: 等待服務啟動"
|
||
print_info "等待 30 秒讓服務完全啟動..."
|
||
|
||
for i in {1..30}; do
|
||
echo -ne "\r${CYAN}等待中... ${i}/30 秒${NC}"
|
||
sleep 1
|
||
done
|
||
echo ""
|
||
|
||
print_success "等待完成"
|
||
|
||
# 步驟 6: 驗證部署
|
||
print_header "步驟 6/6: 驗證部署"
|
||
|
||
print_step "檢查容器狀態..."
|
||
ssh ${UAT_USER}@${UAT_HOST} "docker ps --filter name=${CONTAINER_NAME} --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"
|
||
|
||
print_step "測試健康檢查端點..."
|
||
HEALTH_STATUS=$(ssh ${UAT_USER}@${UAT_HOST} "curl -s -o /dev/null -w '%{http_code}' http://localhost:5000/health" || echo "000")
|
||
|
||
if [ "$HEALTH_STATUS" = "200" ]; then
|
||
print_success "健康檢查通過 (HTTP 200)"
|
||
else
|
||
print_warning "健康檢查回傳 HTTP ${HEALTH_STATUS}"
|
||
fi
|
||
|
||
print_step "測試首頁..."
|
||
HOME_STATUS=$(ssh ${UAT_USER}@${UAT_HOST} "curl -s -o /dev/null -w '%{http_code}' http://localhost:5000/" || echo "000")
|
||
|
||
if [ "$HOME_STATUS" = "200" ] || [ "$HOME_STATUS" = "302" ]; then
|
||
print_success "首頁正常 (HTTP ${HOME_STATUS})"
|
||
else
|
||
print_warning "首頁回傳 HTTP ${HOME_STATUS}"
|
||
fi
|
||
|
||
# 完成
|
||
print_header "部署完成!"
|
||
echo ""
|
||
echo -e "${GREEN}┌─────────────────────────────────────────────────────────────┐${NC}"
|
||
echo -e "${GREEN}│ 🎉 UAT Docker 部署成功! │${NC}"
|
||
echo -e "${GREEN}├─────────────────────────────────────────────────────────────┤${NC}"
|
||
echo -e "${GREEN}│ 存取網址: http://${UAT_HOST}:5000 │${NC}"
|
||
echo -e "${GREEN}│ 容器名稱: ${CONTAINER_NAME} │${NC}"
|
||
echo -e "${GREEN}│ 映像名稱: ${IMAGE_NAME}:latest │${NC}"
|
||
echo -e "${GREEN}└─────────────────────────────────────────────────────────────┘${NC}"
|
||
echo ""
|
||
echo -e "${CYAN}常用指令:${NC}"
|
||
echo -e " 查看日誌: ssh ${UAT_USER}@${UAT_HOST} 'docker logs -f ${CONTAINER_NAME}'"
|
||
echo -e " 重啟容器: ssh ${UAT_USER}@${UAT_HOST} 'docker restart ${CONTAINER_NAME}'"
|
||
echo -e " 停止容器: ssh ${UAT_USER}@${UAT_HOST} 'docker stop ${CONTAINER_NAME}'"
|
||
echo ""
|
||
}
|
||
|
||
# 顯示使用說明
|
||
usage() {
|
||
echo "使用方式: $0 [選項]"
|
||
echo ""
|
||
echo "選項:"
|
||
echo " deploy 執行完整部署 (預設)"
|
||
echo " status 檢查 UAT 容器狀態"
|
||
echo " logs 查看容器日誌"
|
||
echo " restart 重啟容器"
|
||
echo " stop 停止容器"
|
||
echo " help 顯示此說明"
|
||
echo ""
|
||
}
|
||
|
||
# 檢查狀態
|
||
check_status() {
|
||
print_header "UAT Docker 容器狀態"
|
||
ssh ${UAT_USER}@${UAT_HOST} "docker ps -a --filter name=${CONTAINER_NAME} --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"
|
||
echo ""
|
||
print_step "磁碟空間:"
|
||
ssh ${UAT_USER}@${UAT_HOST} "df -h | head -3"
|
||
}
|
||
|
||
# 查看日誌
|
||
view_logs() {
|
||
print_header "UAT Docker 容器日誌 (最近 100 行)"
|
||
ssh ${UAT_USER}@${UAT_HOST} "docker logs --tail 100 ${CONTAINER_NAME}"
|
||
}
|
||
|
||
# 重啟容器
|
||
restart_container() {
|
||
print_header "重啟 UAT Docker 容器"
|
||
ssh ${UAT_USER}@${UAT_HOST} "docker restart ${CONTAINER_NAME}"
|
||
print_success "容器已重啟"
|
||
}
|
||
|
||
# 停止容器
|
||
stop_container() {
|
||
print_header "停止 UAT Docker 容器"
|
||
ssh ${UAT_USER}@${UAT_HOST} "docker stop ${CONTAINER_NAME}"
|
||
print_success "容器已停止"
|
||
}
|
||
|
||
# 主程式
|
||
case "${1:-deploy}" in
|
||
deploy)
|
||
deploy
|
||
;;
|
||
status)
|
||
check_status
|
||
;;
|
||
logs)
|
||
view_logs
|
||
;;
|
||
restart)
|
||
restart_container
|
||
;;
|
||
stop)
|
||
stop_container
|
||
;;
|
||
help|--help|-h)
|
||
usage
|
||
;;
|
||
*)
|
||
print_error "未知選項: $1"
|
||
usage
|
||
exit 1
|
||
;;
|
||
esac
|