Skip to content

Commit 1898d28

Browse files
ArthurKnauspriscilawebdev
authored andcommitted
ref(autopilot): Limit missing integration detector to JS and python (#107398)
For other platforms, we cannot rely on the docs yet to give us the information we need. Fixed docs URL for python.
1 parent 467afc7 commit 1898d28

File tree

2 files changed

+98
-30
lines changed

2 files changed

+98
-30
lines changed

src/sentry/autopilot/tasks.py

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from itertools import chain, groupby
66
from typing import Any
77

8+
from django.db.models import Q
89
from django.utils import timezone
910
from packaging import version
1011
from pydantic import BaseModel
@@ -30,6 +31,12 @@
3031
logger = logging.getLogger(__name__)
3132

3233

34+
class SupportedPlatformPrefix(StrEnum):
35+
JAVASCRIPT = "javascript"
36+
NODE = "node"
37+
PYTHON = "python"
38+
39+
3340
class AutopilotDetectorName(StrEnum):
3441
SDK_UPDATE = "sdk-update"
3542
MISSING_SDK_INTEGRATION = "missing-sdk-integration"
@@ -266,32 +273,30 @@ def run_missing_sdk_integration_detector() -> None:
266273

267274

268275
def run_missing_sdk_integration_detector_for_organization(organization: Organization) -> None:
269-
projects = Project.objects.filter(organization=organization).all()
270-
271-
if len(projects) == 0:
272-
return
273-
274-
for project in projects:
275-
# Get the repository mapped to this project via RepositoryProjectPathConfig
276-
repo_config = (
277-
RepositoryProjectPathConfig.objects.filter(
278-
project=project,
279-
repository__status=ObjectStatus.ACTIVE,
280-
)
281-
.select_related("repository")
282-
.first()
276+
platform_filter = Q()
277+
for prefix in SupportedPlatformPrefix:
278+
platform_filter |= Q(project__platform__startswith=prefix)
279+
280+
repo_configs = (
281+
RepositoryProjectPathConfig.objects.filter(
282+
platform_filter,
283+
project__organization=organization,
284+
repository__status=ObjectStatus.ACTIVE,
283285
)
286+
.select_related("repository")
287+
.values("project_id", "repository__name", "source_root")
288+
)
284289

285-
if repo_config:
286-
run_missing_sdk_integration_detector_for_project_task.apply_async(
287-
args=(
288-
organization.id,
289-
project.id,
290-
repo_config.repository.name,
291-
repo_config.source_root,
292-
),
293-
headers={"sentry-propagate-traces": False},
294-
)
290+
for config in repo_configs:
291+
run_missing_sdk_integration_detector_for_project_task.apply_async(
292+
args=(
293+
organization.id,
294+
config["project_id"],
295+
config["repository__name"],
296+
config["source_root"],
297+
),
298+
headers={"sentry-propagate-traces": False},
299+
)
295300

296301

297302
@instrumented_task(
@@ -344,11 +349,12 @@ def run_missing_sdk_integration_detector_for_project_task(
344349
# Get docs URL from platform data
345350
platform_data = INTEGRATION_ID_TO_PLATFORM_DATA.get(project.platform or "", {})
346351
docs_url = platform_data.get("link", None)
347-
integration_docs_url = (
348-
f"{docs_url}configuration/integrations/"
349-
if docs_url
350-
else "https://docs.sentry.io/platforms/"
351-
)
352+
if project.platform and project.platform.startswith(SupportedPlatformPrefix.PYTHON):
353+
integration_docs_url = "https://docs.sentry.io/platforms/python/integrations/"
354+
elif docs_url:
355+
integration_docs_url = f"{docs_url}configuration/integrations/"
356+
else:
357+
integration_docs_url = "https://docs.sentry.io/platforms/"
352358

353359
prompt = f"""# Objective
354360
Find missing Sentry SDK integrations for the project `{project.slug}` in repository `{repo_name}`.
@@ -420,7 +426,7 @@ def run_missing_sdk_integration_detector_for_project_task(
420426
)
421427
with metrics.timer(
422428
"autopilot.missing_sdk_integration_detector.run_duration",
423-
tags={"organization_id": organization.id, "project_slug": project.slug},
429+
tags={"project_slug": project.slug},
424430
sample_rate=1.0,
425431
):
426432
state = client.get_run(run_id, blocking=True, poll_timeout=240.0, poll_interval=5.0)

tests/sentry/autopilot/test_tasks.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ def _create_code_mapping(self, project, repo_name: str):
294294
def test_skips_project_without_repository_mapping(
295295
self, mock_apply_async: mock.MagicMock
296296
) -> None:
297+
self.project.platform = "python"
298+
self.project.save()
297299
run_missing_sdk_integration_detector_for_organization(self.organization)
298300
# No task should be spawned for projects without code mappings
299301
assert not mock_apply_async.called
@@ -303,6 +305,8 @@ def test_skips_project_without_repository_mapping(
303305
"sentry.autopilot.tasks.run_missing_sdk_integration_detector_for_project_task.apply_async"
304306
)
305307
def test_skips_inactive_repositories(self, mock_apply_async: mock.MagicMock) -> None:
308+
self.project.platform = "python"
309+
self.project.save()
306310
# Create a code mapping with an inactive repository
307311
code_mapping = self._create_code_mapping(self.project, "inactive-repo")
308312
code_mapping.repository.status = ObjectStatus.PENDING_DELETION
@@ -318,6 +322,8 @@ def test_skips_inactive_repositories(self, mock_apply_async: mock.MagicMock) ->
318322
"sentry.autopilot.tasks.run_missing_sdk_integration_detector_for_project_task.apply_async"
319323
)
320324
def test_spawns_task_for_project_with_mapping(self, mock_apply_async: mock.MagicMock) -> None:
325+
self.project.platform = "python"
326+
self.project.save()
321327
self._create_code_mapping(self.project, "test-repo")
322328

323329
run_missing_sdk_integration_detector_for_organization(self.organization)
@@ -328,6 +334,62 @@ def test_spawns_task_for_project_with_mapping(self, mock_apply_async: mock.Magic
328334
headers={"sentry-propagate-traces": False},
329335
)
330336

337+
@pytest.mark.django_db
338+
@mock.patch(
339+
"sentry.autopilot.tasks.run_missing_sdk_integration_detector_for_project_task.apply_async"
340+
)
341+
def test_only_processes_supported_platforms(self, mock_apply_async: mock.MagicMock) -> None:
342+
# Create projects with supported platforms
343+
python_project = self.create_project(organization=self.organization, platform="python")
344+
node_project = self.create_project(organization=self.organization, platform="node")
345+
js_project = self.create_project(organization=self.organization, platform="javascript")
346+
js_react_project = self.create_project(
347+
organization=self.organization, platform="javascript-react"
348+
)
349+
python_django_project = self.create_project(
350+
organization=self.organization, platform="python-django"
351+
)
352+
node_express_project = self.create_project(
353+
organization=self.organization, platform="node-express"
354+
)
355+
356+
# Create projects with unsupported platforms
357+
go_project = self.create_project(organization=self.organization, platform="go")
358+
ruby_project = self.create_project(organization=self.organization, platform="ruby")
359+
java_project = self.create_project(organization=self.organization, platform="java")
360+
361+
# Create code mappings for all projects
362+
self._create_code_mapping(python_project, "python-repo")
363+
self._create_code_mapping(node_project, "node-repo")
364+
self._create_code_mapping(js_project, "js-repo")
365+
self._create_code_mapping(js_react_project, "js-react-repo")
366+
self._create_code_mapping(python_django_project, "python-django-repo")
367+
self._create_code_mapping(node_express_project, "node-express-repo")
368+
self._create_code_mapping(go_project, "go-repo")
369+
self._create_code_mapping(ruby_project, "ruby-repo")
370+
self._create_code_mapping(java_project, "java-repo")
371+
372+
run_missing_sdk_integration_detector_for_organization(self.organization)
373+
374+
# Only supported platforms should have tasks spawned
375+
assert mock_apply_async.call_count == 6
376+
377+
# Collect all project IDs that had tasks spawned
378+
spawned_project_ids = {call[1]["args"][1] for call in mock_apply_async.call_args_list}
379+
380+
# Supported platforms should be included
381+
assert python_project.id in spawned_project_ids
382+
assert node_project.id in spawned_project_ids
383+
assert js_project.id in spawned_project_ids
384+
assert js_react_project.id in spawned_project_ids
385+
assert python_django_project.id in spawned_project_ids
386+
assert node_express_project.id in spawned_project_ids
387+
388+
# Unsupported platforms should NOT be included
389+
assert go_project.id not in spawned_project_ids
390+
assert ruby_project.id not in spawned_project_ids
391+
assert java_project.id not in spawned_project_ids
392+
331393

332394
class TestRunMissingSdkIntegrationDetectorForProject(TestCase):
333395
@pytest.mark.django_db

0 commit comments

Comments
 (0)