feat(phase32): 實作 review_push + gitea_webhook 改用本地 Ollama 審查
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
- local_code_review_service: 新增 review_push() 方法 使用 qwen2.5-coder:7b 審查 push event(非 PR) - gitea_webhook_service: _call_openclaw_push_review 改用本地推理 OpenClaw 無 push-review 端點(404) → 改用 LocalCodeReviewService Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -244,25 +244,31 @@ class GiteaWebhookService:
|
|||||||
files_changed: dict,
|
files_changed: dict,
|
||||||
) -> CodeReviewResult | None:
|
) -> CodeReviewResult | None:
|
||||||
"""
|
"""
|
||||||
呼叫 OpenClaw 進行 Push 代碼審查
|
Phase 32 ADR-067: Ollama qwen2.5-coder:7b push 代碼審查
|
||||||
|
2026-04-10 Claude Sonnet 4.6: OpenClaw 無 push-review 端點 → 改用 Ollama 本地推理
|
||||||
Phase 22 P0 修復: 使用 OpenClawHttpService (2026-03-31)
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from src.services.openclaw_http_service import get_openclaw_http_service
|
from src.services.local_code_review_service import get_local_code_review_service
|
||||||
service = get_openclaw_http_service()
|
svc = get_local_code_review_service()
|
||||||
data = await service.push_review(
|
|
||||||
repo_name=repo_name,
|
branch = ref.split("/")[-1]
|
||||||
ref=ref,
|
commit_msgs = "\n".join(f'- {c["sha"]}: {c["message"]}' for c in commits[:5])
|
||||||
commits=commits,
|
added = files_changed.get("added", [])
|
||||||
files_changed=files_changed,
|
modified = files_changed.get("modified", [])
|
||||||
prefer_local=True,
|
removed = files_changed.get("removed", [])
|
||||||
timeout=120.0,
|
files_summary = (
|
||||||
|
f"Added: {', '.join(added[:5]) or '無'}\n"
|
||||||
|
f"Modified: {', '.join(modified[:5]) or '無'}\n"
|
||||||
|
f"Removed: {', '.join(removed[:5]) or '無'}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if data:
|
result = await svc.review_push(
|
||||||
return CodeReviewResult(**data)
|
repo_name=repo_name,
|
||||||
return None
|
branch=branch,
|
||||||
|
commit_summary=commit_msgs,
|
||||||
|
files_summary=files_summary,
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception("openclaw_push_review_error", error=str(e))
|
logger.exception("openclaw_push_review_error", error=str(e))
|
||||||
|
|||||||
@@ -180,6 +180,49 @@ class LocalCodeReviewService:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("pr_review_db_save_failed", error=str(e))
|
logger.warning("pr_review_db_save_failed", error=str(e))
|
||||||
|
|
||||||
|
async def review_push(
|
||||||
|
self,
|
||||||
|
repo_name: str,
|
||||||
|
branch: str,
|
||||||
|
commit_summary: str,
|
||||||
|
files_summary: str,
|
||||||
|
) -> dict[str, Any] | None:
|
||||||
|
"""
|
||||||
|
審查 push event(非 PR),用 qwen2.5-coder:7b 快速掃描
|
||||||
|
2026-04-10 Claude Sonnet 4.6: Phase 32 ADR-067 — gitea_webhook_service 呼叫
|
||||||
|
"""
|
||||||
|
async with _SEMAPHORE:
|
||||||
|
prompt = (
|
||||||
|
f"你是資深程式審查員,請用繁體中文快速審查以下 Git Push。\n"
|
||||||
|
f"Repository: {repo_name} Branch: {branch}\n\n"
|
||||||
|
f"=== Commits ===\n{commit_summary}\n\n"
|
||||||
|
f"=== Changed Files ===\n{files_summary}\n\n"
|
||||||
|
"請簡要說明:1) 有無明顯安全風險 2) 有無破壞性變更 3) 整體品質評估\n"
|
||||||
|
"格式:每個問題以「⚠️」開頭,如無問題說「✅ Push 品質正常」\n"
|
||||||
|
"5 行以內,繁體中文。"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
http = await self._get_http()
|
||||||
|
resp = await http.post(
|
||||||
|
f"{settings.OLLAMA_URL}/api/generate",
|
||||||
|
json={
|
||||||
|
"model": _MODEL_OLLAMA,
|
||||||
|
"prompt": prompt,
|
||||||
|
"stream": False,
|
||||||
|
"options": {"num_predict": 512, "temperature": 0.1},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if resp.status_code == 200:
|
||||||
|
text = resp.json().get("response", "").strip()
|
||||||
|
issues = text.count("⚠️")
|
||||||
|
logger.info("push_review_ollama_done", repo=repo_name, branch=branch, issues=issues)
|
||||||
|
return {"review_text": text, "issues_count": issues, "model": _MODEL_OLLAMA, "provider": "ollama"}
|
||||||
|
except httpx.TimeoutException:
|
||||||
|
logger.warning("push_review_ollama_timeout", repo=repo_name)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("push_review_ollama_failed", repo=repo_name, error=str(e))
|
||||||
|
return None
|
||||||
|
|
||||||
async def close(self) -> None:
|
async def close(self) -> None:
|
||||||
if self._http and not self._http.is_closed:
|
if self._http and not self._http.is_closed:
|
||||||
await self._http.aclose()
|
await self._http.aclose()
|
||||||
|
|||||||
Reference in New Issue
Block a user