Skip to content
2 changes: 1 addition & 1 deletion migrations_lockfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ hybridcloud: 0016_add_control_cacheversion
nodestore: 0002_nodestore_no_dictfield
remote_subscriptions: 0003_drop_remote_subscription
replays: 0004_index_together
sentry: 0769_add_seer_fields_to_grouphash_metadata
sentry: 0770_increase_project_slug_max_length
social_auth: 0002_default_auto_field
uptime: 0014_add_uptime_enviromnet
workflow_engine: 0007_loosen_workflow_action_relationship
3 changes: 2 additions & 1 deletion src/sentry/api/endpoints/organization_teams.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from sentry.apidocs.examples.team_examples import TeamExamples
from sentry.apidocs.parameters import CursorQueryParam, GlobalParams, TeamParams
from sentry.apidocs.utils import inline_sentry_response_serializer
from sentry.db.models.fields.slug import DEFAULT_SLUG_MAX_LENGTH
from sentry.integrations.models.external_actor import ExternalActor
from sentry.models.organizationmember import OrganizationMember
from sentry.models.organizationmemberteam import OrganizationMemberTeam
Expand All @@ -44,7 +45,7 @@ class TeamPostSerializer(serializers.Serializer):
slug = SentrySerializerSlugField(
help_text="""Uniquely identifies a team and is used for the interface. If not
provided, it is automatically generated from the name.""",
max_length=50,
max_length=DEFAULT_SLUG_MAX_LENGTH,
required=False,
allow_null=True,
)
Expand Down
4 changes: 2 additions & 2 deletions src/sentry/api/endpoints/project_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
)
from sentry.lang.native.utils import STORE_CRASH_REPORTS_MAX, convert_crashreport_count
from sentry.models.group import Group, GroupStatus
from sentry.models.project import Project
from sentry.models.project import PROJECT_SLUG_MAX_LENGTH, Project
from sentry.models.projectbookmark import ProjectBookmark
from sentry.models.projectredirect import ProjectRedirect
from sentry.notifications.utils import has_alert_integration
Expand Down Expand Up @@ -135,7 +135,7 @@ class ProjectAdminSerializer(ProjectMemberSerializer):
)
slug = SentrySerializerSlugField(
help_text="Uniquely identifies a project and is used for the interface.",
max_length=50,
max_length=PROJECT_SLUG_MAX_LENGTH,
required=False,
)
platform = serializers.CharField(
Expand Down
3 changes: 2 additions & 1 deletion src/sentry/api/endpoints/team_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
)
from sentry.apidocs.examples.team_examples import TeamExamples
from sentry.apidocs.parameters import GlobalParams, TeamParams
from sentry.db.models.fields.slug import DEFAULT_SLUG_MAX_LENGTH
from sentry.deletions.models.scheduleddeletion import RegionScheduledDeletion
from sentry.models.team import Team, TeamStatus


@extend_schema_serializer(exclude_fields=["name"])
class TeamDetailsSerializer(CamelSnakeModelSerializer):
slug = SentrySerializerSlugField(
max_length=50,
max_length=DEFAULT_SLUG_MAX_LENGTH,
help_text="Uniquely identifies a team. This is must be available.",
)

Expand Down
4 changes: 2 additions & 2 deletions src/sentry/api/endpoints/team_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from sentry.apidocs.parameters import CursorQueryParam, GlobalParams
from sentry.apidocs.utils import inline_sentry_response_serializer
from sentry.constants import RESERVED_PROJECT_SLUGS, ObjectStatus
from sentry.models.project import Project
from sentry.models.project import PROJECT_SLUG_MAX_LENGTH, Project
from sentry.models.team import Team
from sentry.seer.similarity.utils import project_is_seer_eligible
from sentry.signals import project_created
Expand All @@ -38,7 +38,7 @@ class ProjectPostSerializer(serializers.Serializer):
slug = SentrySerializerSlugField(
help_text="""Uniquely identifies a project and is used for the interface.
If not provided, it is automatically generated from the name.""",
max_length=50,
max_length=PROJECT_SLUG_MAX_LENGTH,
required=False,
allow_null=True,
)
Expand Down
6 changes: 5 additions & 1 deletion src/sentry/api/fields/sentry_slug.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers

