Skip to content

Commit 45aa599

Browse files
grichaclaude
andcommitted
feat(hybridcloud): Propagate ViewerContext in Vercel webhook
Wrap the per-matched-org processing in _deployment_created with webhook_viewer_context so downstream code has access to the current organization identity via the ViewerContext contextvar. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1de477a commit 45aa599

File tree

1 file changed

+76
-70
lines changed

1 file changed

+76
-70
lines changed

src/sentry/integrations/vercel/webhook.py

Lines changed: 76 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from sentry.hybridcloud.services.organization_mapping import organization_mapping_service
2525
from sentry.integrations.models.integration import Integration
2626
from sentry.integrations.models.organization_integration import OrganizationIntegration
27+
from sentry.integrations.utils.webhook_viewer_context import webhook_viewer_context
2728
from sentry.models.project import Project
2829
from sentry.projects.services.project import project_service
2930
from sentry.sentry_apps.models.sentry_app_installation_for_provider import (
@@ -353,80 +354,85 @@ def _deployment_created(self, external_id, request):
353354
continue
354355
sentry_project_id = matched_mappings[0][0]
355356

356-
logging_params["organization_id"] = organization.id
357-
logging_params["project_id"] = sentry_project_id
358-
359-
try:
360-
release_payload, token = get_payload_and_token(
361-
payload, organization.id, sentry_project_id
362-
)
363-
except Project.DoesNotExist:
364-
logger.info("Project not found", extra=logging_params)
365-
return self.respond({"detail": "Project not found"}, status=404)
366-
except SentryAppInstallationForProvider.DoesNotExist:
367-
logger.info("Installation not found", extra=logging_params)
368-
return self.respond({"detail": "Installation not found"}, status=404)
369-
except SentryAppInstallationToken.DoesNotExist:
370-
logger.info("Token not found", extra=logging_params)
371-
return self.respond({"detail": "Token not found"}, status=404)
372-
except NoCommitFoundError:
373-
logger.info("No commit found", extra=logging_params)
374-
return self.respond({"detail": "No commit found"}, status=404)
375-
except MissingRepositoryError:
376-
logger.info("Could not determine repository", extra=logging_params)
377-
return self.respond({"detail": "Could not determine repository"}, status=400)
378-
379-
url = absolute_uri(f"/api/0/organizations/{organization.slug}/releases/")
380-
headers = {
381-
"Accept": "application/json",
382-
"Authorization": f"Bearer {token}",
383-
"User-Agent": f"sentry_vercel/{VERSION}",
384-
}
385-
json_error = None
386-
387-
no_ref_payload = {
388-
"version": release_payload["version"],
389-
"projects": release_payload["projects"],
390-
}
391-
392-
with http.build_session() as session:
393-
try:
394-
resp = session.post(url, json=no_ref_payload, headers=headers)
395-
json_error = safe_json_parse(resp)
396-
resp.raise_for_status()
397-
except RequestException as e:
398-
# errors here should be uncommon but we should be aware of them
399-
logger.warning(
400-
"Error creating release: %s - %s",
401-
e,
402-
json_error,
403-
extra=logging_params,
404-
)
405-
# 400 probably isn't the right status code but oh well
406-
return self.respond({"detail": f"Error creating release: {e}"}, status=400)
357+
with webhook_viewer_context(organization.id):
358+
logging_params["organization_id"] = organization.id
359+
logging_params["project_id"] = sentry_project_id
407360

408-
# set the refs
409361
try:
410-
resp = session.post(
411-
url,
412-
json=release_payload,
413-
headers=headers,
362+
release_payload, token = get_payload_and_token(
363+
payload, organization.id, sentry_project_id
414364
)
415-
json_error = safe_json_parse(resp)
416-
resp.raise_for_status()
417-
except RequestException as e:
418-
# errors will probably be common if the user doesn't have repos set up
419-
logger.info(
420-
"Error setting refs: %s - %s",
421-
e,
422-
json_error,
423-
extra=logging_params,
424-
exc_info=True,
365+
except Project.DoesNotExist:
366+
logger.info("Project not found", extra=logging_params)
367+
return self.respond({"detail": "Project not found"}, status=404)
368+
except SentryAppInstallationForProvider.DoesNotExist:
369+
logger.info("Installation not found", extra=logging_params)
370+
return self.respond({"detail": "Installation not found"}, status=404)
371+
except SentryAppInstallationToken.DoesNotExist:
372+
logger.info("Token not found", extra=logging_params)
373+
return self.respond({"detail": "Token not found"}, status=404)
374+
except NoCommitFoundError:
375+
logger.info("No commit found", extra=logging_params)
376+
return self.respond({"detail": "No commit found"}, status=404)
377+
except MissingRepositoryError:
378+
logger.info("Could not determine repository", extra=logging_params)
379+
return self.respond(
380+
{"detail": "Could not determine repository"}, status=400
425381
)
426-
# 400 probably isn't the right status code but oh well
427-
return self.respond({"detail": f"Error setting refs: {e}"}, status=400)
428382

429-
# we are going to quit after the first project match as there shouldn't be multiple matches
430-
return self.respond(status=201)
383+
url = absolute_uri(f"/api/0/organizations/{organization.slug}/releases/")
384+
headers = {
385+
"Accept": "application/json",
386+
"Authorization": f"Bearer {token}",
387+
"User-Agent": f"sentry_vercel/{VERSION}",
388+
}
389+
json_error = None
390+
391+
no_ref_payload = {
392+
"version": release_payload["version"],
393+
"projects": release_payload["projects"],
394+
}
395+
396+
with http.build_session() as session:
397+
try:
398+
resp = session.post(url, json=no_ref_payload, headers=headers)
399+
json_error = safe_json_parse(resp)
400+
resp.raise_for_status()
401+
except RequestException as e:
402+
# errors here should be uncommon but we should be aware of them
403+
logger.warning(
404+
"Error creating release: %s - %s",
405+
e,
406+
json_error,
407+
extra=logging_params,
408+
)
409+
# 400 probably isn't the right status code but oh well
410+
return self.respond(
411+
{"detail": f"Error creating release: {e}"}, status=400
412+
)
413+
414+
# set the refs
415+
try:
416+
resp = session.post(
417+
url,
418+
json=release_payload,
419+
headers=headers,
420+
)
421+
json_error = safe_json_parse(resp)
422+
resp.raise_for_status()
423+
except RequestException as e:
424+
# errors will probably be common if the user doesn't have repos set up
425+
logger.info(
426+
"Error setting refs: %s - %s",
427+
e,
428+
json_error,
429+
extra=logging_params,
430+
exc_info=True,
431+
)
432+
# 400 probably isn't the right status code but oh well
433+
return self.respond({"detail": f"Error setting refs: {e}"}, status=400)
434+
435+
# we are going to quit after the first project match as there shouldn't be multiple matches
436+
return self.respond(status=201)
431437

432438
return self.respond(status=204)

0 commit comments

Comments
 (0)