Files
ewoooc/docs/runbooks/aider-heal-110-setup-sop.md

203 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AiderHeal 110 主機部署 SOPADR-020
> 解決 2026-05-03 發現的 AiderHeal 100% no-op 根因110 主機上 `AIDER_REPO_PATH` (`/home/wooo/ewoooc`) **不存在**,所有 `cd` 立刻失敗,`|| true` 吞掉錯誤後整條 pipeline 走完卻 0 次 push。
>
> 本 SOP 設定一次後永久生效,需統帥手動執行(牽涉 SSH key 部署 + Gitea push 權限驗證)。
---
## 前置確認
| # | 檢查項 | 命令 |
|---|--------|------|
| 1 | 110 主機可達 | `ssh wooo@192.168.0.110 hostname` |
| 2 | 110 上是否已有 `~/.ssh/autoheal_id_ed25519` | `ssh wooo@192.168.0.110 'ls -la ~/.ssh/autoheal*'` |
| 3 | 188 容器內 `config/autoheal_id_ed25519` 是否存在 | `ssh ollama@192.168.0.188 'ls -la /home/ollama/momo-pro-system/config/autoheal*'` |
| 4 | Gitea 上該 ssh key 是否已加為 deploy keywrite 權限)| Gitea → wooo/ewoooc → Settings → Deploy Keys |
**若 #2 #3 都 OK 且 #4 已加** → 直接跳到「步驟 2 clone repo」
**若 #2 缺 key** → 走「步驟 1 部署 SSH Key」
**若 #4 沒加** → 走「步驟 3 加 Gitea Deploy Key」
---
## 步驟 1部署 SSH Key 到 110 主機
容器內已有的 key 同步到 110作為 110 push 回 Gitea 的身份。
```bash
# 從 188 取出私鑰container mount 點)
ssh ollama@192.168.0.188 'cat /home/ollama/momo-pro-system/config/autoheal_id_ed25519' \
| ssh wooo@192.168.0.110 'umask 077 && cat > ~/.ssh/autoheal_id_ed25519'
# 取公鑰
ssh ollama@192.168.0.188 'cat /home/ollama/momo-pro-system/config/autoheal_id_ed25519.pub' \
| ssh wooo@192.168.0.110 'cat > ~/.ssh/autoheal_id_ed25519.pub'
# 設權限
ssh wooo@192.168.0.110 'chmod 600 ~/.ssh/autoheal_id_ed25519 && chmod 644 ~/.ssh/autoheal_id_ed25519.pub'
# 在 ~/.ssh/config 加 host alias 讓 git 自動用此 key
ssh wooo@192.168.0.110 'cat >> ~/.ssh/config << "EOF"
Host gitea-autoheal
HostName 192.168.0.110
Port 3022
User git
IdentityFile ~/.ssh/autoheal_id_ed25519
IdentitiesOnly yes
EOF
chmod 600 ~/.ssh/config'
```
> **Port 3022 確認**:用 `ssh wooo@192.168.0.110 'docker ps | grep gitea'` 看 Gitea SSH port預設 3022 但可能不同。
---
## 步驟 2在 110 上 clone repo 到 `/home/wooo/ewoooc`(直接 SSH clone
> 注意:**從一開始就用 SSH clone**,避免 HTTP clone 在 private repo 卡帳密 prompt + 跟步驟 1 部署的 key 不關聯。先確認 Gitea SSH port預設 3022 但可能被改):
>
> ```bash
> ssh wooo@192.168.0.110 'docker ps --format "{{.Ports}}" | grep gitea'
> ```
>
> 從輸出找到 `0.0.0.0:NNN->22/tcp` 的 NNN 即為 Gitea SSH port。下方用 3022 為例,**請依實況替換**。
```bash
ssh wooo@192.168.0.110 << 'EOF'
set -e
cd ~
# 防呆:如果 ewoooc 已存在但不是 git repo可能舊垃圾先備份
if [ -d ewoooc ] && [ ! -d ewoooc/.git ]; then
mv ewoooc ewoooc.bak.$(date +%s)
fi
# 直接 SSH clone複用步驟 1 部署的 key + ~/.ssh/config 的 gitea-autoheal alias
if [ ! -d ewoooc/.git ]; then
git clone gitea-autoheal:wooo/ewoooc.git ewoooc
fi
cd ewoooc
# 設 git identity 讓 AiderHeal commit 有可識別作者
git config user.name "AiderHeal"
git config user.email "autoheal@wooo.work"
# 確認 remote 走 SSHgitea-autoheal alias 自帶正確 port + key
git remote -v
git log --oneline -3
EOF
```
驗證:應印出 `origin gitea-autoheal:wooo/ewoooc.git`fetch+push 兩行)和最近 3 個 commit。
> **若 clone 失敗報 `Permission denied (publickey)`**:步驟 3 的 Gitea Deploy Key 還沒加或沒勾 write access先回去處理步驟 3。
---
## 步驟 3在 Gitea 加 Deploy Key若 #4 沒加)
1. 取公鑰:
```bash
ssh wooo@192.168.0.110 'cat ~/.ssh/autoheal_id_ed25519.pub'
```
2. Gitea Web UI
- 開 `http://192.168.0.110:3001/wooo/ewoooc/settings/keys`
- Add Deploy Key
- Title: `AiderHeal 110 host`
- Key: 貼上 #1 的公鑰
- **勾選 `Allow write access`**(必要!否則只能 fetch 不能 push
- Add Key
---
## 步驟 4端到端驗證
### 4a. 110 上手動測試 push 鏈
```bash
ssh wooo@192.168.0.110 << 'EOF'
cd ~/ewoooc
git fetch origin main
git status
EOF
```
預期:`fetch` 不報錯,`status` 顯示 `Your branch is up to date`。
### 4b. 從 188 容器測試 SSH 鏈(模擬 AiderHeal preflight
> 早期版本曾用 `docker exec ... bash -c "ssh ... \"...\""` 三層引號,內層雙引號會被中層吃掉,導致 `&& echo PREFLIGHT_OK` 變成本地 echo 而非 remote echo —— **永遠 false positive**。改用 heredoc + 單引號嵌套保護:
```bash
ssh ollama@192.168.0.188 << 'OUTER'
docker exec momo-pro-system bash -c '
ssh -i /app/config/autoheal_id_ed25519 \
-o StrictHostKeyChecking=no \
wooo@192.168.0.110 "test -d /home/wooo/ewoooc/.git && echo PREFLIGHT_OK"
'
OUTER
```
預期輸出:`PREFLIGHT_OK`**從遠端 110 印出**,非本地)。
驗證真假:故意把 path 寫錯一個字母,應該 **0 輸出**(不該印 PREFLIGHT_OK
### 4c. 觸發 AiderHeal pipeline 觀察
任意推一個會被 Hermes 找到 finding 的 commit或統帥 push 一個下次自然有 finding 的 commit等 2 分鐘後查:
```bash
# 看是否有 AiderHeal 簽名的新 commit
git fetch origin main && git log --pretty='%h | %an | %s' origin/main -5
```
預期:看到 author 是 `AiderHeal` 或 commit message 開頭 `fix(autoheal):` 的新 commit。
### 4d. 看容器 log
```bash
ssh ollama@192.168.0.188 'docker logs momo-pro-system --since 10m 2>&1 | grep -E "event=(heal_start|aider_exec|push_ok|preflight_failed|setup_failed)"'
```
預期:`event=heal_start` → `event=aider_exec`(停 1060s→ `event=push_ok` 連貫出現,**不應**看到 `event=preflight_failed`。
---
## 故障排除
| 症狀 | 可能原因 | 排查 |
|------|---------|------|
| `event=preflight_failed` | 110 上 `~/ewoooc` 不存在 / 不是 git repo | 重跑步驟 2 |
| `event=setup_failed` 顯示 `Permission denied (publickey)` | Gitea deploy key 未加 / write 權限沒勾 | 檢查步驟 3 |
| `event=push_failed` 顯示 `remote: hook declined` | Gitea 設 protected branch | 在 Gitea 把 main 從 protected 移除(或加 deploy key 為例外)|
| `event=no_diff` 但 aider 確實看到問題 | aider 模型品質不佳qwen2.5-coder:7b 太小)| 改 `AIDER_MODEL` env例如 `ollama/deepseek-coder-v2:16b`;需 110 上有對應 model |
| `event=diff_too_large` 連續發生 | finding 牽涉檔案 > 50 行修改 | 調 `AIDER_MAX_DIFF_LINES` env但建議保留 50 作 ADR-020 安全網 |
---
## 安全護欄回顧ADR-020
| L | 機制 | 觸發點 |
|---|------|-------|
| L0 | preflight 路徑檢查 | `aider_heal_executor.py:execute_code_fix` 白名單通過後 |
| L1 | 檔案白名單 `^(services\|routes\|database)/(?:[a-zA-Z0-9_]+/)*[a-zA-Z0-9_]+\.py$`,允許子目錄但不允許 `tests/` | `ALLOWED_FILE_PATTERN` |
| L2 | diff > 50 行拒絕 push | `AIDER_MAX_DIFF_LINES` |
| L3 | 每小時最多 5 次 CODE_FIX | `_enforce_rate_limit` |
| L4 | health check 失敗自動 git revert | `_revert_last_commit` |
| L5 | Telegram 通知(成功/失敗/回滾)| `_notify_telegram` → EventRouter |
主開關:`CODE_REVIEW_AUTO_FIX_ENABLED=false`docker-compose env即時切斷整條鏈。
---
## 完成後更新
- [ ] 110 上 `~/ewoooc` 存在且 `git remote -v` 顯示走 SSH push
- [ ] Gitea deploy key 已加write access 勾選
- [ ] 步驟 4b 印出 `PREFLIGHT_OK`
- [ ] 至少一次自然觸發 AiderHeal 後看到 `fix(autoheal):` commit
- [ ] 通知 Claude 把 memory `feedback_code_review_autoheal.md` 的「待觀察」段刪掉,標記 AiderHeal 執行層也驗證完成