from sentry.db.models.fields.slug import DEFAULT_SLUG_MAX_LENGTH
from sentry.slug.errors import DEFAULT_SLUG_ERROR_MESSAGE, ORG_SLUG_ERROR_MESSAGE
from sentry.slug.patterns import MIXED_SLUG_PATTERN, ORG_SLUG_PATTERN

Expand All @@ -24,6 +25,7 @@ def __init__(
self,
error_messages=None,
org_slug: bool = False,
max_length: int = DEFAULT_SLUG_MAX_LENGTH,
*args,
**kwargs,
):
Expand All @@ -37,4 +39,6 @@ def __init__(
pattern = ORG_SLUG_PATTERN
error_messages["invalid"] = ORG_SLUG_ERROR_MESSAGE

super().__init__(pattern, error_messages=error_messages, *args, **kwargs)
super().__init__(
pattern, error_messages=error_messages, max_length=max_length, *args, **kwargs
)
3 changes: 2 additions & 1 deletion src/sentry/api/serializers/models/organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
UPTIME_AUTODETECTION,
ObjectStatus,
)
from sentry.db.models.fields.slug import DEFAULT_SLUG_MAX_LENGTH
from sentry.dynamic_sampling.tasks.common import get_organization_volume
from sentry.dynamic_sampling.tasks.helpers.sliding_window import get_sliding_window_org_sample_rate
from sentry.killswitches import killswitch_matches_context
Expand Down Expand Up @@ -101,7 +102,7 @@ class BaseOrganizationSerializer(serializers.Serializer):
# 3. cannot end with a dash
slug = SentrySerializerSlugField(
org_slug=True,
max_length=50,
max_length=DEFAULT_SLUG_MAX_LENGTH,
)

def validate_slug(self, value: str) -> str:
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/db/models/fields/slug.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

from sentry.slug.validators import no_numeric_validator, org_slug_validator

DEFAULT_SLUG_MAX_LENGTH = 50


class SentrySlugField(SlugField):
default_validators = [*SlugField.default_validators, no_numeric_validator]
Expand Down
34 changes: 34 additions & 0 deletions src/sentry/migrations/0770_increase_project_slug_max_length.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Generated by Django 5.1.1 on 2024-09-30 19:46

from django.db import migrations

import sentry.db.models.fields.slug
from sentry.new_migrations.migrations import CheckedMigration


class Migration(CheckedMigration):
# This flag is used to mark that a migration shouldn't be automatically run in production.
# This should only be used for operations where it's safe to run the migration after your
# code has deployed. So this should not be used for most operations that alter the schema
# of a table.
# Here are some things that make sense to mark as post deployment:
# - Large data migrations. Typically we want these to be run manually so that they can be
# monitored and not block the deploy for a long period of time while they run.
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
# run this outside deployments so that we don't block them. Note that while adding an index
# is a schema change, it's completely safe to run the operation after the code has deployed.
# Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment

is_post_deployment = True

dependencies = [
("sentry", "0769_add_seer_fields_to_grouphash_metadata"),
]

operations = [
migrations.AlterField(
model_name="project",
name="slug",
field=sentry.db.models.fields.slug.SentrySlugField(max_length=100, null=True),
),
]
3 changes: 2 additions & 1 deletion src/sentry/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
from sentry.users.models.user import User

SENTRY_USE_SNOWFLAKE = getattr(settings, "SENTRY_USE_SNOWFLAKE", False)
PROJECT_SLUG_MAX_LENGTH = 100

# NOTE:
# - When you modify this list, ensure that the platform IDs listed in "sentry/static/app/data/platforms.tsx" match.
Expand Down Expand Up @@ -232,7 +233,7 @@ class Project(Model, PendingDeletionMixin):

