diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index 28d7b67..177886b 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -172,14 +172,15 @@ jobs: - name: 重啟容器(Sync 模式) if: steps.deploy_type.outputs.type == 'sync' run: | - # ROOT CAUSE FIX (2026-04-28): 從 `restart` 改為 `up -d` - # restart 對「不存在的容器」會失敗 → 任一外力清掉容器後下次 sync 必爆 502 - # up -d 對不存在容器會自動 create;restart 讓 Python process 重新載入 bind-mounted 檔案 + # ROOT CAUSE FIX (2026-04-28): `up -d` 確保容器不存在時可自動 create。 + # ZERO-DOWNTIME SYNC (2026-04-30): app 用 Gunicorn HUP 熱重載 workers, + # 不重啟 momo-pro-system 容器,避免一般 Python/模板同步造成短暫 502。 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 compose restart momo-app scheduler telegram-bot && \ - echo '✅ 三容器已就緒(app/scheduler/telegram-bot)'" + docker kill -s HUP momo-pro-system && \ + docker compose restart scheduler telegram-bot && \ + echo '✅ Sync 已套用(app 熱重載;scheduler/telegram-bot 已重啟)'" # ── 模式 B:重建 Docker Image(Dockerfile / requirements.txt 變動) ── - name: 同步所有檔案並重建 Image diff --git a/CONSTITUTION.md b/CONSTITUTION.md index 0d841eb..2092f41 100644 --- a/CONSTITUTION.md +++ b/CONSTITUTION.md @@ -2,7 +2,7 @@ > 本文件定義專案開發的核心準則與不可違反的規範 > **建立日期**: 2026-01-12 -> **當前版本**: V10.27 (action_plans schema drift 修復版) +> **當前版本**: V10.28 (CD sync hot reload 降 502 版) > **最後更新**: 2026-04-30 --- diff --git a/app.py b/app.py index 0c20304..577ead3 100644 --- a/app.py +++ b/app.py @@ -95,8 +95,8 @@ except Exception as e: sys_log.error(f"無法檢測磁碟空間: {e}") # 🚩 系統版本定義 (備份與顯示用) -# 🚩 2026-04-30 V10.27: action_plans schema drift repair -SYSTEM_VERSION = "V10.27" +# 🚩 2026-04-30 V10.28: CD sync hot reload without app container restart +SYSTEM_VERSION = "V10.28" # ========================================== # 🔒 SQL Injection 防護函數 diff --git a/config.py b/config.py index 1b5bf15..0e6865e 100644 --- a/config.py +++ b/config.py @@ -254,7 +254,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.27" +SYSTEM_VERSION = "V10.28" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/docs/memory/ai_automation_closure_20260429.md b/docs/memory/ai_automation_closure_20260429.md index 81c3c02..9b6e4c0 100644 --- a/docs/memory/ai_automation_closure_20260429.md +++ b/docs/memory/ai_automation_closure_20260429.md @@ -51,6 +51,7 @@ - Monitoring compose 的 cAdvisor 只需在 `monitoring` network 內提供 `cadvisor:8080` 給 Prometheus,不應綁定 host `8080`,避免與其他服務衝突;blackbox target 需要 `blackbox-exporter` 容器存在於同一 network。 - 2026-04-30 線上驗證:目前 active MOMO UAT blackbox target 只保留 `https://mo.wooo.work`;`momo.wooo.work` 與 `wooo.work` 需等 DNS/Nginx 恢復後再加入 active monitoring。 - 110 Gitea runner 必須只宣告 `ewoooc-host` label;若混入 `ubuntu-latest` / `awoooi-host`,EWOOOC 與 AWOOOI workflows 會互相搶同一個 runner,導致推版卡住或跨專案污染。 +- CD sync 模式應對 `momo-pro-system` 發 Gunicorn `HUP` 熱重載,不重啟 app 容器;scheduler / telegram-bot 才用 compose restart,避免每次一般程式碼推版都產生短暫 502。 - App container 的 runtime `gunicorn.conf.py` 由 `docker-compose.yml` bind mount;若未來改 gunicorn 設定,不應再手動 `docker cp` 作為常態流程。 ## 驗證紀錄 diff --git a/docs/memory/history_logs.md b/docs/memory/history_logs.md index 4844302..b103e79 100644 --- a/docs/memory/history_logs.md +++ b/docs/memory/history_logs.md @@ -50,6 +50,7 @@ - **Active blackbox target 降噪**: 線上 Nginx 與 curl 驗證目前有效 MOMO 入口為 `https://mo.wooo.work`;`momo.wooo.work` 逾時、`wooo.work` DNS 不解析,先從 active UAT blackbox targets 移除,避免舊域名噪音誤導告警。 - **action_plans schema drift 修復**: CodeReview pipeline 寫入 action plan 時發現線上表只有 NemoTron Group B 欄位;啟動期 PostgreSQL metadata repair 會補 `action_type` / `description` / `priority` / `metadata_json` 與 index,恢復 AI code review action plan 閉環。 - **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,降低推版 502 窗口。 ### 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 05665fc..976c28c 100644 --- a/tests/test_cd_health_check.py +++ b/tests/test_cd_health_check.py @@ -22,11 +22,13 @@ def test_cd_health_check_validates_internal_and_external_health(): assert 'internal=$INTERNAL_CODE, external=$EXTERNAL_CODE' in workflow -def test_cd_sync_mode_restarts_after_rsync_to_reload_python_processes(): +def test_cd_sync_mode_hot_reloads_app_without_container_restart(): workflow = CD_WORKFLOW.read_text(encoding="utf-8") assert "docker compose up -d --no-deps momo-app scheduler telegram-bot" in workflow - assert "docker compose restart momo-app scheduler telegram-bot" 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 def test_cd_rebuild_builds_image_before_stopping_running_containers():