fix bug
All checks were successful
Build and Deploy Log Center / build-and-deploy (push) Successful in 1m39s
All checks were successful
Build and Deploy Log Center / build-and-deploy (push) Successful in 1m39s
This commit is contained in:
parent
708021c443
commit
25c9b2d18e
@ -1,9 +1,10 @@
|
||||
"""
|
||||
Gitea API 客户端
|
||||
"""
|
||||
import re
|
||||
import httpx
|
||||
import os
|
||||
from typing import Tuple
|
||||
from typing import Tuple, Optional
|
||||
|
||||
|
||||
class GiteaClient:
|
||||
@ -12,7 +13,7 @@ class GiteaClient:
|
||||
def __init__(self, gitea_url: str = None, token: str = None):
|
||||
self.gitea_url = (gitea_url or os.getenv("GITEA_URL", "")).rstrip("/")
|
||||
self.token = token or os.getenv("GITEA_TOKEN", "")
|
||||
self.base_api_url = f"{self.gitea_url}/api/v1"
|
||||
self.base_api_url = f"{self.gitea_url}/api/v1" if self.gitea_url else ""
|
||||
self.client = httpx.Client(timeout=30)
|
||||
|
||||
def _headers(self) -> dict:
|
||||
@ -22,21 +23,31 @@ class GiteaClient:
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
def _extract_owner_repo_from_pr_url(self, pr_url: str) -> Tuple[str, str, int]:
|
||||
def _parse_pr_url(self, pr_url: str) -> Tuple[str, str, str, int]:
|
||||
"""
|
||||
从 PR URL 提取 owner, repo, pr_number
|
||||
从 PR URL 提取 base_url, owner, repo, pr_number
|
||||
例如: https://gitea.airlabs.art/owner/repo/pulls/45
|
||||
返回: ("https://gitea.airlabs.art", "owner", "repo", 45)
|
||||
"""
|
||||
import re
|
||||
match = re.search(r'([^/]+)/([^/]+)/pulls/(\d+)', pr_url)
|
||||
match = re.search(r'(https?://[^/]+)/([^/]+)/([^/]+)/pulls/(\d+)', pr_url)
|
||||
if not match:
|
||||
raise ValueError(f"无法解析 PR URL: {pr_url}")
|
||||
|
||||
owner, repo, pr_number = match.groups()
|
||||
return owner, repo, int(pr_number)
|
||||
base_url, owner, repo, pr_number = match.groups()
|
||||
return base_url, owner, repo, int(pr_number)
|
||||
|
||||
def _get_api_url(self, pr_url: Optional[str] = None) -> str:
|
||||
"""获取 API base URL,优先从 pr_url 解析,否则用 self.base_api_url"""
|
||||
if pr_url:
|
||||
match = re.search(r'(https?://[^/]+)/', pr_url)
|
||||
if match:
|
||||
return f"{match.group(1)}/api/v1"
|
||||
if self.base_api_url:
|
||||
return self.base_api_url
|
||||
raise ValueError("无法确定 Gitea API 地址:未配置 GITEA_URL 且 PR URL 中无法提取")
|
||||
|
||||
def merge_pr(
|
||||
self, owner: str, repo: str, pr_number: int
|
||||
self, owner: str, repo: str, pr_number: int, api_base_url: str = None
|
||||
) -> Tuple[bool, str]:
|
||||
"""
|
||||
合并 PR
|
||||
@ -45,11 +56,13 @@ class GiteaClient:
|
||||
owner: 仓库所有者
|
||||
repo: 仓库名称
|
||||
pr_number: PR 编号
|
||||
api_base_url: 可选,API base URL(从 pr_url 解析得到)
|
||||
|
||||
Returns:
|
||||
(是否成功, 消息)
|
||||
"""
|
||||
url = f"{self.base_api_url}/repos/{owner}/{repo}/pulls/{pr_number}/merge"
|
||||
base = api_base_url or self.base_api_url
|
||||
url = f"{base}/repos/{owner}/{repo}/pulls/{pr_number}/merge"
|
||||
payload = {
|
||||
"Do": "merge", # merge / squash / rebase
|
||||
"MergeMessageField": f"Merge PR #{pr_number} (approved via Log Center)",
|
||||
@ -75,7 +88,7 @@ class GiteaClient:
|
||||
return False, str(e)
|
||||
|
||||
def close_pr(
|
||||
self, owner: str, repo: str, pr_number: int, reason: str = ""
|
||||
self, owner: str, repo: str, pr_number: int, reason: str = "", api_base_url: str = None
|
||||
) -> Tuple[bool, str]:
|
||||
"""
|
||||
关闭 PR(可选添加评论说明原因)
|
||||
@ -85,20 +98,24 @@ class GiteaClient:
|
||||
repo: 仓库名称
|
||||
pr_number: PR 编号
|
||||
reason: 关闭原因(将作为评论添加)
|
||||
api_base_url: 可选,API base URL(从 pr_url 解析得到)
|
||||
|
||||
Returns:
|
||||
(是否成功, 消息)
|
||||
"""
|
||||
base = api_base_url or self.base_api_url
|
||||
|
||||
# Step 1: 如果提供了原因,先添加评论
|
||||
if reason:
|
||||
comment_success, comment_msg = self.add_pr_comment(
|
||||
owner, repo, pr_number, f"## ❌ 修复被拒绝\n\n**原因:**\n{reason}"
|
||||
owner, repo, pr_number, f"## ❌ 修复被拒绝\n\n**原因:**\n{reason}",
|
||||
api_base_url=base,
|
||||
)
|
||||
if not comment_success:
|
||||
return False, f"添加评论失败: {comment_msg}"
|
||||
|
||||
# Step 2: 关闭 PR
|
||||
url = f"{self.base_api_url}/repos/{owner}/{repo}/pulls/{pr_number}"
|
||||
url = f"{base}/repos/{owner}/{repo}/pulls/{pr_number}"
|
||||
payload = {"state": "closed"}
|
||||
|
||||
try:
|
||||
@ -111,7 +128,7 @@ class GiteaClient:
|
||||
return False, str(e)
|
||||
|
||||
def add_pr_comment(
|
||||
self, owner: str, repo: str, pr_number: int, comment: str
|
||||
self, owner: str, repo: str, pr_number: int, comment: str, api_base_url: str = None
|
||||
) -> Tuple[bool, str]:
|
||||
"""
|
||||
添加 PR 评论
|
||||
@ -121,12 +138,14 @@ class GiteaClient:
|
||||
repo: 仓库名称
|
||||
pr_number: PR 编号
|
||||
comment: 评论内容
|
||||
api_base_url: 可选,API base URL
|
||||
|
||||
Returns:
|
||||
(是否成功, 消息)
|
||||
"""
|
||||
base = api_base_url or self.base_api_url
|
||||
# 注意: Gitea 中 PR 和 Issue 共用评论 API
|
||||
url = f"{self.base_api_url}/repos/{owner}/{repo}/issues/{pr_number}/comments"
|
||||
url = f"{base}/repos/{owner}/{repo}/issues/{pr_number}/comments"
|
||||
payload = {"body": comment}
|
||||
|
||||
try:
|
||||
@ -137,17 +156,19 @@ class GiteaClient:
|
||||
return False, str(e)
|
||||
|
||||
def merge_pr_by_url(self, pr_url: str) -> Tuple[bool, str]:
|
||||
"""通过 PR URL 直接合并"""
|
||||
"""通过 PR URL 直接合并(从 URL 自动解析 Gitea 地址)"""
|
||||
try:
|
||||
owner, repo, pr_number = self._extract_owner_repo_from_pr_url(pr_url)
|
||||
return self.merge_pr(owner, repo, pr_number)
|
||||
base_url, owner, repo, pr_number = self._parse_pr_url(pr_url)
|
||||
api_base_url = f"{base_url}/api/v1"
|
||||
return self.merge_pr(owner, repo, pr_number, api_base_url=api_base_url)
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
|
||||
def close_pr_by_url(self, pr_url: str, reason: str = "") -> Tuple[bool, str]:
|
||||
"""通过 PR URL 直接关闭"""
|
||||
"""通过 PR URL 直接关闭(从 URL 自动解析 Gitea 地址)"""
|
||||
try:
|
||||
owner, repo, pr_number = self._extract_owner_repo_from_pr_url(pr_url)
|
||||
return self.close_pr(owner, repo, pr_number, reason)
|
||||
base_url, owner, repo, pr_number = self._parse_pr_url(pr_url)
|
||||
api_base_url = f"{base_url}/api/v1"
|
||||
return self.close_pr(owner, repo, pr_number, reason, api_base_url=api_base_url)
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
|
||||
@ -32,6 +32,9 @@ spec:
|
||||
value: "log_center"
|
||||
- name: DB_PASSWORD
|
||||
value: "JogNQdtrd3WY8CBCAiYfYEGx"
|
||||
# Gitea Token(URL 从 PR URL 自动解析)
|
||||
- name: GITEA_TOKEN
|
||||
value: "443f7f2f556b4832f90e46df9af3e21ccb06b8a3"
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
|
||||
@ -38,6 +38,7 @@ class ClaudeService:
|
||||
cmd = [
|
||||
self.cli_path,
|
||||
"-p", prompt,
|
||||
"--model", settings.claude_model,
|
||||
"--dangerously-skip-permissions",
|
||||
]
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ class Settings(BaseSettings):
|
||||
# Claude CLI
|
||||
claude_cli_path: str = Field(default="claude", description="Claude CLI 路径")
|
||||
claude_timeout: int = Field(default=1000, description="Claude CLI 超时时间(秒)")
|
||||
claude_model: str = Field(default="claude-opus-4-6", description="Claude 模型")
|
||||
|
||||
# Git
|
||||
git_user_name: str = Field(default="repair-agent", description="Git 用户名")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user