feat(webhooks): Add REST API endpoint for webhook URL management#115861
feat(webhooks): Add REST API endpoint for webhook URL management#115861Christinarlong wants to merge 6 commits into
Conversation
Create a project-scoped endpoint at /legacy-webhooks/ that reads and
writes the same webhooks:urls ProjectOption used by the plugin:
- GET: returns {"urls": [...]}
- POST: accepts {"urls": [...]}, validates HTTP/HTTPS + is_valid_url
- DELETE: clears the webhooks:urls option
This replaces the plugin settings UI endpoint and can be used by the
frontend independently of the plugin system.
Refs: https://linear.app/getsentry/project/migrate-legacy-webhooks-away-from-plugins-c7549d6ed29b
Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
|
🚨 Warning: This pull request contains Frontend and Backend changes! It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently. Have questions? Please ask in the |
📊 Type Coverage Diff✅ No new type safety issues introduced. Coverage: 93.59% |
Use LegacyWebhookUrlsSerializer with CharField + URLValidator(schemes= ["http", "https"]) for format/scheme validation, and is_valid_url for IP blocklist checking. Update error assertions in tests. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
- Add LegacyWebhookUrlsSerializer with URLValidator for scheme check and is_valid_url for IP blocklist - Add LegacyWebhookEnabledSerializer for PUT enabled/disabled toggle - GET now returns both urls and enabled state - PUT sets webhooks:enabled (same ProjectOption the plugin uses) - Fix Serializer type arg (Serializer[None]) for mypy Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit aefe4c8. Configure here.
…alizer Django's URLValidator raises django.core.exceptions.ValidationError, which is not caught by DRF's serializer validation pipeline, causing a 500 instead of a 400 on invalid URLs.
leeandher
left a comment
There was a problem hiding this comment.
design nit about PUT vs POST, wondering if it'll be easier for you to just consolidate into one method, since updates/creates both overwrite whatever data was there before anyway, and it's not obvious which attributes are available on each method
either way i'll defer to you! feel free to keep both if its meant to be compatible with a UI/considerations that I'm missing
| def post(self, request: Request, project: Project) -> Response: | ||
| serializer = LegacyWebhookUrlsSerializer(data=request.data) | ||
| if not serializer.is_valid(): | ||
| return Response(serializer.errors, status=400) | ||
|
|
||
| urls = serializer.validated_data["urls"] | ||
| ProjectOption.objects.set_value(project, "webhooks:urls", "\n".join(urls)) | ||
| return Response({"urls": urls}, status=200) |
There was a problem hiding this comment.
Would this mean to create both project option rows you'd have to make a POST and PUT request to set both? Wondering if the PUT can be removed and have the POST just handle both, especially if it overrides the existing values anyway, but I might be missing something
There was a problem hiding this comment.
👍 POST should accept enabled as well.
| urls_raw = ProjectOption.objects.get_value(project, "webhooks:urls", default="") | ||
| urls = split_urls(urls_raw) | ||
| enabled = ProjectOption.objects.get_value(project, "webhooks:enabled", default=False) | ||
| return Response({"urls": urls, "enabled": enabled}) |
There was a problem hiding this comment.
nit: optional, but you could use a type or serializer here that gets used on all the methods (except delete probably)

Summary
PR 4 of the legacy webhook plugin migration. Independent of PRs 1-3 — this endpoint can land at any time.
Refs: https://linear.app/getsentry/project/migrate-legacy-webhooks-away-from-plugins-c7549d6ed29b