Skip to content

Commit 6b975cd

Browse files
committed
fix: Move underscore replacement from shared slugify_instance to Organization-specific code
1 parent 0260dc5 commit 6b975cd

File tree

5 files changed

+24
-4
lines changed

5 files changed

+24
-4
lines changed

src/sentry/db/models/utils.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ def slugify_instance(
103103
*args: Any,
104104
**kwargs: Any,
105105
) -> None:
106-
# Django's slugify() doesn't replace underscores with hyphens, so we need to do it manually
107-
# to ensure the slug matches ORG_SLUG_PATTERN which doesn't allow underscores
108-
value = slugify(label.replace("_", "-"))[:max_length]
106+
value = slugify(label)[:max_length]
109107
value = value.strip("-")
110108

111109
return unique_db_instance(inst, value, reserved, max_length, field_name, *args, **kwargs)

src/sentry/hybridcloud/services/control_organization_provisioning/impl.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ def _generate_org_snowflake_id(region_name: str) -> int:
9898
@staticmethod
9999
def _generate_org_slug(region_name: str, slug: str) -> str:
100100
surrogate_org_slug = OrganizationSlugReservation()
101-
slugify_instance(surrogate_org_slug, slug, reserved=RESERVED_ORGANIZATION_SLUGS)
101+
# Django's slugify() doesn't replace underscores with hyphens, so we need to do it manually
102+
# to ensure the slug matches ORG_SLUG_PATTERN which doesn't allow underscores
103+
slugify_instance(surrogate_org_slug, slug.replace("_", "-"), reserved=RESERVED_ORGANIZATION_SLUGS)
102104

103105
return surrogate_org_slug.slug
104106

src/sentry/models/organization.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ def save(self, *args, **kwargs):
247247
elif not self.id:
248248
slugify_target = self.slug
249249
if slugify_target is not None:
250+
# Django's slugify() doesn't replace underscores with hyphens, so we need to do it manually
251+
# to ensure the slug matches ORG_SLUG_PATTERN which doesn't allow underscores
252+
slugify_target = slugify_target.replace("_", "-")
250253
lock = locks.get("slug:organization", duration=5, name="organization_slug")
251254
with TimedRetryPolicy(10)(lock.acquire):
252255
slugify_instance(self, slugify_target, reserved=RESERVED_ORGANIZATION_SLUGS)

tests/sentry/db/models/test_utils.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,17 @@ def test_replaces_space_with_hyphen(self) -> None:
105105
assert org.slug == "f-o-o"
106106

107107
def test_removes_underscores(self) -> None:
108+
# Note: slugify_instance does NOT replace underscores - that's done by callers
109+
# who need it (like Organization). This test verifies Django's slugify behavior.
108110
org = Organization(name="_foo_")
109111
slugify_instance(org, org.name)
112+
# Django's slugify converts underscores to hyphens and strips them
110113
assert org.slug == "foo"
114+
115+
def test_strips_leading_hyphens_before_truncation(self) -> None:
116+
# Test that leading hyphens are stripped after truncation
117+
org = Organization(name="---Long-Name-That-Exceeds-Length")
118+
slugify_instance(org, org.name, max_length=30)
119+
# Should strip trailing hyphen after truncation
120+
assert org.slug == "long-name-that-exceeds-length"
121+
assert not org.slug.endswith("-")

tests/sentry/models/test_project.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@
4141

4242

4343
class ProjectTest(APITestCase, TestCase):
44+
def test_slug_preserves_underscores(self) -> None:
45+
# Projects use MIXED_SLUG_PATTERN which allows underscores
46+
org = self.create_organization()
47+
project = self.create_project(organization=org, name="my_project")
48+
assert project.slug == "my_project"
49+
4450
def test_member_set_simple(self) -> None:
4551
user = self.create_user()
4652
org = self.create_organization(owner=user)

0 commit comments

Comments
 (0)