feat(repair-agent): scan all bug sources and improve CI/CD triage
All checks were successful
Build and Deploy Log Center / build-and-deploy (push) Successful in 2m56s
All checks were successful
Build and Deploy Log Center / build-and-deploy (push) Successful in 2m56s
- task_manager: scan runtime + cicd + deployment sources (not just runtime) - claude_service: add CI/CD-specific triage rules for build/deploy failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
aa3a5b8c5d
commit
75fe8dfc0c
@ -197,6 +197,8 @@ class ClaudeService:
|
||||
|
||||
## 判断规则
|
||||
|
||||
### 运行时错误(runtime)
|
||||
|
||||
属于 **无法复现 / 不需要修复** 的情况(CANNOT_REPRODUCE):
|
||||
1. JWT Token 过期、认证失败 — 正常认证流程,不是代码 Bug
|
||||
2. HTTP 405 Method Not Allowed — 客户端请求了错误的方法
|
||||
@ -210,6 +212,19 @@ class ClaudeService:
|
||||
2. 数据库约束错误(IntegrityError)由项目代码逻辑引起
|
||||
3. TypeError / AttributeError 出现在项目视图或模型中
|
||||
|
||||
### CI/CD 构建错误(CICDFailure)
|
||||
|
||||
属于 **需要修复** 的情况(FIX):
|
||||
1. Docker build 失败且日志中包含代码编译/语法错误(SyntaxError、ImportError、ModuleNotFoundError 等)
|
||||
2. npm/pip install 成功但 build 阶段因代码问题失败
|
||||
3. Dockerfile 中 RUN 命令因项目代码问题报错
|
||||
|
||||
属于 **无法复现 / 不需要修复** 的情况(CANNOT_REPRODUCE):
|
||||
1. Docker 镜像仓库认证失败、推送失败 — 基础设施问题
|
||||
2. kubectl 部署失败、K8s 资源不足 — 运维问题
|
||||
3. 网络超时、镜像拉取失败 — 瞬态错误
|
||||
4. 日志中没有具体代码错误,只有通用构建/部署失败信息
|
||||
|
||||
请先用 Grep/Read 查看相关源文件确认当前代码状态,然后给出判断。
|
||||
|
||||
**最后一行必须输出以下格式之一(只输出一个):**
|
||||
|
||||
@ -28,9 +28,60 @@ class TaskManager:
|
||||
"""
|
||||
all_bugs: dict[int, Bug] = {}
|
||||
|
||||
for status in ("NEW", "PENDING_FIX"):
|
||||
for source in ("runtime", "cicd", "deployment"):
|
||||
for status in ("NEW", "PENDING_FIX"):
|
||||
try:
|
||||
params: dict[str, str] = {"status": status, "source": source}
|
||||
if project_id:
|
||||
params["project_id"] = project_id
|
||||
|
||||
response = self.client.get(
|
||||
f"{self.base_url}/api/v1/bugs",
|
||||
params=params,
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
for item in data.get("items", []):
|
||||
bug_id = item["id"]
|
||||
if bug_id in all_bugs:
|
||||
continue
|
||||
|
||||
stack_trace = item.get("stack_trace")
|
||||
if isinstance(stack_trace, str):
|
||||
stack_trace = stack_trace.split("\n")
|
||||
|
||||
all_bugs[bug_id] = Bug(
|
||||
id=bug_id,
|
||||
project_id=item["project_id"],
|
||||
environment=item.get("environment", "production"),
|
||||
level=item.get("level", "ERROR"),
|
||||
error={
|
||||
"type": item.get("error_type", "Unknown"),
|
||||
"message": item.get("error_message", ""),
|
||||
"file_path": item.get("file_path"),
|
||||
"line_number": item.get("line_number"),
|
||||
"stack_trace": stack_trace,
|
||||
},
|
||||
context=item.get("context"),
|
||||
status=BugStatus(item.get("status", "NEW")),
|
||||
retry_count=item.get("retry_count", 0),
|
||||
)
|
||||
except httpx.HTTPError as e:
|
||||
logger.error(f"获取 {source}/{status} 状态 Bug 列表失败: {e}")
|
||||
|
||||
bugs = list(all_bugs.values())
|
||||
logger.info(f"获取到 {len(bugs)} 个待修复 Bug(runtime + cicd + deployment)")
|
||||
return bugs
|
||||
|
||||
def fetch_failed_bugs(self, project_id: Optional[str] = None) -> list[Bug]:
|
||||
"""
|
||||
获取修复失败的 Bug 列表(FIX_FAILED 状态,所有来源)
|
||||
"""
|
||||
all_bugs: dict[int, Bug] = {}
|
||||
for source in ("runtime", "cicd", "deployment"):
|
||||
try:
|
||||
params: dict[str, str] = {"status": status, "source": "runtime"}
|
||||
params: dict[str, str] = {"status": "FIX_FAILED", "source": source}
|
||||
if project_id:
|
||||
params["project_id"] = project_id
|
||||
|
||||
@ -51,7 +102,7 @@ class TaskManager:
|
||||
stack_trace = stack_trace.split("\n")
|
||||
|
||||
all_bugs[bug_id] = Bug(
|
||||
id=bug_id,
|
||||
id=item["id"],
|
||||
project_id=item["project_id"],
|
||||
environment=item.get("environment", "production"),
|
||||
level=item.get("level", "ERROR"),
|
||||
@ -63,57 +114,13 @@ class TaskManager:
|
||||
"stack_trace": stack_trace,
|
||||
},
|
||||
context=item.get("context"),
|
||||
status=BugStatus(item.get("status", "NEW")),
|
||||
status=BugStatus.FIX_FAILED,
|
||||
retry_count=item.get("retry_count", 0),
|
||||
)
|
||||
except httpx.HTTPError as e:
|
||||
logger.error(f"获取 {status} 状态 Bug 列表失败: {e}")
|
||||
logger.error(f"获取 {source}/FIX_FAILED Bug 列表失败: {e}")
|
||||
|
||||
bugs = list(all_bugs.values())
|
||||
logger.info(f"获取到 {len(bugs)} 个待修复 Bug(NEW + PENDING_FIX)")
|
||||
return bugs
|
||||
|
||||
def fetch_failed_bugs(self, project_id: Optional[str] = None) -> list[Bug]:
|
||||
"""
|
||||
获取修复失败的 Bug 列表(FIX_FAILED 状态)
|
||||
"""
|
||||
bugs: list[Bug] = []
|
||||
try:
|
||||
params: dict[str, str] = {"status": "FIX_FAILED", "source": "runtime"}
|
||||
if project_id:
|
||||
params["project_id"] = project_id
|
||||
|
||||
response = self.client.get(
|
||||
f"{self.base_url}/api/v1/bugs",
|
||||
params=params,
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
for item in data.get("items", []):
|
||||
stack_trace = item.get("stack_trace")
|
||||
if isinstance(stack_trace, str):
|
||||
stack_trace = stack_trace.split("\n")
|
||||
|
||||
bugs.append(Bug(
|
||||
id=item["id"],
|
||||
project_id=item["project_id"],
|
||||
environment=item.get("environment", "production"),
|
||||
level=item.get("level", "ERROR"),
|
||||
error={
|
||||
"type": item.get("error_type", "Unknown"),
|
||||
"message": item.get("error_message", ""),
|
||||
"file_path": item.get("file_path"),
|
||||
"line_number": item.get("line_number"),
|
||||
"stack_trace": stack_trace,
|
||||
},
|
||||
context=item.get("context"),
|
||||
status=BugStatus.FIX_FAILED,
|
||||
retry_count=item.get("retry_count", 0),
|
||||
))
|
||||
except httpx.HTTPError as e:
|
||||
logger.error(f"获取 FIX_FAILED Bug 列表失败: {e}")
|
||||
|
||||
logger.info(f"获取到 {len(bugs)} 个 FIX_FAILED Bug")
|
||||
return bugs
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user