Skip to content

ref(webhooks): Add legacy_webhook to the Plugin ActionType#116454

Merged
Christinarlong merged 3 commits into
masterfrom
christinarlong/legacy-webhook-plugin-shim
May 29, 2026
Merged

ref(webhooks): Add legacy_webhook to the Plugin ActionType#116454
Christinarlong merged 3 commits into
masterfrom
christinarlong/legacy-webhook-plugin-shim

Conversation

@Christinarlong
Copy link
Copy Markdown
Contributor

@Christinarlong Christinarlong commented May 28, 2026

Turns out webhooks can also be sent from the PLUGIN ActionType via "Notify all legacy integrations" action option. So add calling into the legacy_webhook service from here since we don't care about notifying the other plugins

Mirror the WebhookActionHandler dual-path pattern so PLUGIN actions
also route through the new task-based legacy webhook service when the
existing legacy-webhook feature flags are enabled. Without flags, behavior
is unchanged (old synchronous path only).

This ensures projects using the PLUGIN action type (from dual-written
'notify all legacy integrations' rules) benefit from the new service's
retry logic, metrics, and feature-flagged control.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label May 28, 2026
@Christinarlong Christinarlong changed the title ref(webhooks): Add feature-flagged dual-path shim to PluginActionHandler ref(webhooks): Add legacy_webhook to the Plugin ActionType May 28, 2026
@Christinarlong Christinarlong marked this pull request as ready for review May 29, 2026 00:59
@Christinarlong Christinarlong requested a review from a team as a code owner May 29, 2026 00:59
@Christinarlong Christinarlong requested a review from a team May 29, 2026 01:27
The old path (execute_via_group_type_registry) notifies all legacy
NotificationPlugins, not just webhooks. Disabling it entirely would
break Slack, PagerDuty, OpsGenie, and other plugins still in use.

Instead, always run the old path but skip the webhooks plugin in
NotifyEventAction.get_plugins() when the disable-old-path flag is on.
The new task-based service handles webhook delivery exclusively.

Co-Authored-By: Claude <noreply@anthropic.com>
@Christinarlong Christinarlong requested a review from a team as a code owner May 29, 2026 02:26
Comment on lines +31 to +32
if skip_webhooks and plugin.slug == "webhooks":
continue
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can't cut off at the action layer as we still need to alert for the following notificationplugins (that aren't slack, pagerduty, webhooks, and opsgenie)

Image

Copy link
Copy Markdown
Member

@leeandher leeandher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! I did notice that we're using two flags, one to shut off the old path, one to enable the new path -- It just makes a lot more possibilities to consider to avoid putting the user in a bad state but I suspect it's done for a reason, just mentioning it in case theres a way around it

Comment on lines +56 to +57
if new_path and isinstance(invocation.event_data.event, GroupEvent):
send_legacy_webhooks_for_invocation(invocation)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the old path even permit Activity? It may be worth adding this GroupEvent gate right at the top and having the only condition to check here by the feature flag.

except Exception:
logger.exception(
"plugin_action_handler.old_path_error",
extra={"invocation": invocation},
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I'd add the same error handling for your new path if you want to compare logging, but if you don't expect errors it might be fine

Move the GroupEvent isinstance check to the top of execute() as an
early return since both paths require it. Add try/except error
handling around the new path for logging parity with the old path.

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b841095. Configure here.

def execute(invocation: ActionInvocation) -> None:
execute_via_group_type_registry(invocation)
if not isinstance(invocation.event_data.event, GroupEvent):
return
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GroupEvent gate blocks Activity events from old path

High Severity

The early return for non-GroupEvent events prevents Activity events from reaching execute_via_group_type_registry, which explicitly handles Activity events (e.g., calling send_notification() for resolution notifications). Before this change, the old path ran unconditionally. The analogous WebhookActionHandler.execute() correctly places the GroupEvent check only on the new path, not the old one. This silently drops plugin notifications for Activity-based events like issue resolutions.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b841095. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plugins don't support activity alerts since there's no metric handler

@Christinarlong Christinarlong merged commit 196b72d into master May 29, 2026
63 checks passed
@Christinarlong Christinarlong deleted the christinarlong/legacy-webhook-plugin-shim branch May 29, 2026 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants