fix(lint): 修复 PR #14 引入的 lint 回退 (119→0)
PR #14 从旧分支复制文件导致回退了 PR #10 的 lint 修复。 修复内容: - autoflake 移除未使用导入/变量 - autopep8 修复缩进/空格 - 手动修复 F821(pathlib→Path), F541(f-string), F841(未使用变量) - 所有修复均通过 flake8 --max-line-length=120 --extend-ignore=E501 检查 (0 errors)
This commit is contained in:
+49
-16
@@ -46,7 +46,8 @@ _TTL_SECONDS = 7 * 24 * 3600
|
||||
_idempotency_lock = asyncio.Lock()
|
||||
|
||||
|
||||
def _is_duplicate(event: str, delivery: str, payload: Optional[Dict[str, Any]] = None) -> bool:
|
||||
def _is_duplicate(event: str, delivery: str,
|
||||
payload: Optional[Dict[str, Any]] = None) -> bool:
|
||||
"""检查 Webhook 是否重复投递,自动清理过期条目。
|
||||
|
||||
双重去重策略:
|
||||
@@ -56,7 +57,8 @@ def _is_duplicate(event: str, delivery: str, payload: Optional[Dict[str, Any]] =
|
||||
"""
|
||||
now = time.time()
|
||||
# 清理过期条目
|
||||
while _delivery_timestamps and (now - _delivery_timestamps[0][0]) > _TTL_SECONDS:
|
||||
while _delivery_timestamps and (
|
||||
now - _delivery_timestamps[0][0]) > _TTL_SECONDS:
|
||||
_, key = _delivery_timestamps.pop(0)
|
||||
_delivery_cache.discard(key)
|
||||
|
||||
@@ -77,7 +79,11 @@ def _is_duplicate(event: str, delivery: str, payload: Optional[Dict[str, Any]] =
|
||||
content_hash = hashlib.sha256(content.encode()).hexdigest()[:16]
|
||||
content_key = f"content:{event}:{pr_num}:{sender}:{content_hash}"
|
||||
if content_key in _delivery_cache:
|
||||
logger.info("Content-based duplicate detected: %s PR#%s by %s", event, pr_num, sender)
|
||||
logger.info(
|
||||
"Content-based duplicate detected: %s PR#%s by %s",
|
||||
event,
|
||||
pr_num,
|
||||
sender)
|
||||
return True
|
||||
_delivery_cache.add(content_key)
|
||||
_delivery_timestamps.append((now, content_key))
|
||||
@@ -137,8 +143,16 @@ async def _fetch_pr_files(repo: str, pr_number: int) -> Tuple[List[str], str]:
|
||||
last_error = str(e)
|
||||
if attempt < 2:
|
||||
await asyncio.sleep(0.5 * (attempt + 1))
|
||||
logger.warning("Retry %d/3 fetching PR files: %s/pulls/%d", attempt + 1, repo, pr_number)
|
||||
logger.warning("Failed to fetch PR files after 3 retries: %s/pulls/%d - %s", repo, pr_number, last_error)
|
||||
logger.warning(
|
||||
"Retry %d/3 fetching PR files: %s/pulls/%d",
|
||||
attempt + 1,
|
||||
repo,
|
||||
pr_number)
|
||||
logger.warning(
|
||||
"Failed to fetch PR files after 3 retries: %s/pulls/%d - %s",
|
||||
repo,
|
||||
pr_number,
|
||||
last_error)
|
||||
return [], f"获取文件列表失败(重试3次): {last_error}"
|
||||
|
||||
|
||||
@@ -166,7 +180,6 @@ def _calc_risk_level(changed_files: List[str]) -> str:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
MAIL_PROJECT_ID = "_mail"
|
||||
|
||||
|
||||
@@ -252,7 +265,8 @@ async def _handle_pull_request(payload: Dict[str, Any]) -> None:
|
||||
|
||||
pr = payload.get("pull_request")
|
||||
if not pr or not isinstance(pr, dict):
|
||||
logger.warning("pull_request event missing pull_request field, skipping")
|
||||
logger.warning(
|
||||
"pull_request event missing pull_request field, skipping")
|
||||
return
|
||||
repo = _repo_fullname(payload)
|
||||
pr_number = pr.get("number", 0)
|
||||
@@ -266,7 +280,8 @@ async def _handle_pull_request(payload: Dict[str, Any]) -> None:
|
||||
if fetch_error:
|
||||
file_list = f"⚠️ {fetch_error}"
|
||||
else:
|
||||
file_list = "\n".join(f"- {f}" for f in changed_files) if changed_files else "(无文件变更)"
|
||||
file_list = "\n".join(
|
||||
f"- {f}" for f in changed_files) if changed_files else "(无文件变更)"
|
||||
|
||||
text = render_template("review_request", {
|
||||
"repo": repo,
|
||||
@@ -291,11 +306,13 @@ async def _handle_pull_request_review(payload: Dict[str, Any]) -> None:
|
||||
"""
|
||||
review = payload.get("review")
|
||||
if not review or not isinstance(review, dict):
|
||||
logger.warning("pull_request_review event missing review field, skipping")
|
||||
logger.warning(
|
||||
"pull_request_review event missing review field, skipping")
|
||||
return
|
||||
pr = payload.get("pull_request")
|
||||
if not pr or not isinstance(pr, dict):
|
||||
logger.warning("pull_request_review event missing pull_request field, skipping")
|
||||
logger.warning(
|
||||
"pull_request_review event missing pull_request field, skipping")
|
||||
return
|
||||
|
||||
# 兼容两种 payload 格式提取 state
|
||||
@@ -319,7 +336,15 @@ async def _handle_pull_request_review(payload: Dict[str, Any]) -> None:
|
||||
pr_title = pr.get("title", "")
|
||||
pr_author = pr.get("user", {}).get("login", "unknown")
|
||||
# 兼容:org webhook 的 review 没有 user,从 sender 取
|
||||
reviewer = review.get("user", {}).get("login", "") or payload.get("sender", {}).get("login", "unknown")
|
||||
reviewer = review.get(
|
||||
"user",
|
||||
{}).get(
|
||||
"login",
|
||||
"") or payload.get(
|
||||
"sender",
|
||||
{}).get(
|
||||
"login",
|
||||
"unknown")
|
||||
review_body = review.get("body", "") or review.get("content", "(无评论)")
|
||||
|
||||
result_map = {"APPROVED": "通过 ✓", "REQUEST_CHANGES": "驳回 ✗"}
|
||||
@@ -366,7 +391,8 @@ async def _handle_issues(payload: Dict[str, Any]) -> None:
|
||||
logger.debug("Issue assigned but no assignee found, skipping")
|
||||
return
|
||||
|
||||
labels_list = [lbl.get("name", "") for lbl in (issue.get("labels") or [])]
|
||||
labels_list = [lbl.get("name", "")
|
||||
for lbl in (issue.get("labels") or [])]
|
||||
labels = ", ".join(labels_list) if labels_list else "(无标签)"
|
||||
issue_body = issue.get("body", "(无描述)")
|
||||
brief = issue_title[:20].replace(" ", "-").lower()
|
||||
@@ -417,7 +443,9 @@ async def _handle_issue_comment(payload: Dict[str, Any]) -> None:
|
||||
|
||||
# 已关闭的 Issue/PR 不再发送 CI 失败通知
|
||||
if issue.get("state") == "closed":
|
||||
logger.debug("Skipping CI failure notification for closed issue #%s", issue.get("number"))
|
||||
logger.debug(
|
||||
"Skipping CI failure notification for closed issue #%s",
|
||||
issue.get("number"))
|
||||
return
|
||||
|
||||
repo = _repo_fullname(payload)
|
||||
@@ -485,7 +513,8 @@ async def gitea_webhook(
|
||||
# 1. 签名验证
|
||||
if not _verify_signature(body, x_gitea_signature):
|
||||
logger.warning("Webhook signature verification failed")
|
||||
return Response(status_code=403, content="signature verification failed")
|
||||
return Response(status_code=403,
|
||||
content="signature verification failed")
|
||||
|
||||
# 3. 解析 payload(提前解析,用于幂等检查)
|
||||
try:
|
||||
@@ -498,14 +527,18 @@ async def gitea_webhook(
|
||||
if x_gitea_event and x_gitea_delivery:
|
||||
async with _idempotency_lock:
|
||||
if _is_duplicate(x_gitea_event, x_gitea_delivery, payload):
|
||||
logger.debug("Duplicate webhook: %s/%s", x_gitea_event, x_gitea_delivery)
|
||||
logger.debug(
|
||||
"Duplicate webhook: %s/%s",
|
||||
x_gitea_event,
|
||||
x_gitea_delivery)
|
||||
return Response(status_code=200, content="duplicate")
|
||||
|
||||
# 4. 查找 handler
|
||||
handler = _EVENT_HANDLERS.get(x_gitea_event or "")
|
||||
if not handler:
|
||||
logger.debug("Unhandled event type: %s", x_gitea_event)
|
||||
return Response(status_code=200, content=f"unhandled event: {x_gitea_event}")
|
||||
return Response(status_code=200,
|
||||
content=f"unhandled event: {x_gitea_event}")
|
||||
|
||||
# 5. 执行 handler
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user