From 49c5307c231df385759a4347f07d2a803144672e Mon Sep 17 00:00:00 2001 From: "Terry.Mao" Date: Thu, 5 Nov 2026 11:51:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(triage):=20=E9=98=B2=E6=AD=A2=E8=AF=AF?= =?UTF-8?q?=E6=94=B9=E5=90=AB=20marker=20=E7=9A=84=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=AF=84=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #344 --- .../test_apply_issue_triage_result.py | 23 +++++++++++++++++++ .../test_nightly_existing_code_review.py | 9 +++++++- .github/scripts/apply_issue_triage_result.py | 9 +++++++- .github/scripts/publish_nightly_findings.py | 4 ++-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/.github/aicodingflow-tests/test_apply_issue_triage_result.py b/.github/aicodingflow-tests/test_apply_issue_triage_result.py index a83a355..37db8a7 100644 --- a/.github/aicodingflow-tests/test_apply_issue_triage_result.py +++ b/.github/aicodingflow-tests/test_apply_issue_triage_result.py @@ -102,6 +102,29 @@ def test_upsert_triage_comment_patches_existing_marker_comment(self) -> None: check=True, ) + def test_find_triage_comment_skips_unowned_and_quoted_markers(self) -> None: + marker = apply_triage.MARKER + comments = [ + {"id": 1, "user": {"login": "reporter"}, "body": f"{marker}\nCopied triage"}, + {"id": 2, "user": {"login": "other[bot]"}, "body": f"{marker}\nOther bot"}, + {"id": 3, "user": {"login": "github-actions[bot]"}, "body": f"Quote: {marker}"}, + {"id": 4, "user": {"login": "github-actions[bot]"}, "body": f"{marker}\nActual triage"}, + ] + with mock.patch.object(apply_triage, "run_gh_json", return_value=[comments]): + self.assertEqual(apply_triage.find_triage_comment("owner/repo", 19), comments[3]) + + def test_upsert_triage_comment_creates_when_only_user_comment_has_marker(self) -> None: + comment = {"id": 123, "user": {"login": "reporter"}, "body": apply_triage.MARKER} + with ( + mock.patch.object(apply_triage, "run_gh_json", return_value=[[comment]]), + mock.patch.object(apply_triage.subprocess, "run") as run, + ): + apply_triage.upsert_triage_comment("owner/repo", 19, "body") + + run.assert_called_once_with( + ["gh", "api", "repos/owner/repo/issues/19/comments", "-f", "body=body"], check=True, + ) + if __name__ == "__main__": unittest.main() diff --git a/.github/aicodingflow-tests/test_nightly_existing_code_review.py b/.github/aicodingflow-tests/test_nightly_existing_code_review.py index a8a6165..4e4bc30 100644 --- a/.github/aicodingflow-tests/test_nightly_existing_code_review.py +++ b/.github/aicodingflow-tests/test_nightly_existing_code_review.py @@ -258,9 +258,16 @@ def test_user_created_duplicate_never_triggers_nightly_triage_dispatch(self) -> dispatch.assert_not_called() def test_triage_comment_lookup_and_dispatch_command(self) -> None: - with mock.patch.object(publish, "run_gh_json", return_value=[[{"body": publish.TRIAGE_COMMENT_MARKER}]]) as fetch: + marker = "" + comments = [ + {"user": {"login": "reporter"}, "body": marker}, + {"user": {"login": "github-actions[bot]"}, "body": marker}, + ] + with mock.patch.object(publish, "run_gh_json", return_value=[comments]) as fetch: self.assertTrue(publish.has_triage_comment("owner/repo", 7)) fetch.assert_called_once() + with mock.patch.object(publish, "run_gh_json", return_value=[comments[:1]]): + self.assertFalse(publish.has_triage_comment("owner/repo", 7)) with mock.patch.object(publish.subprocess, "run") as run: publish.dispatch_triage("owner/repo", "main", 7) run.assert_called_once_with([ diff --git a/.github/scripts/apply_issue_triage_result.py b/.github/scripts/apply_issue_triage_result.py index 35d5369..1aff4b7 100644 --- a/.github/scripts/apply_issue_triage_result.py +++ b/.github/scripts/apply_issue_triage_result.py @@ -14,6 +14,7 @@ MARKER = "" +TRIAGE_COMMENT_AUTHOR = "github-actions[bot]" PROTECTED_LABELS = {"plan-approved", "ready-to-implement", "ready-to-spec"} @@ -55,6 +56,12 @@ def sync_labels( ) +def is_triage_comment(comment: dict[str, Any]) -> bool: + user = comment.get("user") or {} + body = comment.get("body") or "" + return user.get("login") == TRIAGE_COMMENT_AUTHOR and isinstance(body, str) and body.startswith(MARKER) + + def find_triage_comment(repo: str, issue_number: int) -> dict[str, Any] | None: pages = run_gh_json( [ @@ -65,7 +72,7 @@ def find_triage_comment(repo: str, issue_number: int) -> dict[str, Any] | None: ] ) for comment in flatten_pages(pages): - if MARKER in (comment.get("body") or ""): + if is_triage_comment(comment): return comment return None diff --git a/.github/scripts/publish_nightly_findings.py b/.github/scripts/publish_nightly_findings.py index ed22046..3192bec 100644 --- a/.github/scripts/publish_nightly_findings.py +++ b/.github/scripts/publish_nightly_findings.py @@ -13,7 +13,7 @@ from pathlib import Path from typing import Any -from apply_issue_triage_result import MARKER as TRIAGE_COMMENT_MARKER +from apply_issue_triage_result import is_triage_comment from github_api import flatten_gh_pages, run_gh_json from prepare_nightly_review import focus_files, issue_snapshot, parse_cycle_days @@ -181,7 +181,7 @@ def has_triage_comment(repo: str, issue_number: int) -> bool: "api", f"repos/{repo}/issues/{issue_number}/comments?per_page=100", "--paginate", "--slurp", ]) - return any(TRIAGE_COMMENT_MARKER in str(item.get("body") or "") for item in flatten_gh_pages(pages)) + return any(is_triage_comment(item) for item in flatten_gh_pages(pages)) def dispatch_triage(repo: str, default_branch: str, issue_number: int) -> None: