# RunBook: Phase D — Sentry Comment 回寫啟動指南 > **類型**: 操作型 RunBook > **優先級**: 🔴 P0(功能框架已建,只缺 Token 配置) > **建立**: 2026-03-29 12:35 (台北) > **建立者**: Antigravity > **工時預估**: 1.5–2 小時 > **前置條件**: AWOOOI API 正常運行 (`/api/v1/health` 返回 200) --- ## 背景與現況 ### 🔍 精確現況診斷 `sentry_webhook.py` 的 `post_sentry_comment()` 函式已實作完整邏輯: ``` sentry_webhook.py:251 → 呼叫 post_sentry_comment() sentry_service.py:206 → post_issue_comment() 已實作 POST /api/0/issues/{id}/comments/ sentry_service.py:223 → 若 SENTRY_AUTH_TOKEN 為空,直接 return None 並 warning ``` **唯一阻塞點**:`settings.SENTRY_AUTH_TOKEN` 環境變數未設定,導致 comment 靜默跳過。 ### 資料流確認 ``` Sentry Issue 觸發 ↓ /api/v1/webhooks/sentry/error (sentry_webhook.py) ↓ analyze_and_comment() [Background Task] ↓ call_openclaw_analyzer() → OpenClaw AI 分析 ↓ create_sentry_approval() → 建立 Approval ✅ 已運作 ↓ send_sentry_telegram_alert()→ Telegram 通知 ✅ 已運作 ↓ post_sentry_comment() → ❌ SENTRY_AUTH_TOKEN 缺失,靜默跳過 ``` --- ## Step 1: 取得 Sentry API Token ### 1.1 登入 Sentry 後台 ``` 瀏覽器開啟:http://192.168.0.110:9000 帳號:參見 docs/security/SECRETS_REFERENCE.md ``` ### 1.2 建立 API Token ``` 路徑:設定 → API → Auth Tokens → Create New Token 權限設定: ☑ project:read ☑ project:write ☑ issues:write ← 必須勾選,否則無法回寫 comment ☑ event:read Token 名稱建議:awoooi-openclaw-comment-writer ``` ### 1.3 記錄 Token(請勿存入代碼庫!) ```bash # 暫存到環境變數(本機測試用) export SENTRY_AUTH_TOKEN="sentry_xxx..." # 驗證 Token 有效性 curl -s http://192.168.0.110:9000/api/0/organizations/ \ -H "Authorization: Bearer $SENTRY_AUTH_TOKEN" | python3 -m json.tool | head -20 # 預期看到 organization 列表,無 401 ``` --- ## Step 2: 注入 GitHub Secrets(CD 自動化) ### 2.1 加入 GitHub Repository Secrets ``` 路徑:GitHub → owenhytsai/awoooi → Settings → Secrets → Actions 新增以下 Secrets: 名稱:SENTRY_AUTH_TOKEN 值:步驟 1.2 取得的 Token ``` ### 2.2 更新 K8s Secret(手動注入生產環境) ```bash # 在 192.168.0.120(K3s Master)執行 kubectl patch secret awoooi-secrets -n awoooi-prod \ --patch="{\"data\":{\"SENTRY_AUTH_TOKEN\":\"$(echo -n 'YOUR_TOKEN' | base64)\"}}" # 驗證 kubectl get secret awoooi-secrets -n awoooi-prod -o jsonpath='{.data.SENTRY_AUTH_TOKEN}' | base64 -d ``` ### 2.3 更新 k8s/awoooi-prod/03-secrets.yaml(模板) ```yaml # k8s/awoooi-prod/03-secrets.yaml # 新增以下欄位(使用 CD 自動注入,非硬編碼) stringData: # ... 現有欄位 ... SENTRY_AUTH_TOKEN: "${SENTRY_AUTH_TOKEN}" # CD 自動注入 ``` --- ## Step 3: 更新 CD Workflow 自動注入 ```yaml # .github/workflows/cd.yaml # 在 "Inject K8s Secrets" 步驟中新增 SENTRY_AUTH_TOKEN - name: Inject K8s Secrets run: | kubectl patch secret awoooi-secrets -n awoooi-prod \ --patch="{\"data\":{ \"OPENCLAW_TG_BOT_TOKEN\":\"$(echo -n '${{ secrets.OPENCLAW_TG_BOT_TOKEN }}' | base64)\", \"OPENCLAW_TG_CHAT_ID\":\"$(echo -n '${{ secrets.OPENCLAW_TG_CHAT_ID }}' | base64)\", \"SENTRY_AUTH_TOKEN\":\"$(echo -n '${{ secrets.SENTRY_AUTH_TOKEN }}' | base64)\" }}" ``` --- ## Step 4: 驗證 Sentry Comment 功能 ### 4.1 本地單元測試(快速驗證) ```bash cd /Users/ogt/awoooi source .env # 設定測試 Token export SENTRY_AUTH_TOKEN="你的真實 Token" export SENTRY_SELF_HOSTED_URL="http://192.168.0.110:9000" # 用 Python 直接測試 SentryService python3 -c " import asyncio import sys sys.path.insert(0, 'apps/api/src') from services.sentry_service import SentryService async def test(): svc = SentryService( base_url='http://192.168.0.110:9000', auth_token='$SENTRY_AUTH_TOKEN' ) # 先列出 Issues 找一個真實 ID issues = await svc.list_issues(project='awoooi-api', limit=3) if issues: issue_id = issues[0]['id'] print(f'找到 Issue: {issue_id}') result = await svc.post_issue_comment( issue_id=issue_id, text='🤖 **AWOOOI 測試** - Sentry Comment 回寫功能正常運作。' ) print(f'Comment 結果: {result}') else: print('無 Issue 可測試') asyncio.run(test()) " ``` ### 4.2 E2E 端對端驗證(生產環境) ```bash # 1. 在 Sentry 手動觸發一個測試 Issue curl -X POST http://localhost:8000/api/v1/webhooks/sentry/error \ -H "Content-Type: application/json" \ -d '{ "action": "triggered", "data": { "issue": { "id": "TEST-001", "title": "AWOOOI Comment 功能測試", "level": "error", "culprit": "test.py:1", "firstSeen": "2026-03-29T12:00:00Z", "count": 1, "project": {"slug": "awoooi-api"} }, "event": { "message": "這是一個測試錯誤", "platform": "python" } } }' # 預期回應 # {"status": "accepted", "issue_id": "TEST-001", "message": "Analysis scheduled"} # 2. 等待 60 秒後(OpenClaw 分析需時) sleep 60 # 3. 到 Sentry UI 的 Issue 中確認是否有 AI 分析 Comment # http://192.168.0.110:9000/organizations/sentry/issues/TEST-001/ ``` ### 4.3 確認日誌 ```bash # 查看 API Pod 日誌 kubectl logs -n awoooi-prod \ $(kubectl get pod -n awoooi-prod -l app=awoooi-api -o name | head -1) \ --tail=50 | grep -i sentry_comment # 預期看到 # sentry_comment_posted issue_id=xxx comment_id=12345 ``` --- ## Step 5: 部署與驗收 ```bash # 觸發 CD git add k8s/awoooi-prod/03-secrets.yaml .github/workflows/cd.yaml git commit -m "feat(sentry): enable comment write-back via SENTRY_AUTH_TOKEN injection" git push origin main # 確認 CD 成功 gh run list --workflow=cd.yaml --limit 1 # 確認 Pod 有新 Token kubectl exec -n awoooi-prod \ $(kubectl get pod -n awoooi-prod -l app=awoooi-api -o name | head -1) \ -- env | grep SENTRY_AUTH_TOKEN ``` --- ## 驗收標準 | 項目 | 通過條件 | |------|---------| | K8s Secret 已注入 | `kubectl get secret` 確認 `SENTRY_AUTH_TOKEN` 不為空 | | Token 有效 | Sentry API `/api/0/organizations/` 返回 200 | | Comment 回寫 | Sentry Issue 中有「AI 錯誤分析」Comment | | 日誌正常 | `sentry_comment_posted` 日誌出現,無 `sentry_comment_failed` | | 頻率統計 | Comment 含「頻率統計」表格(24h 次數 > 1 時顯示)| --- ## 常見問題排除 | 症狀 | 診斷指令 | 解法 | |------|---------|------| | `sentry_comment_skipped` 日誌 | `env \| grep SENTRY_AUTH_TOKEN` | Secret 未注入,重跑 Step 3 | | `sentry_api_unauthorized` | 手動 curl Sentry API | Token 權限不足,重新建立 | | `sentry_api_timeout` | `curl -v http://192.168.0.110:9000/` | Sentry 服務本身異常 | | OpenClaw 分析失敗 | `curl http://192.168.0.188:8089/health` | OpenClaw 服務需重啟 |