From eb1d7f419d9d8132bf301de7363c374409ffd552 Mon Sep 17 00:00:00 2001 From: Timothy Wayne Gregg Date: Thu, 9 Jul 2026 21:19:27 -0400 Subject: [PATCH] fix hosted issue trigger gating --- deploy/coven-github/coven_github_adapter.py | 14 ++-- .../coven-github/test_coven_github_adapter.py | 84 +++++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/deploy/coven-github/coven_github_adapter.py b/deploy/coven-github/coven_github_adapter.py index 884d2d2..a8af581 100644 --- a/deploy/coven-github/coven_github_adapter.py +++ b/deploy/coven-github/coven_github_adapter.py @@ -315,10 +315,12 @@ def build_task_from_event(event_name, delivery_id, payload, policy): if event_name == "issue_comment": issue = payload.get("issue") or {} comment = payload.get("comment") or {} + if payload.get("action") != "created": + return ignored(base, "unsupported_issue_comment_action") if not mentioned(comment.get("body"), policy): return ignored(base, "issue_comment_without_mention") - if not trigger_enabled(policy, "issue_mention"): - return ignored(base, "issue_mention_not_enabled") + if not trigger_enabled(policy, "issue_comment.created"): + return ignored(base, "issue_comment_not_enabled") if issue.get("pull_request"): base.update( { @@ -352,9 +354,11 @@ def build_task_from_event(event_name, delivery_id, payload, policy): if event_name == "pull_request_review_comment": comment = payload.get("comment") or {} pull_request = payload.get("pull_request") or {} + if payload.get("action") != "created": + return ignored(base, "unsupported_pr_review_comment_action") if not mentioned(comment.get("body"), policy): return ignored(base, "pr_review_comment_without_mention") - if not trigger_enabled(policy, "pr_review_comment"): + if not trigger_enabled(policy, "pull_request_review_comment.created"): return ignored(base, "pr_review_comment_not_enabled") base.update( { @@ -380,13 +384,13 @@ def build_task_from_event(event_name, delivery_id, payload, policy): action = payload.get("action") if action not in ("assigned", "labeled"): return ignored(base, "unsupported_issue_action") - if action == "assigned" and not trigger_enabled(policy, "issue_assigned"): + if action == "assigned" and not trigger_enabled(policy, "issues.assigned"): return ignored(base, "issue_assigned_not_enabled") if action == "assigned" and not issue_assigned_to_bot(issue, policy): return ignored(base, "issue_assigned_to_unmanaged_user") if action == "labeled" and not labels_include_trigger(issue.get("labels"), policy): return ignored(base, "issue_label_not_enabled") - if action == "labeled" and not trigger_enabled(policy, "issue_label"): + if action == "labeled" and not trigger_enabled(policy, "issues.labeled"): return ignored(base, "issue_label_not_enabled") base.update( { diff --git a/deploy/coven-github/test_coven_github_adapter.py b/deploy/coven-github/test_coven_github_adapter.py index aead618..c666139 100644 --- a/deploy/coven-github/test_coven_github_adapter.py +++ b/deploy/coven-github/test_coven_github_adapter.py @@ -41,6 +41,90 @@ def test_route_signed_delivery_reports_missing_secret(self): self.assertEqual(result["status"], 500) self.assertIn("GITHUB_WEBHOOK_SECRET", result["error"]) + def test_issue_opened_is_not_a_work_trigger(self): + adapter = load_adapter() + + task = adapter.build_task_from_event( + "issues", + "delivery-issue-opened", + { + "action": "opened", + "installation": {"id": 123456}, + "repository": { + "id": 987654321, + "full_name": "OpenCoven/example", + "clone_url": "https://github.com/OpenCoven/example.git", + "default_branch": "main", + }, + "issue": { + "number": 43, + "title": "Installer is slow", + "body": "A diagnostic issue, not a bot task.", + "labels": [], + "assignees": [], + }, + }, + { + "enabled_triggers": [ + "issues.labeled", + "issue_comment.created", + "pull_request_review_comment.created", + ], + "trigger_labels": ["coven:fix"], + "bot_usernames": ["coven-cody[bot]"], + "familiar": { + "id": "cody", + "display_name": "Cody", + "model": "openai/gpt-5.5", + "skills": [], + }, + "publication": {"mode": "record_only"}, + }, + ) + + self.assertEqual(task["state"], "ignored") + self.assertEqual(task["ignored_reason"], "unsupported_issue_action") + + def test_labeled_issue_uses_webhook_trigger_name_policy(self): + adapter = load_adapter() + + task = adapter.build_task_from_event( + "issues", + "delivery-issue-labeled", + { + "action": "labeled", + "installation": {"id": 123456}, + "repository": { + "id": 987654321, + "full_name": "OpenCoven/example", + "clone_url": "https://github.com/OpenCoven/example.git", + "default_branch": "main", + }, + "issue": { + "number": 44, + "title": "Fix it", + "body": "Please fix it.", + "labels": [{"name": "coven:fix"}], + }, + }, + { + "enabled_triggers": ["issues.labeled"], + "trigger_labels": ["coven:fix"], + "bot_usernames": ["coven-cody[bot]"], + "familiar": { + "id": "cody", + "display_name": "Cody", + "model": "openai/gpt-5.5", + "skills": [], + }, + "publication": {"mode": "record_only"}, + }, + ) + + self.assertEqual(task["state"], "queued") + self.assertEqual(task["trigger"], "issue_assigned") + self.assertEqual(task["task"]["kind"], "fix_issue") + def test_prepare_review_context_rejects_stale_pr_head_evidence(self): adapter = load_adapter()