Restore Missing Webhook Notifications for Issue Deletion
Issue deletion webhooks stopped firing, so integrations (Slack, Mattermost, etc.) never saw DELETE notifications even though CREATE/UPDATE kept working. See https://github.com/makeplane/plane/issues/8054. The regression comes from IssueDetailAPIEndpoint.delete() skipping model_activity.delay(); only the internal issue_activity.delay() ran.
Two commits fix this on fix/issue-deletion-webhook-events:
apps/api/plane/api/views/issue.py: invokemodel_activity.delay()with{"deleted": True}so deletion reaches the activity stream.apps/api/plane/bgtasks/webhook_task.py: whenrequested_data["deleted"] is True, enqueue a singleverb="deleted"webhook and short-circuit the normal update flow.
Results
- Broken build: DELETE webhooks never fired, confirmed by the receiver output and missing rows in
webhook_logs. - Fixed build: both
createdanddeletedevents are emitted end-to-end (receiver + DB), restoring the external integration contract. - No migrations or configuration changes required; scope is limited to webhook dispatch.
[!NOTE] Restores DELETE webhooks for issues by emitting
model_activityon issue delete and handling adeletedflag to send a singleverb="deleted"event.
- Webhooks:
- Deletion handling: In
apps/api/plane/bgtasks/webhook_task.py,model_activitynow detectsrequested_data["deleted"] == Trueand triggers a singlewebhook_activity(..., verb="deleted"), bypassing field-diff updates.- API:
- Issue delete: In
apps/api/plane/api/views/issue.pyIssueDetailAPIEndpoint.delete, after removing the issue and loggingissue_activity, now enqueuesmodel_activitywithmodel_name="issue",model_id,requested_data={"deleted": True},current_instance,actor_id,slug, andoriginto drive deletion webhooks.Written by Cursor Bugbot for commit 0582045eb3b166018e2b1ecb04f9ecd331c40e19. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
-
Bug Fixes
- Improved deletion event handling for issues, ensuring deletion events are properly recorded and distinguished in activity logs and webhooks.
-
Enhancements
- Webhooks now correctly identify and process issue deletions as distinct events rather than individual field changes.
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.
Walkthrough
When an issue is deleted, the system now enqueues a model-level activity task alongside the existing activity log. The webhook task processes this deletion event by detecting the deleted flag and emitting a single "deleted" webhook before any field-level comparisons occur.
Changes
| Cohort / File(s) | Summary |
|---|---|
Issue deletion handler apps/api/plane/api/views/issue.py |
Enqueues model_activity background task after issue deletion with deletion context (model_name="issue", model_id, requested_data, and context fields) |
Webhook hard delete handling apps/api/plane/bgtasks/webhook_task.py |
Adds explicit deletion path in model_activity: detects deleted==True in requested_data and emits webhook with verb "deleted", then exits early before per-field comparisons |
Sequence Diagram
sequenceDiagram
actor User
participant IssueView as Issue View
participant BGQueue as Background Queue
participant ActivityTask as Activity Task
participant WebhookTask as Webhook Task
participant Webhook as Webhook Endpoint
User->>IssueView: Delete Issue
IssueView->>BGQueue: Enqueue issue_activity.delay()
IssueView->>BGQueue: Enqueue model_activity(model_name="issue", deleted=True)
rect rgb(200, 220, 255)
Note over ActivityTask,WebhookTask: Deletion Processing
BGQueue->>WebhookTask: model_activity task
alt Deletion Event
WebhookTask->>WebhookTask: Detect deleted==True in requested_data
WebhookTask->>Webhook: Emit webhook(verb="deleted")
else Non-deletion Update
WebhookTask->>WebhookTask: Compare fields in requested_data
WebhookTask->>Webhook: Emit webhook(verb="updated")
end
end
Webhook-->>User: Webhook delivered
Estimated code review effort
๐ฏ 3 (Moderate) | โฑ๏ธ ~20 minutes
- Areas requiring attention:
- Verify the early exit in
model_activitydoesn't inadvertently skip necessary processing for deletion events - Confirm the context fields (current_instance, actor_id, slug, origin) are correctly populated when enqueued from the issue delete handler
- Ensure the webhook emission for "deleted" verb is compatible with downstream systems expecting this new event type
- Check that the existing per-field comparison logic for updates remains unaffected by the new deletion conditional
- Verify the early exit in
Poem
๐ฐ A deletion flows through queues so deep,
Model activity takes a leap,
Webhooks sing the "deleted" cry,
Before field diffs say goodbye!
Logs and events dance in harmony bright, ๐ญ
Pre-merge checks and finishing touches
โ Passed checks (3 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title Check | โ Passed | The pull request title "Restore Missing Webhook Notifications for Issue Deletion" directly and accurately reflects the main objective of the changeset. The changes address a regression where issue deletion webhooks were not firing, and the fix restores this functionality by invoking model_activity on issue deletion and handling the deleted flag to emit webhook events. The title is concise, clear, and specific enough for a teammate to understand the primary change without ambiguity. |
| Description Check | โ Passed | The pull request description is comprehensive and detailed, providing a clear problem statement, root cause analysis, and explanation of the two-commit fix. The description covers the issue background (GitHub issue #8054), the regression cause, specific implementation details for both affected files, and before/after results showing the restoration of webhook functionality. However, the description deviates from the template structure by not explicitly marking the Type of Change (which would be "Bug fix"), not formally including a Test Scenarios section describing specific test steps, and not using the References section with the template checkbox format. Despite these structural gaps, the core content is thorough and the omitted sections are non-critical given the detailed explanations already provided. |
| Docstring Coverage | โ Passed | Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. |
โจ Finishing touches
- [ ] ๐ Generate docstrings
๐งช Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.