From a75423ba54bde83c785099076fc0e1e8b37ac9c7 Mon Sep 17 00:00:00 2001 From: "sentry[bot]" <39604003+sentry[bot]@users.noreply.github.com> Date: Sun, 6 Sep 2026 10:45:30 +0000 Subject: [PATCH 1/2] fix(sentry_apps): Treat missing servicehook as halt, not error --- src/sentry/sentry_apps/metrics.py | 1 + src/sentry/sentry_apps/tasks/sentry_apps.py | 3 ++- tests/sentry/sentry_apps/tasks/test_sentry_apps.py | 11 +++++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/sentry/sentry_apps/metrics.py b/src/sentry/sentry_apps/metrics.py index b5ed4fec2042..5cc1a5557b00 100644 --- a/src/sentry/sentry_apps/metrics.py +++ b/src/sentry/sentry_apps/metrics.py @@ -77,6 +77,7 @@ class SentryAppWebhookHaltReason(StrEnum): APP_DISABLED = "app_disabled" INNER_TIMEOUT = "inner_timeout" MISSING_GROUP = "missing_group" + MISSING_SERVICEHOOK = "missing_servicehook" class SentryAppExternalRequestFailureReason(StrEnum): diff --git a/src/sentry/sentry_apps/tasks/sentry_apps.py b/src/sentry/sentry_apps/tasks/sentry_apps.py index e324fe91ef44..940d4bc97c4a 100644 --- a/src/sentry/sentry_apps/tasks/sentry_apps.py +++ b/src/sentry/sentry_apps/tasks/sentry_apps.py @@ -813,7 +813,8 @@ def send_webhooks(installation: RpcSentryAppInstallation, event: str, **kwargs: "webhook_url": installation.sentry_app.webhook_url or "", } ) - raise SentryAppSentryError(message=SentryAppWebhookFailureReason.MISSING_SERVICEHOOK) + lifecycle.record_halt(halt_reason=SentryAppWebhookHaltReason.MISSING_SERVICEHOOK) + return if event not in servicehook.events: lifecycle.add_extras( { diff --git a/tests/sentry/sentry_apps/tasks/test_sentry_apps.py b/tests/sentry/sentry_apps/tasks/test_sentry_apps.py index b30efe021bd5..634845a9bf3b 100644 --- a/tests/sentry/sentry_apps/tasks/test_sentry_apps.py +++ b/tests/sentry/sentry_apps/tasks/test_sentry_apps.py @@ -1658,15 +1658,14 @@ def test_does_not_send_if_no_service_hook_exists( install = self.create_sentry_app_installation( organization=self.project.organization, slug=sentry_app.slug ) - with pytest.raises(SentryAppSentryError): - workflow_notification(install.id, self.issue.id, "assigned", self.user.id) + workflow_notification(install.id, self.issue.id, "assigned", self.user.id) assert not safe_urlopen.called # SLO assertions - assert_failure_metric( - mock_record, SentryAppSentryError(SentryAppWebhookFailureReason.MISSING_SERVICEHOOK) + assert_halt_metric( + mock_record, SentryAppWebhookHaltReason.MISSING_SERVICEHOOK ) - # APP_CREATE (success) -> UPDATE_WEBHOOK (success) -> GRANT_EXCHANGER (success) -> PREPARE_WEBHOOK (success) -> send_webhook (error) + # APP_CREATE (success) -> UPDATE_WEBHOOK (success) -> GRANT_EXCHANGER (success) -> PREPARE_WEBHOOK (success) -> send_webhook (halt) assert_count_of_metric( mock_record=mock_record, outcome=EventLifecycleOutcome.STARTED, outcome_count=5 ) @@ -1674,7 +1673,7 @@ def test_does_not_send_if_no_service_hook_exists( mock_record=mock_record, outcome=EventLifecycleOutcome.SUCCESS, outcome_count=4 ) assert_count_of_metric( - mock_record=mock_record, outcome=EventLifecycleOutcome.FAILURE, outcome_count=1 + mock_record=mock_record, outcome=EventLifecycleOutcome.FAILURE, outcome_count=0 ) @patch("sentry.integrations.utils.metrics.EventLifecycle.record_event") From cfd3f5cabc91ca768c11f77960111e919c61686d Mon Sep 17 00:00:00 2001 From: "sentry[bot]" <39604003+sentry[bot]@users.noreply.github.com> Date: Sun, 6 Sep 2026 10:59:14 +0000 Subject: [PATCH 2/2] fix(sentry_apps): Treat missing servicehook as halt, not error --- tests/sentry/sentry_apps/tasks/test_sentry_apps.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/sentry/sentry_apps/tasks/test_sentry_apps.py b/tests/sentry/sentry_apps/tasks/test_sentry_apps.py index 634845a9bf3b..16d307d6d82b 100644 --- a/tests/sentry/sentry_apps/tasks/test_sentry_apps.py +++ b/tests/sentry/sentry_apps/tasks/test_sentry_apps.py @@ -1662,9 +1662,7 @@ def test_does_not_send_if_no_service_hook_exists( assert not safe_urlopen.called # SLO assertions - assert_halt_metric( - mock_record, SentryAppWebhookHaltReason.MISSING_SERVICEHOOK - ) + assert_halt_metric(mock_record, SentryAppWebhookHaltReason.MISSING_SERVICEHOOK) # APP_CREATE (success) -> UPDATE_WEBHOOK (success) -> GRANT_EXCHANGER (success) -> PREPARE_WEBHOOK (success) -> send_webhook (halt) assert_count_of_metric( mock_record=mock_record, outcome=EventLifecycleOutcome.STARTED, outcome_count=5