Skip to content

Commit 8521fc6

Browse files
jianyuanandrewshie-sentry
authored andcommitted
ref: abstract on_create_or_update_comment_error method (#89683)
1 parent 552aef7 commit 8521fc6

File tree

9 files changed

+69
-40
lines changed

9 files changed

+69
-40
lines changed

src/sentry/integrations/github/integration.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
IntegrationMetadata,
2727
IntegrationProvider,
2828
)
29-
from sentry.integrations.github.constants import RATE_LIMITED_MESSAGE
29+
from sentry.integrations.github.constants import ISSUE_LOCKED_ERROR_MESSAGE, RATE_LIMITED_MESSAGE
3030
from sentry.integrations.github.tasks.link_all_repos import link_all_repos
3131
from sentry.integrations.models.integration import Integration
3232
from sentry.integrations.models.organization_integration import OrganizationIntegration
@@ -290,6 +290,26 @@ def search_issues(self, query: str | None, **kwargs) -> dict[str, Any]:
290290
assert isinstance(resp, dict)
291291
return resp
292292

293+
# CommitContextIntegration methods
294+
295+
def on_create_or_update_comment_error(self, api_error: ApiError, metrics_base: str) -> bool:
296+
if api_error.json:
297+
if ISSUE_LOCKED_ERROR_MESSAGE in api_error.json.get("message", ""):
298+
metrics.incr(
299+
metrics_base.format(integration=self.integration_name, key="error"),
300+
tags={"type": "issue_locked_error"},
301+
)
302+
return True
303+
304+
elif RATE_LIMITED_MESSAGE in api_error.json.get("message", ""):
305+
metrics.incr(
306+
metrics_base.format(integration=self.integration_name, key="error"),
307+
tags={"type": "rate_limited_error"},
308+
)
309+
return True
310+
311+
return False
312+
293313

294314
class GitHubIntegrationProvider(IntegrationProvider):
295315
key = "github"

src/sentry/integrations/github/tasks/open_pr_comment.py

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
from sentry.constants import EXTENSION_LANGUAGE_MAP, ObjectStatus
2525
from sentry.integrations.github.client import GitHubApiClient
26-
from sentry.integrations.github.constants import ISSUE_LOCKED_ERROR_MESSAGE, RATE_LIMITED_MESSAGE
26+
from sentry.integrations.github.constants import RATE_LIMITED_MESSAGE
2727
from sentry.integrations.github.tasks.pr_comment import format_comment_url
2828
from sentry.integrations.github.tasks.utils import (
2929
GithubAPIErrorType,
@@ -624,20 +624,10 @@ def open_pr_comment_workflow(pr_id: int) -> None:
624624
language=language,
625625
)
626626
except ApiError as e:
627-
if e.json:
628-
if ISSUE_LOCKED_ERROR_MESSAGE in e.json.get("message", ""):
629-
metrics.incr(
630-
OPEN_PR_METRICS_BASE.format(integration="github", key="error"),
631-
tags={"type": "issue_locked_error"},
632-
)
633-
return
634-
635-
elif RATE_LIMITED_MESSAGE in e.json.get("message", ""):
636-
metrics.incr(
637-
OPEN_PR_METRICS_BASE.format(integration="github", key="error"),
638-
tags={"type": "rate_limited_error"},
639-
)
640-
return
627+
if installation.on_create_or_update_comment_error(
628+
api_error=e, metrics_base=OPEN_PR_METRICS_BASE
629+
):
630+
return
641631

