10
10
SCMIntegrationInteractionType ,
11
11
)
12
12
from sentry .integrations .source_code_management .repository import BaseRepositoryIntegration
13
+ from sentry .integrations .utils .metrics import EventLifecycle
13
14
from sentry .models .group import Group
14
15
from sentry .shared_integrations .exceptions import ApiError , IntegrationError
15
16
17
+ SOURCE_CODE_ISSUE_HALT_PATTERNS = {
18
+ "No workspace with identifier" , # Bitbucket
19
+ }
20
+
16
21
17
22
class SourceCodeIssueIntegration (IssueBasicIntegration , BaseRepositoryIntegration , ABC ):
18
23
def record_event (self , event : SCMIntegrationInteractionType ):
@@ -23,35 +28,53 @@ def record_event(self, event: SCMIntegrationInteractionType):
23
28
org_integration = self .org_integration ,
24
29
)
25
30
26
- def get_repository_choices (self , group : Group | None , params : Mapping [str , Any ], ** kwargs ):
27
- """
28
- Returns the default repository and a set/subset of repositories of associated with the installation
29
- """
30
- with self .record_event (SCMIntegrationInteractionType .GET_REPOSITORY_CHOICES ).capture ():
31
- try :
32
- repos = self .get_repositories ()
33
- except ApiError :
34
- raise IntegrationError ("Unable to retrieve repositories. Please try again later." )
31
+ def _get_repository_choices (
32
+ self , * , group : Group | None , params : Mapping [str , Any ], lifecycle : EventLifecycle
33
+ ):
34
+ try :
35
+ repos = self .get_repositories ()
36
+ except ApiError as exc :
37
+ if any (pattern in str (exc ) for pattern in SOURCE_CODE_ISSUE_HALT_PATTERNS ):
38
+ lifecycle .record_halt (exc )
35
39
else :
36
- repo_choices = [(repo ["identifier" ], repo ["name" ]) for repo in repos ]
40
+ lifecycle .record_failure (exc )
41
+ raise IntegrationError ("Unable to retrieve repositories. Please try again later." )
42
+ else :
43
+ repo_choices = [(repo ["identifier" ], repo ["name" ]) for repo in repos ]
37
44
38
- defaults = self .get_project_defaults (group .project_id ) if group else {}
39
- repo = params .get ("repo" ) or defaults .get ("repo" )
45
+ defaults = self .get_project_defaults (group .project_id ) if group else {}
46
+ repo = params .get ("repo" ) or defaults .get ("repo" )
40
47
41
- try :
42
- default_repo = repo or repo_choices [0 ][0 ]
43
- except IndexError :
44
- return "" , repo_choices
48
+ try :
49
+ default_repo = repo or repo_choices [0 ][0 ]
50
+ except IndexError :
51
+ return "" , repo_choices
45
52
46
- # If a repo has been selected outside of the default list of
47
- # repos, stick it onto the front of the list so that it can be
48
- # selected.
49
- try :
50
- next (True for r in repo_choices if r [0 ] == default_repo )
51
- except StopIteration :
52
- repo_choices .insert (0 , self .create_default_repo_choice (default_repo ))
53
+ # If a repo has been selected outside of the default list of
54
+ # repos, stick it onto the front of the list so that it can be
55
+ # selected.
56
+ try :
57
+ next (True for r in repo_choices if r [0 ] == default_repo )
58
+ except StopIteration :
59
+ repo_choices .insert (0 , self .create_default_repo_choice (default_repo ))
60
+
61
+ return default_repo , repo_choices
53
62
54
- return default_repo , repo_choices
63
+ def get_repository_choices (self , group : Group | None , params : Mapping [str , Any ]):
64
+ """
65
+ Returns the default repository and a set/subset of repositories of associated with the installation
66
+ """
67
+ user_facing_error = None
68
+ with self .record_event (
69
+ SCMIntegrationInteractionType .GET_REPOSITORY_CHOICES
70
+ ).capture () as lifecycle :
71
+ try :
72
+ return self ._get_repository_choices (group = group , params = params , lifecycle = lifecycle )
73
+ except IntegrationError as exc :
74
+ user_facing_error = exc
75
+ # Now that we're outside the lifecycle, we can raise the user facing error
76
+ if user_facing_error :
77
+ raise user_facing_error
55
78
56
79
# TODO(saif): Make private and move all usages over to `get_defaults`
57
80
def get_project_defaults (self , project_id ):
0 commit comments