From 61ca1269248807ed0f4af510b2c558f90ad82b34 Mon Sep 17 00:00:00 2001 From: Lyn Nagara Date: Mon, 31 Aug 2026 14:23:08 -0700 Subject: [PATCH 1/3] ref: Begin deprecating `category` from localities No longer required, visibility is controlled via `visible` and `signup_visible` parameters --- src/sentry/core/endpoints/organization_index.py | 3 +-- src/sentry/testutils/cell.py | 3 +-- src/sentry/types/cell.py | 15 +++++---------- src/sentry/web/client_config.py | 2 -- .../core/endpoints/test_organization_index.py | 3 --- .../middleware/integrations/parsers/test_jira.py | 6 +++--- tests/sentry/types/test_cell.py | 7 +------ .../users/api/endpoints/test_user_regions.py | 8 ++------ tests/sentry/web/test_client_config.py | 6 +----- 9 files changed, 14 insertions(+), 39 deletions(-) diff --git a/src/sentry/core/endpoints/organization_index.py b/src/sentry/core/endpoints/organization_index.py index 8c3bcae76395..e31e8b531a0d 100644 --- a/src/sentry/core/endpoints/organization_index.py +++ b/src/sentry/core/endpoints/organization_index.py @@ -51,7 +51,6 @@ from sentry.silo.base import SiloMode from sentry.types.cell import ( CellResolutionError, - RegionCategory, get_locality_by_name, ) from sentry.users.services.user.serial import serialize_generic_user @@ -106,7 +105,7 @@ def validate_dataStorageLocation(self, value: str) -> str: if "request" in self.context and is_active_staff(self.context["request"]): # Staff users are allowed to create orgs in hidden cells/localities. return value - if locality.category != RegionCategory.MULTI_TENANT or not locality.visible: + if not locality.visible: raise serializers.ValidationError(f"Unknown data storage location {value!r}.") return value diff --git a/src/sentry/testutils/cell.py b/src/sentry/testutils/cell.py index 06498fd2098a..384d4e8a2fa7 100644 --- a/src/sentry/testutils/cell.py +++ b/src/sentry/testutils/cell.py @@ -5,7 +5,7 @@ from django.test import override_settings -from sentry.types.cell import Cell, CellDirectory, Locality, RegionCategory, get_global_directory +from sentry.types.cell import Cell, CellDirectory, Locality, get_global_directory class TestEnvCellDirectory(CellDirectory): @@ -24,7 +24,6 @@ def _apply_cells( Locality( name=c.name, cells=frozenset([c.name]), - category=RegionCategory.MULTI_TENANT, visible=c.visible, new_org_cell=c.name, ) diff --git a/src/sentry/types/cell.py b/src/sentry/types/cell.py index 8484bb136a11..ee60bf60c0dc 100644 --- a/src/sentry/types/cell.py +++ b/src/sentry/types/cell.py @@ -34,8 +34,6 @@ class Locality: cells: frozenset[str] """The set of cell names that belong to this locality.""" - category: RegionCategory - new_org_cell: str """The cell within this locality where new organizations are provisioned.""" @@ -45,6 +43,9 @@ class Locality: signup_visible: bool = True """Whether or not a locality should be visible for org signup/relocation.""" + category: RegionCategory = RegionCategory.MULTI_TENANT + """Deprecated. Visibility is defined via `visible` and `signup_visible`.""" + def to_url(self, path: str) -> str: """Resolve a path into a customer facing URL on this locality. @@ -495,11 +496,7 @@ def find_all_multitenant_locality_names() -> list[str]: """ Return all visible multi-tenant localities. """ - return [ - loc.name - for loc in get_global_directory().localities - if loc.category == RegionCategory.MULTI_TENANT and loc.visible - ] + return [loc.name for loc in get_global_directory().localities if loc.visible] def find_all_signup_locality_names() -> list[str]: @@ -507,7 +504,5 @@ def find_all_signup_locality_names() -> list[str]: Return all locality names that are visible to org signup. """ return [ - loc.name - for loc in get_global_directory().localities - if loc.category == RegionCategory.MULTI_TENANT and loc.visible and loc.signup_visible + loc.name for loc in get_global_directory().localities if loc.visible and loc.signup_visible ] diff --git a/src/sentry/web/client_config.py b/src/sentry/web/client_config.py index 78ae6dc1f48e..ab458d32917e 100644 --- a/src/sentry/web/client_config.py +++ b/src/sentry/web/client_config.py @@ -34,7 +34,6 @@ from sentry.types.cell import ( Cell, Locality, - RegionCategory, find_all_cell_names, find_all_multitenant_locality_names, find_all_signup_locality_names, @@ -368,7 +367,6 @@ def localities(self) -> list[Mapping[str, Any]]: def region_display_order(region: Locality) -> tuple[bool, bool, str]: return ( region.name != monolith_locality, # default locality comes first - region.category != RegionCategory.MULTI_TENANT, # multi-tenant before single region.name, # then sort alphabetically ) diff --git a/tests/sentry/core/endpoints/test_organization_index.py b/tests/sentry/core/endpoints/test_organization_index.py index 51b3057fa9cb..ee6d3572a379 100644 --- a/tests/sentry/core/endpoints/test_organization_index.py +++ b/tests/sentry/core/endpoints/test_organization_index.py @@ -289,14 +289,12 @@ def test_locality_to_cell_resolution(self) -> None: Locality( name="us", cells=frozenset(["us", "us2"]), - category=RegionCategory.MULTI_TENANT, new_org_cell="us2", visible=True, ), Locality( name="de", cells=frozenset(["de"]), - category=RegionCategory.MULTI_TENANT, new_org_cell="de", visible=True, ), @@ -339,7 +337,6 @@ def test_staff_user_override_cell_visiblity(self) -> None: Locality( name="ja", cells=frozenset(["ja"]), - category=RegionCategory.MULTI_TENANT, new_org_cell="ja", visible=False, ), diff --git a/tests/sentry/middleware/integrations/parsers/test_jira.py b/tests/sentry/middleware/integrations/parsers/test_jira.py index 486a380cf7a5..f2065ef143bc 100644 --- a/tests/sentry/middleware/integrations/parsers/test_jira.py +++ b/tests/sentry/middleware/integrations/parsers/test_jira.py @@ -15,12 +15,12 @@ from sentry.testutils.cell import override_cells from sentry.testutils.outbox import assert_no_webhook_payloads, assert_webhook_payloads_for_mailbox from sentry.testutils.silo import control_silo_test -from sentry.types.cell import Cell, Locality, RegionCategory +from sentry.types.cell import Cell, Locality cell = Cell("us", 1, "http://us.testserver") eu_cell = Cell("eu", 2, "http://eu.testserver") -locality = Locality("us", frozenset(["us"]), RegionCategory.MULTI_TENANT, new_org_cell="us") -eu_locality = Locality("eu", frozenset(["eu"]), RegionCategory.MULTI_TENANT, new_org_cell="eu") +locality = Locality("us", frozenset(["us"]), new_org_cell="us") +eu_locality = Locality("eu", frozenset(["eu"]), new_org_cell="eu") cell_config = (cell, eu_cell) diff --git a/tests/sentry/types/test_cell.py b/tests/sentry/types/test_cell.py index 6fe20551fc22..100c39951e5d 100644 --- a/tests/sentry/types/test_cell.py +++ b/tests/sentry/types/test_cell.py @@ -201,7 +201,7 @@ def test_validate_cell(self) -> None: cell.validate() def test_locality_to_url(self) -> None: - locality = Locality("us", frozenset(["us"]), RegionCategory.MULTI_TENANT, new_org_cell="us") + locality = Locality("us", frozenset(["us"]), new_org_cell="us") with override_settings(SILO_MODE=SiloMode.CELL, SENTRY_LOCAL_CELL="us"): assert locality.to_url("/avatar/abcdef/") == "http://us.testserver/avatar/abcdef/" with override_settings(SILO_MODE=SiloMode.CONTROL, SENTRY_LOCAL_CELL=""): @@ -345,14 +345,12 @@ def test_get_new_org_cell_for_locality(self) -> None: Locality( name="us", cells=frozenset(["us", "us2"]), - category=RegionCategory.MULTI_TENANT, new_org_cell="us2", visible=True, ), Locality( name="de", cells=frozenset(["de1", "de2"]), - category=RegionCategory.MULTI_TENANT, new_org_cell="de2", visible=True, ), @@ -392,14 +390,12 @@ def test_find_all_signup_locality_names(self) -> None: Locality( name="us", cells=frozenset(["us"]), - category=RegionCategory.MULTI_TENANT, new_org_cell="us", visible=True, ), Locality( name="de", cells=frozenset(["de"]), - category=RegionCategory.MULTI_TENANT, new_org_cell="de", visible=True, signup_visible=False, @@ -407,7 +403,6 @@ def test_find_all_signup_locality_names(self) -> None: Locality( name="ja", cells=frozenset(["ja"]), - category=RegionCategory.MULTI_TENANT, new_org_cell="de", visible=False, signup_visible=True, diff --git a/tests/sentry/users/api/endpoints/test_user_regions.py b/tests/sentry/users/api/endpoints/test_user_regions.py index 695b9ecab7f0..a4f0c5a6d93e 100644 --- a/tests/sentry/users/api/endpoints/test_user_regions.py +++ b/tests/sentry/users/api/endpoints/test_user_regions.py @@ -12,12 +12,8 @@ cell_config = (us, de, st) SECRET = "test-seer-api-shared-secret-thirty-two-bytes!" -us_locality = Locality( - name="us", cells=frozenset(["us"]), category=RegionCategory.MULTI_TENANT, new_org_cell="us" -) -de_locality = Locality( - name="de", cells=frozenset(["de"]), category=RegionCategory.MULTI_TENANT, new_org_cell="de" -) +us_locality = Locality(name="us", cells=frozenset(["us"]), new_org_cell="us") +de_locality = Locality(name="de", cells=frozenset(["de"]), new_org_cell="de") st_locality = Locality( name="acme", cells=frozenset(["acme"]), diff --git a/tests/sentry/web/test_client_config.py b/tests/sentry/web/test_client_config.py index 9e8f52b097cb..abc7a30788f1 100644 --- a/tests/sentry/web/test_client_config.py +++ b/tests/sentry/web/test_client_config.py @@ -71,12 +71,8 @@ def create_test_localities( cell.Locality( name=c.name, cells=frozenset([c.name]), - category=( - cell.RegionCategory.SINGLE_TENANT - if c.name in single_tenants - else cell.RegionCategory.MULTI_TENANT - ), new_org_cell=c.name, + visible=c.name not in single_tenants, ) for c in cells ) From 53c570f647b8c8591fbb65ebb50f7ad420f42bb2 Mon Sep 17 00:00:00 2001 From: Lyn Nagara Date: Mon, 31 Aug 2026 14:55:43 -0700 Subject: [PATCH 2/3] typing --- src/sentry/web/client_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/web/client_config.py b/src/sentry/web/client_config.py index ab458d32917e..00610bbbcb97 100644 --- a/src/sentry/web/client_config.py +++ b/src/sentry/web/client_config.py @@ -364,7 +364,7 @@ def localities(self) -> list[Mapping[str, Any]]: monolith_locality = get_locality_name_for_cell(settings.SENTRY_FALLBACK_CELL) - def region_display_order(region: Locality) -> tuple[bool, bool, str]: + def region_display_order(region: Locality) -> tuple[bool, str]: return ( region.name != monolith_locality, # default locality comes first region.name, # then sort alphabetically From 0bf30a6db2ab81c85504c058c7d935cc7f8cfd31 Mon Sep 17 00:00:00 2001 From: Lyn Nagara Date: Mon, 31 Aug 2026 15:23:00 -0700 Subject: [PATCH 3/3] org creation honors signup_visible --- src/sentry/core/endpoints/organization_index.py | 2 +- tests/sentry/core/endpoints/test_organization_index.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sentry/core/endpoints/organization_index.py b/src/sentry/core/endpoints/organization_index.py index e31e8b531a0d..fabc24d3a9f4 100644 --- a/src/sentry/core/endpoints/organization_index.py +++ b/src/sentry/core/endpoints/organization_index.py @@ -105,7 +105,7 @@ def validate_dataStorageLocation(self, value: str) -> str: if "request" in self.context and is_active_staff(self.context["request"]): # Staff users are allowed to create orgs in hidden cells/localities. return value - if not locality.visible: + if not locality.visible or not locality.signup_visible: raise serializers.ValidationError(f"Unknown data storage location {value!r}.") return value diff --git a/tests/sentry/core/endpoints/test_organization_index.py b/tests/sentry/core/endpoints/test_organization_index.py index ee6d3572a379..05f609c0b5da 100644 --- a/tests/sentry/core/endpoints/test_organization_index.py +++ b/tests/sentry/core/endpoints/test_organization_index.py @@ -346,6 +346,7 @@ def test_staff_user_override_cell_visiblity(self) -> None: category=RegionCategory.SINGLE_TENANT, new_org_cell="acme", visible=True, + signup_visible=False, ), ] with get_test_env_directory().swap_state(cells, localities):