From d06c7016dcdc93b5625ea62b8bee1debf4bba7d4 Mon Sep 17 00:00:00 2001 From: OoO Date: Thu, 30 Apr 2026 23:24:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(cd):=20=E4=BF=AE=E5=BE=A9=20sync=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC=20mount=20drift?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/cd.yaml | 21 ++++++++++++++++----- CONSTITUTION.md | 2 +- app.py | 4 ++-- config.py | 2 +- docs/memory/history_logs.md | 1 + tests/test_cd_health_check.py | 11 ++++++++++- 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index 177886b..82e8780 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -175,12 +175,23 @@ jobs: # ROOT CAUSE FIX (2026-04-28): `up -d` 確保容器不存在時可自動 create。 # ZERO-DOWNTIME SYNC (2026-04-30): app 用 Gunicorn HUP 熱重載 workers, # 不重啟 momo-pro-system 容器,避免一般 Python/模板同步造成短暫 502。 + # MOUNT DRIFT GUARD (2026-04-30): 舊容器若尚未套用 app.py/config.py bind mount, + # health/version 會卡在 image 內舊檔;只在偵測到 drift 時 force-recreate app。 ssh -i ~/.ssh/id_deploy ollama@192.168.0.188 \ - "cd /home/ollama/momo-pro && \ - docker compose up -d --no-deps momo-app scheduler telegram-bot && \ - docker kill -s HUP momo-pro-system && \ - docker compose restart scheduler telegram-bot && \ - echo '✅ Sync 已套用(app 熱重載;scheduler/telegram-bot 已重啟)'" + "cd /home/ollama/momo-pro && bash -s" <<'REMOTE_SYNC' + set -e + docker compose up -d --no-deps scheduler telegram-bot + if docker inspect momo-pro-system --format '{{range .Mounts}}{{println .Destination}}{{end}}' | grep -qx '/app/app.py' \ + && docker inspect momo-pro-system --format '{{range .Mounts}}{{println .Destination}}{{end}}' | grep -qx '/app/config.py'; then + docker compose up -d --no-deps momo-app + else + echo '⚠️ momo-app mount drift detected; recreating app container once to apply bind mounts' + docker compose up -d --no-deps --force-recreate momo-app + fi + docker kill -s HUP momo-pro-system + docker compose restart scheduler telegram-bot + echo '✅ Sync 已套用(app 熱重載;scheduler/telegram-bot 已重啟)' +REMOTE_SYNC # ── 模式 B:重建 Docker Image(Dockerfile / requirements.txt 變動) ── - name: 同步所有檔案並重建 Image diff --git a/CONSTITUTION.md b/CONSTITUTION.md index 63aedc4..6cddafa 100644 --- a/CONSTITUTION.md +++ b/CONSTITUTION.md @@ -2,7 +2,7 @@ > 本文件定義專案開發的核心準則與不可違反的規範 > **建立日期**: 2026-01-12 -> **當前版本**: V10.30 (OpenClaw 選單鍵盤模組化) +> **當前版本**: V10.31 (CD sync app/config mount drift guard) > **最後更新**: 2026-04-30 --- diff --git a/app.py b/app.py index bfd80d6..3aa6560 100644 --- a/app.py +++ b/app.py @@ -95,8 +95,8 @@ except Exception as e: sys_log.error(f"無法檢測磁碟空間: {e}") # 🚩 系統版本定義 (備份與顯示用) -# 🚩 2026-04-30 V10.30: OpenClaw menu keyboard builders modularized -SYSTEM_VERSION = "V10.30" +# 🚩 2026-04-30 V10.31: CD sync app/config mount drift guard +SYSTEM_VERSION = "V10.31" # ========================================== # 🔒 SQL Injection 防護函數 diff --git a/config.py b/config.py index eab2991..c08ffde 100644 --- a/config.py +++ b/config.py @@ -254,7 +254,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.30" +SYSTEM_VERSION = "V10.31" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/docs/memory/history_logs.md b/docs/memory/history_logs.md index 5218ad4..b94f5f1 100644 --- a/docs/memory/history_logs.md +++ b/docs/memory/history_logs.md @@ -52,6 +52,7 @@ - **Gitea runner label 隔離**: EWOOOC CD workflow 改用 `ewoooc-host`;110 的 `/home/wooo/act-runner` runner config 必須只宣告 `ewoooc-host`,避免 user-level runner 混接 AWOOOI workflow。 - **CD sync hot reload**: 一般 Python/模板同步不再 `restart momo-app`,改為 `docker kill -s HUP momo-pro-system` 讓 Gunicorn 熱重載 workers,只重啟 scheduler / telegram-bot;Gunicorn 關閉 `preload_app`,確保 HUP 後 workers 會 import 新版 app code。 - **OpenClaw Bot 第二刀拆分**: Inline Keyboard builders 移到 `services/openclaw_bot/menu_keyboards.py`,透過 `configure_menu_keyboards()` 注入 `latest_date/_GOALS/TAIPEI_TZ`,route 檔下降到 5,240 行並補選單回歸測試。 +- **CD sync mount drift guard**: 發現舊 app 容器未掛載 `app.py/config.py` 時,rsync 後服務檔已更新但 `/health` 版本仍卡 image 內舊檔;CD sync 會檢查 mount,僅 drift 時一次性 recreate momo-app,其餘維持 HUP 熱重載。 ### 2026-04-28~29:Phase 3e 重構大戰 + daily_sales cache 隱形 bug 根除 - **app.py 縮減 -10.8%**: 7,386 → 6,590 行,11 commits 全綠零 502。 diff --git a/tests/test_cd_health_check.py b/tests/test_cd_health_check.py index 5f715af..c593538 100644 --- a/tests/test_cd_health_check.py +++ b/tests/test_cd_health_check.py @@ -26,13 +26,22 @@ def test_cd_sync_mode_hot_reloads_app_without_container_restart(): workflow = CD_WORKFLOW.read_text(encoding="utf-8") gunicorn_config = (ROOT / "gunicorn.conf.py").read_text(encoding="utf-8") - assert "docker compose up -d --no-deps momo-app scheduler telegram-bot" in workflow + assert "docker compose up -d --no-deps momo-app" in workflow assert "docker kill -s HUP momo-pro-system" in workflow assert "docker compose restart scheduler telegram-bot" in workflow assert "docker compose restart momo-app" not in workflow assert "preload_app = False" in gunicorn_config +def test_cd_sync_mode_repairs_app_mount_drift_once(): + workflow = CD_WORKFLOW.read_text(encoding="utf-8") + + assert "momo-app mount drift detected" in workflow + assert "grep -qx '/app/app.py'" in workflow + assert "grep -qx '/app/config.py'" in workflow + assert "docker compose up -d --no-deps --force-recreate momo-app" in workflow + + def test_cd_rebuild_builds_image_before_stopping_running_containers(): workflow = CD_WORKFLOW.read_text(encoding="utf-8")