642632
metrics.incr(
643633
OPEN_PR_METRICS_BASE.format(integration="github", key="error"),

src/sentry/integrations/github/tasks/pr_comment.py

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from sentry import features
1313
from sentry.constants import ObjectStatus
14-
from sentry.integrations.github.constants import ISSUE_LOCKED_ERROR_MESSAGE, RATE_LIMITED_MESSAGE
14+
from sentry.integrations.github.constants import RATE_LIMITED_MESSAGE
1515
from sentry.integrations.github.tasks.utils import PullRequestIssue
1616
from sentry.integrations.services.integration import integration_service
1717
from sentry.integrations.source_code_management.commit_context import CommitContextIntegration
@@ -249,20 +249,10 @@ def github_comment_workflow(pullrequest_id: int, project_id: int):
249249
except ApiError as e:
250250
cache.delete(cache_key)
251251

252-
if e.json:
253-
if ISSUE_LOCKED_ERROR_MESSAGE in e.json.get("message", ""):
254-
metrics.incr(
255-
MERGED_PR_METRICS_BASE.format(integration="github", key="error"),
256-
tags={"type": "issue_locked_error"},
257-
)
258-
return
259-
260-
elif RATE_LIMITED_MESSAGE in e.json.get("message", ""):
261-
metrics.incr(
262-
MERGED_PR_METRICS_BASE.format(integration="github", key="error"),
263-
tags={"type": "rate_limited_error"},
264-
)
265-
return
252+
if installation.on_create_or_update_comment_error(
253+
api_error=e, metrics_base=MERGED_PR_METRICS_BASE
254+
):
255+
return
266256

267257
metrics.incr(
268258
MERGED_PR_METRICS_BASE.format(integration="github", key="error"),

src/sentry/integrations/github_enterprise/integration.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,11 @@ def has_repo_access(self, repo: RpcRepository) -> bool:
232232
# TODO: define this, used to migrate repositories
233233
return False
234234

235+
# CommitContextIntegration methods
236+
237+
def on_create_or_update_comment_error(self, api_error: ApiError, metrics_base: str) -> bool:
238+
raise NotImplementedError
239+
235240

236241
class InstallationForm(forms.Form):
237242
url = forms.CharField(

src/sentry/integrations/gitlab/integration.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ def extract_source_path_from_source_url(self, repo: Repository, url: str) -> str
160160
_, _, source_path = url.partition("/")
161161
return source_path
162162

163+
# CommitContextIntegration methods
164+
165+
def on_create_or_update_comment_error(self, api_error: ApiError, metrics_base: str) -> bool:
166+
raise NotImplementedError
167+
163168
# Gitlab only functions
164169

165170
def get_group_id(self):

src/sentry/integrations/source_code_management/commit_context.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
)
3535
from sentry.models.repository import Repository
3636
from sentry.shared_integrations.exceptions import (
37+
ApiError,
3738
ApiInvalidRequestError,
3839
ApiRateLimitedError,
3940
ApiRetryError,
@@ -375,6 +376,15 @@ def create_or_update_comment(
375376
extra={"new_comment": pr_comment is None, "pr_key": pr_key, "repo": repo.name},
376377
)
377378

379+
@abstractmethod
380+
def on_create_or_update_comment_error(self, api_error: ApiError, metrics_base: str) -> bool:
381+
"""
382+
Handle errors from the create_or_update_comment method.
383+
384+
Returns True if the error was handled, False otherwise.
385+
"""
386+
raise NotImplementedError
387+
378388

379389
class CommitContextClient(ABC):
380390
base_url: str

tests/sentry/integrations/github/tasks/test_open_pr_comment.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,9 +1035,11 @@ def test_comment_workflow_early_return(
10351035

10361036
@patch("sentry.analytics.record")
10371037
@patch("sentry.integrations.github.tasks.open_pr_comment.metrics")
1038+
@patch("sentry.integrations.github.integration.metrics")
10381039
@responses.activate
10391040
def test_comment_workflow_api_error(
10401041
self,
1042+
mock_integration_metrics,
10411043
mock_metrics,
10421044
mock_analytics,
10431045
_,
@@ -1083,7 +1085,9 @@ def test_comment_workflow_api_error(
10831085

10841086
with pytest.raises(ApiError):
10851087
open_pr_comment_workflow(self.pr.id)
1086-
mock_metrics.incr.assert_called_with("github.open_pr_comment.api_error")
1088+
mock_metrics.incr.assert_called_with(
1089+
"github.open_pr_comment.error", tags={"type": "api_error"}
1090+
)
10871091

10881092
pr_2 = PullRequest.objects.create(
10891093
organization_id=self.organization.id,
@@ -1093,7 +1097,7 @@ def test_comment_workflow_api_error(
10931097

10941098
# does not raise ApiError for locked issue
10951099
open_pr_comment_workflow(pr_2.id)
1096-
mock_metrics.incr.assert_called_with(
1100+
mock_integration_metrics.incr.assert_called_with(
10971101
"github.open_pr_comment.error", tags={"type": "issue_locked_error"}
10981102
)
10991103

@@ -1106,7 +1110,7 @@ def test_comment_workflow_api_error(
11061110
# does not raise ApiError for rate limited error
11071111
open_pr_comment_workflow(pr_3.id)
11081112

1109-
mock_metrics.incr.assert_called_with(
1113+
mock_integration_metrics.incr.assert_called_with(
11101114
"github.open_pr_comment.error", tags={"type": "rate_limited_error"}
11111115
)
11121116
assert not mock_analytics.called

tests/sentry/integrations/github/tasks/test_pr_comment.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,9 @@ def test_comment_workflow_updates_comment(self, mock_metrics, mock_issues):
492492

493493
@patch("sentry.integrations.github.tasks.pr_comment.get_top_5_issues_by_count")
494494
@patch("sentry.integrations.github.tasks.pr_comment.metrics")
495+
@patch("sentry.integrations.github.integration.metrics")
495496
@responses.activate
496-
def test_comment_workflow_api_error(self, mock_metrics, mock_issues):
497+
def test_comment_workflow_api_error(self, mock_integration_metrics, mock_metrics, mock_issues):
497498
cache.set(self.cache_key, True, timedelta(minutes=5).total_seconds())
498499
mock_issues.return_value = [
499500
{"group_id": g.id, "event_count": 10} for g in Group.objects.all()
@@ -526,8 +527,8 @@ def test_comment_workflow_api_error(self, mock_metrics, mock_issues):
526527

527528
with pytest.raises(ApiError):
528529
github_comment_workflow(self.pr.id, self.project.id)
529-
assert cache.get(self.cache_key) is None
530-
mock_metrics.incr.assert_called_with("github.pr_comment.api_error")
530+
assert cache.get(self.cache_key) is None
531+
mock_metrics.incr.assert_called_with("github.pr_comment.error", tags={"type": "api_error"})
531532

532533
pr_2 = self.create_pr_issues()
533534
cache_key = DEBOUNCE_PR_COMMENT_CACHE_KEY(pr_2.id)
@@ -536,7 +537,7 @@ def test_comment_workflow_api_error(self, mock_metrics, mock_issues):
536537
# does not raise ApiError for locked issue
537538
github_comment_workflow(pr_2.id, self.project.id)
538539
assert cache.get(cache_key) is None
539-
mock_metrics.incr.assert_called_with(
540+
mock_integration_metrics.incr.assert_called_with(
540541
"github.pr_comment.error", tags={"type": "issue_locked_error"}
541542
)
542543

@@ -547,7 +548,7 @@ def test_comment_workflow_api_error(self, mock_metrics, mock_issues):
547548
# does not raise ApiError for rate limited error
548549
github_comment_workflow(pr_3.id, self.project.id)
549550
assert cache.get(cache_key) is None
550-
mock_metrics.incr.assert_called_with(
551+
mock_integration_metrics.incr.assert_called_with(
551552
"github.pr_comment.error", tags={"type": "rate_limited_error"}
552553
)
553554

tests/sentry/integrations/source_code_management/test_commit_context_slo.py renamed to tests/sentry/integrations/source_code_management/test_commit_context.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
)
1010
from sentry.integrations.types import EventLifecycleOutcome
1111
from sentry.models.repository import Repository
12+
from sentry.shared_integrations.exceptions import ApiError
1213
from sentry.testutils.asserts import assert_failure_metric, assert_halt_metric, assert_slo_metric
1314
from sentry.testutils.cases import TestCase
1415
from sentry.users.models.identity import Identity
@@ -26,8 +27,11 @@ def __init__(self):
2627
def get_client(self):
2728
return self.client
2829

30+
def on_create_or_update_comment_error(self, api_error: ApiError, metrics_base: str) -> bool:
31+
raise NotImplementedError
2932

30-
class CommitContextIntegrationTest(TestCase):
33+
34+
class TestCommitContextIntegrationSLO(TestCase):
3135
def setUp(self):
3236
super().setUp()
3337
self.integration = MockCommitContextIntegration()

0 commit comments

Comments
 (0)