Files
ewoooc/sync_env.sh
ogt 1b4f3a7bbe
Some checks failed
CD Pipeline / deploy (push) Failing after 59s
feat: EwoooC 初始化 — 完整專案推版至 Gitea
- 建立 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>
2026-04-19 01:21:13 +08:00

362 lines
12 KiB
Bash
Executable File

#!/bin/bash
# ============================================================================
# MOMO Pro System - 多環境同步腳本
# 支援開發 (DEV)、UAT、正式 (PROD) 三環境同步
# ============================================================================
set -e
# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
# 環境配置
DEV_PATH="/Users/ogt/momo_pro_system"
UAT_HOST="wooo@192.168.0.110"
UAT_PATH="/home/wooo/momo_pro_system"
PROD_HOST="momo-server"
PROD_ZONE="asia-east1-a"
PROD_PATH="/home/ogt/momo_pro_system"
# 密碼檔案(避免硬編碼)
UAT_PASS_FILE="$HOME/.momo_uat_pass"
# 排除的檔案和目錄
EXCLUDES="--exclude='venv' --exclude='__pycache__' --exclude='*.pyc' --exclude='.git' --exclude='logs/*.log' --exclude='backups' --exclude='.DS_Store'"
# ============================================================================
# 工具函式
# ============================================================================
print_header() {
echo -e "\n${CYAN}========================================${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}========================================${NC}\n"
}
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}[OK]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARN]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
get_uat_pass() {
if [ -f "$UAT_PASS_FILE" ]; then
# V-Fix: 使用 xargs 去除可能存在的換行符號,避免 SSH 失敗
cat "$UAT_PASS_FILE" | xargs
else
read -sp "請輸入 UAT 密碼: " pass
echo "$pass"
fi
}
ssh_uat() {
local pass=$(get_uat_pass)
sshpass -p "$pass" ssh -o StrictHostKeyChecking=accept-new $UAT_HOST "$1"
}
scp_to_uat() {
local pass=$(get_uat_pass)
sshpass -p "$pass" scp -r "$1" "$UAT_HOST:$2"
}
scp_to_uat_2() {
local pass=$(get_uat_pass)
sshpass -p "$pass" scp -r "$1" "$UAT_HOST_2:$2"
}
# ============================================================================
# 環境狀態檢查
# ============================================================================
check_all_status() {
print_header "檢查所有環境狀態"
echo -e "${YELLOW}📍 開發環境 (DEV) - 本機 Mac${NC}"
echo " 路徑: $DEV_PATH"
local dev_app_mtime=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$DEV_PATH/app.py" 2>/dev/null || echo "N/A")
local dev_db_size=$(ls -lh "$DEV_PATH/data/momo_database.db" 2>/dev/null | awk '{print $5}' || echo "N/A")
echo " app.py 修改時間: $dev_app_mtime"
echo " 資料庫大小: $dev_db_size"
echo ""
echo -e "${YELLOW}📍 UAT 環境 - VMWare VM${NC}"
echo " 主機: $UAT_HOST"
echo " 網址: https://mo.wooo.work"
local uat_status=$(ssh_uat "systemctl is-active momo 2>/dev/null" 2>/dev/null || echo "N/A")
local uat_app_mtime=$(ssh_uat "stat -c '%y' $UAT_PATH/app.py 2>/dev/null | cut -d'.' -f1" 2>/dev/null || echo "N/A")
local uat_db_size=$(ssh_uat "ls -lh $UAT_PATH/data/momo_database.db 2>/dev/null | awk '{print \$5}'" 2>/dev/null || echo "N/A")
echo " 服務狀態: $uat_status"
echo " app.py 修改時間: $uat_app_mtime"
echo " 資料庫大小: $uat_db_size"
echo ""
echo -e "${YELLOW}📍 正式環境 (PROD) - GCP VM${NC}"
echo " 主機: $PROD_HOST ($PROD_ZONE)"
echo " 網址: https://mo.wooo.work"
local prod_status=$(gcloud compute ssh $PROD_HOST --zone=$PROD_ZONE --command="systemctl is-active momo 2>/dev/null" 2>/dev/null || echo "N/A")
local prod_app_mtime=$(gcloud compute ssh $PROD_HOST --zone=$PROD_ZONE --command="stat -c '%y' $PROD_PATH/app.py 2>/dev/null | cut -d'.' -f1" 2>/dev/null || echo "N/A")
local prod_db_size=$(gcloud compute ssh $PROD_HOST --zone=$PROD_ZONE --command="ls -lh $PROD_PATH/data/momo_database.db 2>/dev/null | awk '{print \$5}'" 2>/dev/null || echo "N/A")
echo " 服務狀態: $prod_status"
echo " app.py 修改時間: $prod_app_mtime"
echo " 資料庫大小: $prod_db_size"
}
# ============================================================================
# 同步程式碼
# ============================================================================
sync_code_to_uat() {
print_header "同步程式碼: DEV → UAT"
print_info "打包程式碼..."
cd "$DEV_PATH"
tar czf /tmp/momo_code_sync.tar.gz \
--exclude='venv' --exclude='__pycache__' --exclude='*.pyc' \
--exclude='.git' --exclude='logs/*.log' --exclude='backups' \
--exclude='.DS_Store' --exclude='data/*.db' \
*.py *.html *.md database/ static/ services/ config/ 2>/dev/null || true
print_info "上傳到 UAT..."
scp_to_uat /tmp/momo_code_sync.tar.gz "$UAT_PATH/"
print_info "在 UAT 解壓並重啟服務..."
local pass=$(get_uat_pass)
ssh_uat "cd $UAT_PATH && tar xzf momo_code_sync.tar.gz && rm momo_code_sync.tar.gz && echo \"$pass\" | sudo -S systemctl restart momo"
print_success "程式碼同步到 UAT 完成!"
}
sync_code_to_prod() {
print_header "同步程式碼: DEV → PROD"
print_info "打包程式碼..."
cd "$DEV_PATH"
tar czf /tmp/momo_code_sync.tar.gz \
--exclude='venv' --exclude='__pycache__' --exclude='*.pyc' \
--exclude='.git' --exclude='logs/*.log' --exclude='backups' \
--exclude='.DS_Store' --exclude='data/*.db' \
*.py *.html *.md database/ static/ services/ config/ 2>/dev/null || true
print_info "上傳到 PROD..."
gcloud compute scp /tmp/momo_code_sync.tar.gz $PROD_HOST:$PROD_PATH/ --zone=$PROD_ZONE
print_info "在 PROD 解壓並重啟服務..."
gcloud compute ssh $PROD_HOST --zone=$PROD_ZONE --command="cd $PROD_PATH && tar xzf momo_code_sync.tar.gz && rm momo_code_sync.tar.gz && sudo systemctl restart momo"
print_success "程式碼同步到 PROD 完成!"
}
sync_code_uat_to_prod() {
print_header "同步程式碼: UAT → PROD"
print_info "從 UAT 打包程式碼..."
ssh_uat "cd $UAT_PATH && tar czf /tmp/momo_uat_code.tar.gz --exclude='venv' --exclude='__pycache__' --exclude='*.pyc' --exclude='data/*.db' *.py *.html *.md database/ static/ services/ config/ 2>/dev/null || true"
print_info "下載到本機..."
local pass=$(get_uat_pass)
sshpass -p "$pass" scp "$UAT_HOST:/tmp/momo_uat_code.tar.gz" /tmp/
print_info "上傳到 PROD..."
gcloud compute scp /tmp/momo_uat_code.tar.gz $PROD_HOST:$PROD_PATH/ --zone=$PROD_ZONE
print_info "在 PROD 解壓並重啟服務..."
gcloud compute ssh $PROD_HOST --zone=$PROD_ZONE --command="cd $PROD_PATH && tar xzf momo_uat_code.tar.gz && rm momo_uat_code.tar.gz && sudo systemctl restart momo"
print_success "UAT 程式碼同步到 PROD 完成!"
}
# ============================================================================
# 同步資料庫
# ============================================================================
sync_db_to_uat() {
print_header "同步資料庫: DEV → UAT"
print_info "上傳資料庫到 UAT..."
scp_to_uat "$DEV_PATH/data/momo_database.db" "$UAT_PATH/data/"
print_info "重啟 UAT 服務..."
local pass=$(get_uat_pass)
ssh_uat "echo \"$pass\" | sudo -S systemctl restart momo"
print_success "資料庫同步到 UAT 完成!"
}
sync_db_to_prod() {
print_header "同步資料庫: DEV → PROD"
print_info "上傳資料庫到 PROD..."
gcloud compute scp "$DEV_PATH/data/momo_database.db" $PROD_HOST:$PROD_PATH/data/ --zone=$PROD_ZONE
print_info "重啟 PROD 服務..."
gcloud compute ssh $PROD_HOST --zone=$PROD_ZONE --command="sudo systemctl restart momo"
print_success "資料庫同步到 PROD 完成!"
}
sync_db_prod_to_dev() {
print_header "同步資料庫: PROD → DEV"
print_info "備份本機資料庫..."
cp "$DEV_PATH/data/momo_database.db" "$DEV_PATH/data/momo_database_backup_$(date +%Y%m%d_%H%M%S).db"
print_info "從 PROD 下載資料庫..."
gcloud compute scp $PROD_HOST:$PROD_PATH/data/momo_database.db "$DEV_PATH/data/" --zone=$PROD_ZONE
print_success "PROD 資料庫同步到 DEV 完成!"
}
sync_db_prod_to_uat() {
print_header "同步資料庫: PROD → UAT"
print_info "從 PROD 下載資料庫..."
gcloud compute scp $PROD_HOST:$PROD_PATH/data/momo_database.db /tmp/ --zone=$PROD_ZONE
print_info "上傳到 UAT..."
scp_to_uat /tmp/momo_database.db "$UAT_PATH/data/"
print_info "重啟 UAT 服務..."
local pass=$(get_uat_pass)
ssh_uat "echo \"$pass\" | sudo -S systemctl restart momo"
print_success "PROD 資料庫同步到 UAT 完成!"
}
# ============================================================================
# 完整同步
# ============================================================================
sync_all_to_uat() {
print_header "完整同步: DEV → UAT (程式碼 + 資料庫)"
sync_code_to_uat
sync_db_to_uat
print_success "完整同步到 UAT 完成!"
}
sync_all_to_prod() {
print_header "完整同步: DEV → PROD (程式碼 + 資料庫)"
sync_code_to_prod
sync_db_to_prod
print_success "完整同步到 PROD 完成!"
}
sync_all_environments() {
print_header "同步所有環境 (DEV → UAT → PROD)"
sync_all_to_uat
sync_code_uat_to_prod
sync_db_to_prod
print_success "所有環境同步完成!"
}
# ============================================================================
# 主選單
# ============================================================================
show_menu() {
print_header "MOMO Pro System - 多環境同步工具"
echo "請選擇操作:"
echo ""
echo -e "${CYAN}狀態檢查${NC}"
echo " 1) 檢查所有環境狀態"
echo ""
echo -e "${CYAN}程式碼同步${NC}"
echo " 2) DEV → UAT (程式碼)"
echo " 3) DEV → PROD (程式碼)"
echo " 4) UAT → PROD (程式碼)"
echo ""
echo -e "${CYAN}資料庫同步${NC}"
echo " 5) DEV → UAT (資料庫)"
echo " 6) DEV → PROD (資料庫)"
echo " 7) PROD → DEV (資料庫)"
echo " 8) PROD → UAT (資料庫)"
echo ""
echo -e "${CYAN}完整同步${NC}"
echo " 9) DEV → UAT (完整)"
echo " 10) DEV → PROD (完整)"
echo " 11) 同步所有環境"
echo ""
echo " 0) 離開"
echo ""
read -p "請輸入選項 [0-11]: " choice
case $choice in
1) check_all_status ;;
2) sync_code_to_uat ;;
3) sync_code_to_prod ;;
4) sync_code_uat_to_prod ;;
5) sync_db_to_uat ;;
6) sync_db_to_prod ;;
7) sync_db_prod_to_dev ;;
8) sync_db_prod_to_uat ;;
9) sync_all_to_uat ;;
10) sync_all_to_prod ;;
11) sync_all_environments ;;
0) echo "再見!"; exit 0 ;;
*) print_error "無效選項"; show_menu ;;
esac
echo ""
read -p "按 Enter 返回選單..."
show_menu
}
# ============================================================================
# 命令列參數處理
# ============================================================================
case "$1" in
--status)
check_all_status
;;
--code-to-uat)
sync_code_to_uat
;;
--code-to-prod)
sync_code_to_prod
;;
--db-to-uat)
sync_db_to_uat
;;
--db-to-prod)
sync_db_to_prod
;;
--db-from-prod)
sync_db_prod_to_dev
;;
--full-uat)
sync_all_to_uat
;;
--full-prod)
sync_all_to_prod
;;
--sync-all)
sync_all_environments
;;
--help|-h)
echo "使用方式: $0 [選項]"
echo ""
echo "選項:"
echo " --status 檢查所有環境狀態"
echo " --code-to-uat 同步程式碼到 UAT"
echo " --code-to-prod 同步程式碼到 PROD"
echo " --db-to-uat 同步資料庫到 UAT"
echo " --db-to-prod 同步資料庫到 PROD"
echo " --db-from-prod 從 PROD 下載資料庫到 DEV"
echo " --full-uat 完整同步到 UAT"
echo " --full-prod 完整同步到 PROD"
echo " --sync-all 同步所有環境"
echo " --help, -h 顯示此說明"
echo ""
echo "不帶參數執行會顯示互動式選單"
;;
*)
show_menu
;;
esac