__relocation_scope__ = RelocationScope.Organization

slug = SentrySlugField(null=True)
slug = SentrySlugField(null=True, max_length=PROJECT_SLUG_MAX_LENGTH)
# DEPRECATED do not use, prefer slug
name = models.CharField(max_length=200)
forced_color = models.CharField(max_length=6, null=True, blank=True)
Expand Down
3 changes: 0 additions & 3 deletions src/sentry/monitors/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
# being marked as missed
DEFAULT_CHECKIN_MARGIN = 1

# Enforced maximum length of the monitor slug
MAX_SLUG_LENGTH = 50


class PermitCheckInStatus(Enum):
ACCEPT = 0
Expand Down
5 changes: 2 additions & 3 deletions src/sentry/monitors/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@
sane_repr,
)
from sentry.db.models.fields.hybrid_cloud_foreign_key import HybridCloudForeignKey
from sentry.db.models.fields.slug import SentrySlugField
from sentry.db.models.fields.slug import DEFAULT_SLUG_MAX_LENGTH, SentrySlugField
from sentry.db.models.manager.base import BaseManager
from sentry.db.models.utils import slugify_instance
from sentry.locks import locks
from sentry.models.environment import Environment
from sentry.models.rule import Rule, RuleSource
from sentry.monitors.constants import MAX_SLUG_LENGTH
from sentry.monitors.types import CrontabSchedule, IntervalSchedule
from sentry.types.actor import Actor
from sentry.utils.retries import TimedRetryPolicy
Expand Down Expand Up @@ -296,7 +295,7 @@ def save(self, *args, **kwargs):
self,
self.name,
organization_id=self.organization_id,
max_length=MAX_SLUG_LENGTH,
max_length=DEFAULT_SLUG_MAX_LENGTH,
)
return super().save(*args, **kwargs)

Expand Down
4 changes: 2 additions & 2 deletions src/sentry/monitors/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from django.utils.text import slugify
from sentry_kafka_schemas.schema_types.ingest_monitors_v1 import CheckIn

from sentry.monitors.constants import MAX_SLUG_LENGTH
from sentry.db.models.fields.slug import DEFAULT_SLUG_MAX_LENGTH


class CheckinTrace(TypedDict):
Expand Down Expand Up @@ -70,7 +70,7 @@ class CheckinItem:

@cached_property
def valid_monitor_slug(self):
return slugify(self.payload["monitor_slug"])[:MAX_SLUG_LENGTH].strip("-")
return slugify(self.payload["monitor_slug"])[:DEFAULT_SLUG_MAX_LENGTH].strip("-")

@property
def processing_key(self):
Expand Down
5 changes: 3 additions & 2 deletions src/sentry/monitors/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
from sentry.api.serializers.rest_framework.project import ProjectField
from sentry.constants import ObjectStatus
from sentry.db.models import BoundedPositiveIntegerField
from sentry.monitors.constants import MAX_SLUG_LENGTH, MAX_THRESHOLD, MAX_TIMEOUT
from sentry.db.models.fields.slug import DEFAULT_SLUG_MAX_LENGTH
from sentry.monitors.constants import MAX_THRESHOLD, MAX_TIMEOUT
from sentry.monitors.models import CheckInStatus, Monitor, MonitorType, ScheduleType
from sentry.monitors.schedule import get_next_schedule, get_prev_schedule
from sentry.monitors.types import CrontabSchedule
Expand Down Expand Up @@ -246,7 +247,7 @@ class MonitorValidator(CamelSnakeSerializer):
help_text="Name of the monitor. Used for notifications.",
)
slug = SentrySerializerSlugField(
max_length=MAX_SLUG_LENGTH,
max_length=DEFAULT_SLUG_MAX_LENGTH,
required=False,
help_text="Uniquely identifies your monitor within your organization. Changing this slug will require updates to any instrumented check-in calls.",
)
Expand Down
Loading