Browse Source

chore(similarity): Turn on ML grouping for new EA projects in us region (#75207)

On new project creation for EA orgs in the us region, create the
similarity backfill completed option
Jodi Jang 7 months ago
parent
commit
5c2dbe8538

+ 14 - 1
src/sentry/api/endpoints/team_projects.py

@@ -1,10 +1,12 @@
+import time
+
 from django.db import IntegrityError, router, transaction
 from drf_spectacular.utils import OpenApiResponse, extend_schema
 from rest_framework import serializers, status
 from rest_framework.request import Request
 from rest_framework.response import Response
 
-from sentry import audit_log
+from sentry import audit_log, options
 from sentry.api.api_owners import ApiOwner
 from sentry.api.api_publish_status import ApiPublishStatus
 from sentry.api.base import EnvironmentMixin, region_silo_endpoint
@@ -21,6 +23,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.seer.similarity.utils import SEER_ELIGIBLE_PLATFORMS
 from sentry.signals import project_created
 from sentry.utils.snowflake import MaxSnowflakeRetryError
 
@@ -214,4 +217,14 @@ class TeamProjectsEndpoint(TeamEndpoint, EnvironmentMixin):
                 sender=self,
             )
 
+            # Create project option to turn on ML similarity feature for new EA projects
+            is_seer_eligible_platform = project.platform in SEER_ELIGIBLE_PLATFORMS
+            if (
+                hasattr(project.organization, "flags")
+                and project.organization.flags.early_adopter
+                and is_seer_eligible_platform
+                and options.get("similarity.new_project_seer_grouping.enabled")
+            ):
+                project.update_option("sentry:similarity_backfill_completed", int(time.time()))
+
         return Response(serialize(project, request.user), status=201)

+ 5 - 0
src/sentry/options/defaults.py

@@ -2648,6 +2648,11 @@ register(
     default=1,
     flags=FLAG_AUTOMATOR_MODIFIABLE,
 )
+register(
+    "similarity.new_project_seer_grouping.enabled",
+    default=False,
+    flags=FLAG_AUTOMATOR_MODIFIABLE,
+)
 register(
     "similarity.backfill_use_reranking",
     default=False,

+ 70 - 1
tests/sentry/api/endpoints/test_team_projects.py

@@ -1,14 +1,17 @@
+from unittest import TestCase
 from unittest.mock import Mock
 
 from sentry.api.endpoints.organization_projects_experiment import DISABLED_FEATURE_ERROR_STRING
 from sentry.constants import RESERVED_PROJECT_SLUGS
 from sentry.ingest import inbound_filters
+from sentry.models.options.project_option import ProjectOption
 from sentry.models.project import Project
 from sentry.models.rule import Rule
 from sentry.notifications.types import FallthroughChoiceType
 from sentry.signals import alert_rule_created
 from sentry.slug.errors import DEFAULT_SLUG_ERROR_MESSAGE
 from sentry.testutils.cases import APITestCase
+from sentry.testutils.helpers.options import override_options
 
 
 class TeamProjectsListTest(APITestCase):
@@ -40,7 +43,7 @@ class TeamProjectsListTest(APITestCase):
         assert str(proj3.id) not in response.data
 
 
-class TeamProjectsCreateTest(APITestCase):
+class TeamProjectsCreateTest(APITestCase, TestCase):
     endpoint = "sentry-api-0-team-project-index"
     method = "post"
 
@@ -65,6 +68,14 @@ class TeamProjectsCreateTest(APITestCase):
         assert project.platform == "python"
         assert project.teams.first() == self.team
 
+        # Assert project option is not set for non-EA organizations
+        assert (
+            ProjectOption.objects.get_value(
+                project=project, key="sentry:similarity_backfill_completed"
+            )
+            is None
+        )
+
     def test_invalid_numeric_slug(self):
         response = self.get_error_response(
             self.organization.slug,
@@ -228,3 +239,61 @@ class TeamProjectsCreateTest(APITestCase):
         }
         assert javascript_filter_states["web-crawlers"]
         assert javascript_filter_states["filtered-transaction"]
+
+    @override_options({"similarity.new_project_seer_grouping.enabled": True})
+    def test_similarity_project_option_valid(self):
+        """
+        Test that project option for similarity grouping is created for EA organizations
+        where the project platform is Seer-eligible.
+        """
+        self.organization.flags.early_adopter = True
+        self.organization.save()
+        response = self.get_success_response(
+            self.organization.slug,
+            self.team.slug,
+            **self.data,
+            status_code=201,
+        )
+
+        project = Project.objects.get(id=response.data["id"])
+        assert project.name == "foo"
+        assert project.slug == "bar"
+        assert project.platform == "python"
+        assert project.teams.first() == self.team
+
+        assert (
+            ProjectOption.objects.get_value(
+                project=project, key="sentry:similarity_backfill_completed"
+            )
+            is not None
+        )
+
+    def test_similarity_project_option_invalid(self):
+        """
+        Test that project option for similarity grouping is not created for EA organizations
+        where the project platform is not seer eligible.
+        """
+
+        self.organization.flags.early_adopter = True
+        self.organization.save()
+        response = self.get_success_response(
+            self.organization.slug,
+            self.team.slug,
+            name="foo",
+            slug="bar",
+            platform="php",
+            status_code=201,
+        )
+
+        project = Project.objects.get(id=response.data["id"])
+        assert project.name == "foo"
+        assert project.slug == "bar"
+        assert project.platform == "php"
+        assert project.teams.first() == self.team
+
+        assert (
+            ProjectOption.objects.get_value(
+                project=project, key="sentry:similarity_backfill_completed"
+            )
+            is None
+        )