Browse Source

fix(derived_code_mappings): Do not allow empty stack root for packaged languages (#42511)

This is a minor regression from https://github.com/getsentry/sentry/pull/42389

This was creating code mappings with an empty stack root for Python projects.

Unfortunately, all frames on Python issues are considered as in_app even if they're third party libraries. This would hide our ability to properly track how accurate the Python code mappings are.

For now, we will not allow empty stack roots for packaged languages.
Armen Zambrano G 2 years ago
parent
commit
914355da4b

+ 6 - 4
src/sentry/integrations/utils/code_mapping.py

@@ -297,10 +297,12 @@ class CodeMappingTreesHelper:
         if len(matched_files) != 1:
             return []
 
-        stacktrace_root, source_path = self._normalized_stack_and_source_roots(
-            f"{frame_filename.root}/",
-            self._get_code_mapping_source_path(matched_files[0], frame_filename),
-        )
+        stacktrace_root = f"{frame_filename.root}/"
+        source_path = self._get_code_mapping_source_path(matched_files[0], frame_filename)
+        if frame_filename.frame_type() != "packaged":
+            stacktrace_root, source_path = self._normalized_stack_and_source_roots(
+                stacktrace_root, source_path
+            )
         # It is too risky generating code mappings when there's more
         # than one file potentially matching
         return [

+ 45 - 0
tests/sentry/tasks/test_derive_code_mappings.py

@@ -367,3 +367,48 @@ class TestPythonDeriveCodeMappings(BaseDeriveCodeMappings):
 
         # We should not create the code mapping for dry runs
         assert not RepositoryProjectPathConfig.objects.filter(project_id=self.project.id).exists()
+
+    @responses.activate
+    @with_feature("organizations:derive-code-mappings")
+    def test_derive_code_mappings_stack_and_source_root_do_not_match(self):
+        self.create_integration(
+            organization=self.organization,
+            provider="github",
+            external_id=self.organization.id,
+            metadata={"domain_name": "github.com/Test-Org"},
+        )
+        repo_name = "foo/bar"
+        with patch(
+            "sentry.integrations.github.client.GitHubClientMixin.get_trees_for_org"
+        ) as mock_get_trees_for_org:
+            mock_get_trees_for_org.return_value = {
+                repo_name: RepoTree(Repo(repo_name, "master"), ["src/sentry/models/release.py"])
+            }
+            derive_code_mappings(self.project.id, self.test_data)
+            code_mapping = RepositoryProjectPathConfig.objects.all().first()
+            # sentry/models/release.py -> models/release.py -> src/sentry/models/release.py
+            assert code_mapping.stack_root == "sentry/"
+            assert code_mapping.source_root == "src/sentry/"
+
+    @responses.activate
+    @with_feature("organizations:derive-code-mappings")
+    def test_derive_code_mappings_no_normalization(self):
+        self.create_integration(
+            organization=self.organization,
+            provider="github",
+            external_id=self.organization.id,
+            metadata={"domain_name": "github.com/Test-Org"},
+        )
+        repo_name = "foo/bar"
+        with patch(
+            "sentry.integrations.github.client.GitHubClientMixin.get_trees_for_org"
+        ) as mock_get_trees_for_org:
+            mock_get_trees_for_org.return_value = {
+                repo_name: RepoTree(Repo(repo_name, "master"), ["sentry/models/release.py"])
+            }
+            derive_code_mappings(self.project.id, self.test_data)
+            code_mapping = RepositoryProjectPathConfig.objects.all().first()
+            # sentry/models/release.py -> models/release.py -> sentry/models/release.py
+            # If the normalization code was used these would be the empty stack root
+            assert code_mapping.stack_root == "sentry/"
+            assert code_mapping.source_root == "sentry/"