Skip to content

ref(workflow_engine): Dual-write NotifyEventAction to be handled by webhook handler#119121

Merged
Christinarlong merged 4 commits into
masterfrom
christinarlong/pr1-repoint-notifyevent-webhook
Jul 7, 2026
Merged

ref(workflow_engine): Dual-write NotifyEventAction to be handled by webhook handler#119121
Christinarlong merged 4 commits into
masterfrom
christinarlong/pr1-repoint-notifyevent-webhook

Conversation

@Christinarlong

@Christinarlong Christinarlong commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR mainly changes the dual write flow such that when we see a write operation to the NotifyEventAction (ActionType.PLUGIN) we instead create a webhook action. Otherwise the write operation still saves the Rule but no workflow Action is saved.

We added a new translator for NotifyEventAction -> webhooks action. AND we're passing through the project through the dual write layers so we can check if an enabled ProjectOption exists (i.e they have the legacy Webhooks enabled) then make a webhook action. This checking is a little jank because we need to pass the project down a bunch of layers (but otherwise idk how we can get project). But it's temporary for this migration, because for the migration script I want to delete all actions that are plugins and don't have an enabled webhooks config for a clean state.

PR 1 of the effort to remove Action.Type.PLUGIN from the workflow engine

The legacy NotifyEventAction issue-alert action currently dual-writes a
workflow-engine PLUGIN action, whose sole live delivery path fires legacy
project webhooks via send_legacy_webhooks_for_invocation. The identical
delivery already happens through the WEBHOOK action handler when
target_identifier == "webhooks" (dual-written from NotifyEventServiceAction),
so PLUGIN is a duplicate tied to the now-no-op NotifyEventAction.

Repoint the NotifyEventAction translator to emit a WEBHOOK action targeting
the legacy webhooks service instead of PLUGIN. NotifyEventActionTranslator now
subclasses WebhookActionTranslator, dropping the service required-field and
returning the literal "webhooks" target_identifier so delivery routes through
WebhookActionHandler._handle_legacy_webhooks. Runtime delivery stays gated by
send_legacy_webhooks_for_invocation (webhooks:enabled/urls), unchanged from the
PLUGIN path. No new type='plugin' rows are created via the dual-write.

The PLUGIN enum and handlers are intentionally kept; they are removed in a
later PR after the existing rows are migrated.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Jul 7, 2026
@Christinarlong Christinarlong changed the title ref(workflow_engine): Dual-write NotifyEventAction to WEBHOOK not PLUGIN ref(workflow_engine): Dual-write NotifyEventAction to be handled by webhook handler Jul 7, 2026
Christinarlong and others added 2 commits July 7, 2026 11:14
…bhook config

Only dual-write the repointed WEBHOOK("webhooks") action for a NotifyEventAction rule
when the project has the legacy webhook enabled. On projects without it enabled, the
action delivers nothing, so skip it rather than persist a dead webhook action -- the
workflow is left as a valid "No actions" automation.

Threads the rule's project through the dual-write path
(translate_rule_data_actions_to_notification_actions /
build_notification_actions_from_rule_data_actions / create_workflow_actions and the four
call sites) and adds is_legacy_webhook_enabled(project), gating on webhooks:enabled.

Also fixes the dual-read serializer parity checks: NotifyEventAction now reverse-serializes
to the equivalent NotifyEventServiceAction(service="webhooks"), which is an intentional
divergence, and repoints the test-fire mock to the webhook handler.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Comment thread src/sentry/workflow_engine/migration_helpers/rule_action.py
The test-notification endpoint translates each action blob individually and then does
actions[0]. Now that NotifyEventAction is gated on the project's legacy webhook config,
translating it on a webhooks-disabled project returns an empty list, so actions[0] raised
IndexError -- surfaced to the caller as a 400 'An unexpected error occurred'.

Skip the blob when it translates to nothing, restoring the prior clean result (nothing to
deliver, no error).

Co-Authored-By: Claude <noreply@anthropic.com>
Comment on lines +41 to +43
# TODO: After the script migrates/removes all plugin actions, delete this helper and the
# `project` threading through the dual-write path.
return bool(ProjectOption.objects.get_value(project, "webhooks:enabled", default=False))

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.

This is the helper/crux for passing down the project throughout all the dual write layers, since we only want to write a webhook action if we know it'll work/the person has legacy webhooks enabled. Otherwise the state makes no sense. Once the migration is done (i.e the plugin action rows are either deleted or migrated to webhook ones) we can delete this helper and the project passing

@Christinarlong Christinarlong marked this pull request as ready for review July 7, 2026 19:11
@Christinarlong Christinarlong requested review from a team as code owners July 7, 2026 19:11

@saponifi3d saponifi3d left a comment

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.

lgtm - thanks for chatting a bit in slack about how this is covering the legacy API use cases.

@Christinarlong Christinarlong merged commit 72cc027 into master Jul 7, 2026
76 checks passed
@Christinarlong Christinarlong deleted the christinarlong/pr1-repoint-notifyevent-webhook branch July 7, 2026 20:49
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.

3 participants