diff --git a/src/sentry/api/serializers/models/group.py b/src/sentry/api/serializers/models/group.py index d730e2c20e5e7a..f6660e22888d51 100644 --- a/src/sentry/api/serializers/models/group.py +++ b/src/sentry/api/serializers/models/group.py @@ -40,13 +40,14 @@ from sentry.models.team import Team from sentry.models.user import User from sentry.notifications.helpers import collect_groups_by_project, get_subscription_from_attributes -from sentry.notifications.types import GroupSubscriptionStatus, NotificationSettingEnum +from sentry.notifications.types import NotificationSettingEnum from sentry.reprocessing2 import get_progress from sentry.search.events.constants import RELEASE_STAGE_ALIAS from sentry.search.events.filter import convert_search_filter_to_snuba_query, format_search_filter from sentry.services.hybrid_cloud.auth import AuthenticatedToken from sentry.services.hybrid_cloud.integration import integration_service from sentry.services.hybrid_cloud.notifications import notifications_service +from sentry.services.hybrid_cloud.notifications.serial import deserialize_group_subscription_status from sentry.services.hybrid_cloud.user.serial import serialize_generic_user from sentry.services.hybrid_cloud.user.service import user_service from sentry.snuba.dataset import Dataset @@ -573,7 +574,11 @@ def _get_subscriptions( enabled_settings = notifications_service.get_subscriptions_for_projects( user_id=user.id, project_ids=project_ids, type=NotificationSettingEnum.WORKFLOW ) - query_groups = {group for group in groups if (not enabled_settings[group.project_id][2])} + query_groups = { + group + for group in groups + if (not enabled_settings[group.project_id].has_only_inactive_subscriptions) + } subscriptions_by_group_id: dict[int, GroupSubscription] = { subscription.group_id: subscription for subscription in GroupSubscription.objects.filter( @@ -585,11 +590,7 @@ def _get_subscriptions( results = {} for project_id, group_set in groups_by_project.items(): s = enabled_settings[project_id] - subscription_status = GroupSubscriptionStatus( - is_disabled=s[0], - is_active=s[1], - has_only_inactive_subscriptions=s[2], - ) + subscription_status = deserialize_group_subscription_status(s) for group in group_set: subscription = subscriptions_by_group_id.get(group.id) if subscription: diff --git a/src/sentry/integrations/github/webhook.py b/src/sentry/integrations/github/webhook.py index 3661d6ea9958bb..03b2ef819de75f 100644 --- a/src/sentry/integrations/github/webhook.py +++ b/src/sentry/integrations/github/webhook.py @@ -90,10 +90,10 @@ def _handle( def __call__(self, event: Mapping[str, Any], host: str | None = None) -> None: external_id = get_github_external_id(event=event, host=host) - integration, installs = integration_service.get_organization_contexts( + contexts = integration_service.get_organization_contexts( external_id=external_id, provider=self.provider ) - if integration is None or not installs: + if contexts.integration is None or not contexts.installs: # It seems possible for the GH or GHE app to be installed on their # end, but the integration to not exist. Possibly from deleting in # Sentry first or from a failed install flow (where the integration @@ -113,7 +113,7 @@ def __call__(self, event: Mapping[str, Any], host: str | None = None) -> None: orgs = { org.id: org for org in Organization.objects.filter( - id__in=[install.organization_id for install in installs] + id__in=[install.organization_id for install in contexts.installs] ) } repos = Repository.objects.filter( @@ -123,10 +123,10 @@ def __call__(self, event: Mapping[str, Any], host: str | None = None) -> None: ) if not repos.exists(): - provider = get_integration_repository_provider(integration) + provider = get_integration_repository_provider(contexts.integration) config = { - "integration_id": integration.id, + "integration_id": contexts.integration.id, "external_id": str(event["repository"]["id"]), "identifier": event.get("repository", {}).get("full_name", None), } @@ -153,7 +153,7 @@ def __call__(self, event: Mapping[str, Any], host: str | None = None) -> None: repos = repos.all() for repo in repos.exclude(status=ObjectStatus.HIDDEN): - self._handle(integration, event, orgs[repo.organization_id], repo) + self._handle(contexts.integration, event, orgs[repo.organization_id], repo) def update_repo_data(self, repo: Repository, event: Mapping[str, Any]) -> None: """ @@ -213,12 +213,12 @@ def __call__(self, event: Mapping[str, Any], host: str | None = None) -> None: external_id = event["installation"]["id"] if host: external_id = "{}:{}".format(host, event["installation"]["id"]) - integration, org_integrations = integration_service.get_organization_contexts( + contexts = integration_service.get_organization_contexts( provider=self.provider, external_id=external_id, ) - if integration is not None: - self._handle_delete(event, integration, org_integrations) + if contexts.integration is not None: + self._handle_delete(event, contexts.integration, contexts.installs) else: # It seems possible for the GH or GHE app to be installed on their # end, but the integration to not exist. Possibly from deleting in diff --git a/src/sentry/integrations/gitlab/webhooks.py b/src/sentry/integrations/gitlab/webhooks.py index 3b40a64ec54b07..71492e17630852 100644 --- a/src/sentry/integrations/gitlab/webhooks.py +++ b/src/sentry/integrations/gitlab/webhooks.py @@ -270,10 +270,10 @@ def post(self, request: Request) -> HttpResponse: return result (external_id, secret) = result - integration, installs = integration_service.get_organization_contexts( + contexts = integration_service.get_organization_contexts( provider=self.provider, external_id=external_id ) - if integration is None: + if contexts.integration is None: logger.info("gitlab.webhook.invalid-organization", extra=extra) extra["reason"] = "There is no integration that matches your organization." logger.error(extra["reason"]) @@ -286,16 +286,16 @@ def post(self, request: Request) -> HttpResponse: # The metadata could be useful to debug # domain_name -> gitlab.com/getsentry-ecosystem/foo' # scopes -> ['api'] - "metadata": integration.metadata, - "id": integration.id, # This is useful to query via Redash - "status": integration.status, # 0 seems to be active + "metadata": contexts.integration.metadata, + "id": contexts.integration.id, # This is useful to query via Redash + "status": contexts.integration.status, # 0 seems to be active }, - "org_ids": [install.organization_id for install in installs], + "org_ids": [install.organization_id for install in contexts.installs], }, } try: - if not constant_time_compare(secret, integration.metadata["webhook_secret"]): + if not constant_time_compare(secret, contexts.integration.metadata["webhook_secret"]): # Summary and potential workaround mentioned here: # https://github.com/getsentry/sentry/issues/34903#issuecomment-1262754478 # This forces a stack trace to be produced @@ -328,11 +328,11 @@ def post(self, request: Request) -> HttpResponse: logger.exception(extra["reason"]) return HttpResponse(status=400, reason=extra["reason"]) - for install in installs: + for install in contexts.installs: org_context = organization_service.get_organization_by_id( id=install.organization_id, include_teams=False, include_projects=False ) if org_context: organization = org_context.organization - handler()(integration, organization, event) + handler()(contexts.integration, organization, event) return HttpResponse(status=204) diff --git a/src/sentry/integrations/jira/utils/api.py b/src/sentry/integrations/jira/utils/api.py index 18d839a4d38ad1..7361e806b78c0b 100644 --- a/src/sentry/integrations/jira/utils/api.py +++ b/src/sentry/integrations/jira/utils/api.py @@ -90,10 +90,8 @@ def handle_status_change(integration, data): logger.info("jira.missing-changelog-status", extra=log_context) return - _, org_integrations = integration_service.get_organization_contexts( - integration_id=integration.id - ) - for oi in org_integrations: + contexts = integration_service.get_organization_contexts(integration_id=integration.id) + for oi in contexts.installs: install = integration.get_installation(organization_id=oi.organization_id) if isinstance(install, IssueSyncMixin): install.sync_status_inbound(issue_key, {"changelog": changelog, "issue": data["issue"]}) diff --git a/src/sentry/integrations/mixins/repositories.py b/src/sentry/integrations/mixins/repositories.py index 043caa6b04bf92..d97e317a8c44c7 100644 --- a/src/sentry/integrations/mixins/repositories.py +++ b/src/sentry/integrations/mixins/repositories.py @@ -122,9 +122,9 @@ def get_unmigratable_repositories(self) -> Collection[RpcRepository]: def reinstall_repositories(self) -> None: """Reinstalls repositories associated with the integration.""" - _, installs = integration_service.get_organization_contexts(integration_id=self.model.id) + contexts = integration_service.get_organization_contexts(integration_id=self.model.id) - for install in installs: + for install in contexts.installs: repository_service.reinstall_repositories_for_integration( organization_id=install.organization_id, integration_id=self.model.id, diff --git a/src/sentry/integrations/slack/webhooks/action.py b/src/sentry/integrations/slack/webhooks/action.py index 67bcb0798254ca..cd78a62be8753e 100644 --- a/src/sentry/integrations/slack/webhooks/action.py +++ b/src/sentry/integrations/slack/webhooks/action.py @@ -809,13 +809,13 @@ def post(self, request: Request) -> Response: if action_option in NOTIFICATION_SETTINGS_ACTION_OPTIONS: return self.handle_enable_notifications(slack_request) - _, org_integrations = integration_service.get_organization_contexts( + contexts = integration_service.get_organization_contexts( integration_id=slack_request.integration.id ) use_block_kit = False - if len(org_integrations): + if len(contexts.installs): org_context = organization_service.get_organization_by_id( - id=org_integrations[0].organization_id, include_projects=False, include_teams=False + id=contexts.installs[0].organization_id, include_projects=False, include_teams=False ) if org_context: use_block_kit = any( @@ -827,7 +827,7 @@ def post(self, request: Request) -> Response: ) else False ) - for oi in org_integrations + for oi in (contexts.installs) ] ) diff --git a/src/sentry/integrations/utils/scope.py b/src/sentry/integrations/utils/scope.py index 54b54609d51d02..eb2b2c470e24c4 100644 --- a/src/sentry/integrations/utils/scope.py +++ b/src/sentry/integrations/utils/scope.py @@ -50,11 +50,9 @@ def get_org_integrations( can be shared by multiple orgs. """ - _, org_integrations = integration_service.get_organization_contexts( - integration_id=integration_id - ) + contexts = integration_service.get_organization_contexts(integration_id=integration_id) - return org_integrations + return contexts.installs def bind_org_context_from_integration( diff --git a/src/sentry/services/hybrid_cloud/integration/impl.py b/src/sentry/services/hybrid_cloud/integration/impl.py index 4b7864a10495a6..7964207e8d62c0 100644 --- a/src/sentry/services/hybrid_cloud/integration/impl.py +++ b/src/sentry/services/hybrid_cloud/integration/impl.py @@ -26,6 +26,7 @@ from sentry.services.hybrid_cloud.integration.model import ( RpcIntegrationExternalProject, RpcIntegrationIdentityContext, + RpcOrganizationIntegrationContextResult, ) from sentry.services.hybrid_cloud.integration.serial import ( serialize_integration, @@ -234,7 +235,7 @@ def get_organization_contexts( integration_id: int | None = None, provider: str | None = None, external_id: str | None = None, - ) -> tuple[RpcIntegration | None, list[RpcOrganizationIntegration]]: + ) -> RpcOrganizationIntegrationContextResult: integration = self.get_integration( organization_id=organization_id, integration_id=integration_id, @@ -242,12 +243,14 @@ def get_organization_contexts( external_id=external_id, ) if not integration: - return (None, []) + return RpcOrganizationIntegrationContextResult(integration=None, installs=[]) organization_integrations = self.get_organization_integrations( integration_id=integration.id, organization_id=organization_id, ) - return (integration, organization_integrations) + return RpcOrganizationIntegrationContextResult( + integration=integration, installs=organization_integrations + ) def update_integrations( self, diff --git a/src/sentry/services/hybrid_cloud/integration/model.py b/src/sentry/services/hybrid_cloud/integration/model.py index 9bc21fa2f240b5..03be9d3d48909e 100644 --- a/src/sentry/services/hybrid_cloud/integration/model.py +++ b/src/sentry/services/hybrid_cloud/integration/model.py @@ -69,6 +69,11 @@ def get_status_display(self) -> str: return "disabled" +class RpcOrganizationIntegrationContextResult(RpcModel): + integration: RpcIntegration | None + installs: list[RpcOrganizationIntegration] + + class RpcIntegrationExternalProject(RpcModel): id: int organization_integration_id: int diff --git a/src/sentry/services/hybrid_cloud/integration/service.py b/src/sentry/services/hybrid_cloud/integration/service.py index 6776e7814d8ec0..2c3253364b4cbc 100644 --- a/src/sentry/services/hybrid_cloud/integration/service.py +++ b/src/sentry/services/hybrid_cloud/integration/service.py @@ -11,6 +11,7 @@ from sentry.services.hybrid_cloud.integration.model import ( RpcIntegrationExternalProject, RpcIntegrationIdentityContext, + RpcOrganizationIntegrationContextResult, ) from sentry.services.hybrid_cloud.pagination import RpcPaginationArgs, RpcPaginationResult from sentry.services.hybrid_cloud.rpc import RpcService, rpc_method @@ -128,8 +129,6 @@ def get_organization_integration( ) return ois[0] if len(ois) > 0 else None - @rpc_method - @abstractmethod def get_organization_context( self, *, @@ -142,6 +141,17 @@ def get_organization_context( Returns a tuple of RpcIntegration and RpcOrganizationIntegration. The integration is selected by either integration_id, or a combination of provider and external_id. """ + # This is a convencience method for unpacking `get_organization_contexts`. + # Note that it can't be an @rpc_method because it returns a fixed-size tuple. + + contexts = self.get_organization_contexts( + organization_id=organization_id, + integration_id=integration_id, + provider=provider, + external_id=external_id, + ) + + return contexts.integration, (contexts.installs[0] if contexts.installs else None) @rpc_method @abstractmethod @@ -152,11 +162,8 @@ def get_organization_contexts( integration_id: int | None = None, provider: str | None = None, external_id: str | None = None, - ) -> tuple[RpcIntegration | None, list[RpcOrganizationIntegration]]: - """ - Returns a tuple of RpcIntegration and RpcOrganizationIntegrations. The integrations are selected - by either integration_id, or a combination of provider and external_id. - """ + ) -> RpcOrganizationIntegrationContextResult: + pass @rpc_method @abstractmethod diff --git a/src/sentry/services/hybrid_cloud/notifications/impl.py b/src/sentry/services/hybrid_cloud/notifications/impl.py index c62adea7af1782..7ed571b4f5a7d0 100644 --- a/src/sentry/services/hybrid_cloud/notifications/impl.py +++ b/src/sentry/services/hybrid_cloud/notifications/impl.py @@ -14,7 +14,11 @@ NotificationSettingsOptionEnum, ) from sentry.services.hybrid_cloud.actor import ActorType, RpcActor -from sentry.services.hybrid_cloud.notifications import NotificationsService +from sentry.services.hybrid_cloud.notifications import ( + NotificationsService, + RpcGroupSubscriptionStatus, +) +from sentry.services.hybrid_cloud.notifications.serial import serialize_group_subscription_status from sentry.services.hybrid_cloud.user.service import user_service from sentry.types.integrations import EXTERNAL_PROVIDERS, ExternalProviderEnum, ExternalProviders @@ -118,7 +122,7 @@ def get_subscriptions_for_projects( user_id: int, project_ids: list[int], type: NotificationSettingEnum, - ) -> Mapping[int, tuple[bool, bool, bool]]: + ) -> Mapping[int, RpcGroupSubscriptionStatus]: """ Returns a mapping of project_id to a tuple of (is_disabled, is_active, has_only_inactive_subscriptions) """ @@ -132,7 +136,7 @@ def get_subscriptions_for_projects( type=type, ) return { - project: (s.is_disabled, s.is_active, s.has_only_inactive_subscriptions) + project: serialize_group_subscription_status(s) # TODO(Steve): Simplify API to pass in one project at a time for project, s in controller.get_subscriptions_status_for_projects( user=user, project_ids=project_ids, type=type diff --git a/src/sentry/services/hybrid_cloud/notifications/model.py b/src/sentry/services/hybrid_cloud/notifications/model.py index 2c10ae6cbd4826..e5d6ec61f250ba 100644 --- a/src/sentry/services/hybrid_cloud/notifications/model.py +++ b/src/sentry/services/hybrid_cloud/notifications/model.py @@ -20,3 +20,9 @@ class RpcExternalActor(RpcModel): external_name: str = "" # The unique identifier i.e user ID, channel ID. external_id: str | None = None + + +class RpcGroupSubscriptionStatus(RpcModel): + is_disabled: bool + is_active: bool + has_only_inactive_subscriptions: bool diff --git a/src/sentry/services/hybrid_cloud/notifications/serial.py b/src/sentry/services/hybrid_cloud/notifications/serial.py index b9b9eaf8da86d2..bd34226a95cadb 100644 --- a/src/sentry/services/hybrid_cloud/notifications/serial.py +++ b/src/sentry/services/hybrid_cloud/notifications/serial.py @@ -1,5 +1,6 @@ from sentry.models.integrations.external_actor import ExternalActor -from sentry.services.hybrid_cloud.notifications import RpcExternalActor +from sentry.notifications.types import GroupSubscriptionStatus +from sentry.services.hybrid_cloud.notifications import RpcExternalActor, RpcGroupSubscriptionStatus def serialize_external_actor(actor: ExternalActor) -> RpcExternalActor: @@ -13,3 +14,23 @@ def serialize_external_actor(actor: ExternalActor) -> RpcExternalActor: external_name=actor.external_name, external_id=actor.external_id, ) + + +def serialize_group_subscription_status( + status: GroupSubscriptionStatus, +) -> RpcGroupSubscriptionStatus: + return RpcGroupSubscriptionStatus( + is_disabled=status.is_disabled, + is_active=status.is_active, + has_only_inactive_subscriptions=status.has_only_inactive_subscriptions, + ) + + +def deserialize_group_subscription_status( + status: RpcGroupSubscriptionStatus, +) -> GroupSubscriptionStatus: + return GroupSubscriptionStatus( + is_disabled=status.is_disabled, + is_active=status.is_active, + has_only_inactive_subscriptions=status.has_only_inactive_subscriptions, + ) diff --git a/src/sentry/services/hybrid_cloud/notifications/service.py b/src/sentry/services/hybrid_cloud/notifications/service.py index fb256f0fa5b514..bbdd5c522603c6 100644 --- a/src/sentry/services/hybrid_cloud/notifications/service.py +++ b/src/sentry/services/hybrid_cloud/notifications/service.py @@ -11,6 +11,7 @@ NotificationSettingsOptionEnum, ) from sentry.services.hybrid_cloud.actor import ActorType, RpcActor +from sentry.services.hybrid_cloud.notifications import RpcGroupSubscriptionStatus from sentry.services.hybrid_cloud.rpc import RpcService, rpc_method from sentry.silo import SiloMode from sentry.types.integrations import ExternalProviderEnum, ExternalProviders @@ -78,7 +79,7 @@ def get_subscriptions_for_projects( user_id: int, project_ids: list[int], type: NotificationSettingEnum, - ) -> Mapping[int, tuple[bool, bool, bool]]: + ) -> Mapping[int, RpcGroupSubscriptionStatus]: pass @rpc_method diff --git a/src/sentry/services/hybrid_cloud/user/impl.py b/src/sentry/services/hybrid_cloud/user/impl.py index 1c28c8943b0ac7..3bb9d4445932e8 100644 --- a/src/sentry/services/hybrid_cloud/user/impl.py +++ b/src/sentry/services/hybrid_cloud/user/impl.py @@ -37,7 +37,11 @@ UserSerializeType, UserUpdateArgs, ) -from sentry.services.hybrid_cloud.user.model import RpcVerifyUserEmail, UserIdEmailArgs +from sentry.services.hybrid_cloud.user.model import ( + RpcUserCreationResult, + RpcVerifyUserEmail, + UserIdEmailArgs, +) from sentry.services.hybrid_cloud.user.serial import serialize_rpc_user, serialize_user_avatar from sentry.services.hybrid_cloud.user.service import UserService from sentry.signals import user_signup @@ -193,11 +197,11 @@ def get_first_superuser(self) -> RpcUser | None: def get_or_create_user_by_email( self, *, email: str, ident: str | None = None, referrer: str | None = None - ) -> tuple[RpcUser, bool]: + ) -> RpcUserCreationResult: with transaction.atomic(router.db_for_write(User)): rpc_user = self.get_user_by_email(email=email, ident=ident) if rpc_user: - return (rpc_user, False) + return RpcUserCreationResult(user=rpc_user, was_newly_created=False) # Create User if it doesn't exist user = User.objects.create( @@ -209,7 +213,7 @@ def get_or_create_user_by_email( sender=self, user=user, source="api", referrer=referrer or "unknown" ) user.update(flags=F("flags").bitor(User.flags.newsletter_consent_prompt)) - return (serialize_rpc_user(user), True) + return RpcUserCreationResult(user=serialize_rpc_user(user), was_newly_created=True) def get_user_by_email( self, diff --git a/src/sentry/services/hybrid_cloud/user/model.py b/src/sentry/services/hybrid_cloud/user/model.py index df9038b68cc66b..e5f0186aa1b27c 100644 --- a/src/sentry/services/hybrid_cloud/user/model.py +++ b/src/sentry/services/hybrid_cloud/user/model.py @@ -150,3 +150,8 @@ class UserIdEmailArgs(TypedDict): class RpcVerifyUserEmail(RpcModel): exists: bool = False email: str = "" + + +class RpcUserCreationResult(RpcModel): + user: RpcUser + was_newly_created: bool diff --git a/src/sentry/services/hybrid_cloud/user/service.py b/src/sentry/services/hybrid_cloud/user/service.py index bc34ae2ecfc268..8fc3d611e4ee49 100644 --- a/src/sentry/services/hybrid_cloud/user/service.py +++ b/src/sentry/services/hybrid_cloud/user/service.py @@ -17,7 +17,12 @@ UserSerializeType, UserUpdateArgs, ) -from sentry.services.hybrid_cloud.user.model import RpcAvatar, RpcVerifyUserEmail, UserIdEmailArgs +from sentry.services.hybrid_cloud.user.model import ( + RpcAvatar, + RpcUserCreationResult, + RpcVerifyUserEmail, + UserIdEmailArgs, +) from sentry.silo import SiloMode @@ -146,7 +151,7 @@ def get_or_create_user_by_email( email: str, ident: str | None = None, referrer: str | None = None, - ) -> tuple[RpcUser, bool]: + ) -> RpcUserCreationResult: pass @rpc_method diff --git a/src/sentry/shared_integrations/client/base.py b/src/sentry/shared_integrations/client/base.py index e349b60bb985ee..753ada0cc98305 100644 --- a/src/sentry/shared_integrations/client/base.py +++ b/src/sentry/shared_integrations/client/base.py @@ -416,16 +416,14 @@ def record_error(self, error: Exception): self.disable_integration(buffer) def disable_integration(self, buffer: IntegrationRequestBuffer) -> None: - rpc_integration, rpc_org_integrations = integration_service.get_organization_contexts( - integration_id=self.integration_id - ) - if rpc_integration and rpc_integration.status == ObjectStatus.DISABLED: + contexts = integration_service.get_organization_contexts(integration_id=self.integration_id) + if contexts.integration and contexts.integration.status == ObjectStatus.DISABLED: return org = None - if len(rpc_org_integrations) > 0: + if len(contexts.installs) > 0: org_context = organization_service.get_organization_by_id( - id=rpc_org_integrations[0].organization_id, + id=contexts.installs[0].organization_id, include_projects=False, include_teams=False, ) @@ -436,18 +434,18 @@ def disable_integration(self, buffer: IntegrationRequestBuffer) -> None: "integration_id": self.integration_id, "buffer_record": buffer._get_all_from_buffer(), } - if len(rpc_org_integrations) == 0 and rpc_integration is None: + if len(contexts.installs) == 0 and contexts.integration is None: extra["provider"] = "unknown" extra["organization_id"] = "unknown" - elif len(rpc_org_integrations) == 0: - extra["provider"] = rpc_integration.provider + elif len(contexts.installs) == 0: + extra["provider"] = contexts.integration.provider extra["organization_id"] = "unknown" - elif rpc_integration is None: + elif contexts.integration is None: extra["provider"] = "unknown" - extra["organization_id"] = rpc_org_integrations[0].organization_id + extra["organization_id"] = contexts.installs[0].organization_id else: - extra["provider"] = rpc_integration.provider - extra["organization_id"] = rpc_org_integrations[0].organization_id + extra["provider"] = contexts.integration.provider + extra["organization_id"] = contexts.installs[0].organization_id self.logger.info( "integration.disabled", @@ -455,22 +453,22 @@ def disable_integration(self, buffer: IntegrationRequestBuffer) -> None: ) if org and ( - (rpc_integration.provider == "slack" and buffer.is_integration_fatal_broken()) - or (rpc_integration.provider == "github") + (contexts.integration.provider == "slack" and buffer.is_integration_fatal_broken()) + or (contexts.integration.provider == "github") or ( features.has("organizations:gitlab-disable-on-broken", org) - and rpc_integration.provider == "gitlab" + and contexts.integration.provider == "gitlab" ) ): integration_service.update_integration( - integration_id=rpc_integration.id, status=ObjectStatus.DISABLED + integration_id=contexts.integration.id, status=ObjectStatus.DISABLED ) - notify_disable(org, rpc_integration.provider, self._get_redis_key()) + notify_disable(org, contexts.integration.provider, self._get_redis_key()) buffer.clear() create_system_audit_entry( organization_id=org.id, target_object=org.id, event=audit_log.get_event_id("INTEGRATION_DISABLED"), - data={"provider": rpc_integration.provider}, + data={"provider": contexts.integration.provider}, ) return diff --git a/tests/sentry/hybridcloud/test_integration.py b/tests/sentry/hybridcloud/test_integration.py index 3f253794775d17..41a248e679026b 100644 --- a/tests/sentry/hybridcloud/test_integration.py +++ b/tests/sentry/hybridcloud/test_integration.py @@ -288,7 +288,10 @@ def test_get_organization_context(self): org_integration = self.integration3.add_organization(new_org.id) assert org_integration is not None - result_integration, result_org_integration = integration_service.get_organization_context( + ( + result_integration, + result_org_integration, + ) = integration_service.get_organization_context( organization_id=new_org.id, provider="example", ) diff --git a/tests/sentry/services/hybrid_cloud/user/test_impl.py b/tests/sentry/services/hybrid_cloud/user/test_impl.py index 2b3c66ee50ed9c..f1c811b3fe10a4 100644 --- a/tests/sentry/services/hybrid_cloud/user/test_impl.py +++ b/tests/sentry/services/hybrid_cloud/user/test_impl.py @@ -14,7 +14,8 @@ def setUp(self) -> None: def test_create_new_user(self): old_user_count = User.objects.all().count() - rpc_user, created = user_service.get_or_create_user_by_email(email="test@email.com") + result = user_service.get_or_create_user_by_email(email="test@email.com") + rpc_user, created = result.user, result.was_newly_created user = User.objects.get(id=rpc_user.id) new_user_count = User.objects.all().count() assert new_user_count == old_user_count + 1 @@ -28,7 +29,8 @@ def test_get_no_existing(self): def test_get_or_create_user(self): user1 = self.create_user(email="test@email.com", username="1") user2 = self.create_user(email="test@email.com", username="2") - user, created = user_service.get_or_create_user_by_email(email="test@email.com") + result = user_service.get_or_create_user_by_email(email="test@email.com") + user, created = result.user, result.was_newly_created assert user1.id == user.id assert user2.id != user.id assert created is False @@ -38,14 +40,16 @@ def test_get_active_user(self): email="test@email.com", username="inactive", is_active=False ) active_user = self.create_user(email="test@email.com", username="active") - user, created = user_service.get_or_create_user_by_email(email="test@email.com") + result = user_service.get_or_create_user_by_email(email="test@email.com") + user, created = result.user, result.was_newly_created assert active_user.id == user.id assert inactive_user.id != user.id assert created is False def test_get_user_ci(self): user = self.create_user(email="tESt@email.com") - fetched_user, created = user_service.get_or_create_user_by_email(email="TesT@email.com") + result = user_service.get_or_create_user_by_email(email="TesT@email.com") + fetched_user, created = result.user, result.was_newly_created assert user.id == fetched_user.id assert created is False @@ -59,9 +63,10 @@ def test_get_user_with_ident(self): organization_id=org.id, provider="fly", config=config_data ) AuthIdentity.objects.create(auth_provider=provider, user=user2, ident=partner_user_id) - fetched_user, created = user_service.get_or_create_user_by_email( + result = user_service.get_or_create_user_by_email( email="TesT@email.com", ident=partner_user_id ) + fetched_user, created = result.user, result.was_newly_created assert user2.id == fetched_user.id assert user1.id != fetched_user.id assert created is False