Browse Source

feat(github-growth): activate hidden repo in create_repository (#53022)

Cathy Teng 1 year ago
parent
commit
cff0a8e515

+ 22 - 3
src/sentry/plugins/providers/integration_repository.py

@@ -18,6 +18,7 @@ from sentry.models import Integration, Repository
 from sentry.services.hybrid_cloud.integration import integration_service
 from sentry.shared_integrations.exceptions import IntegrationError
 from sentry.signals import repo_linked
+from sentry.utils import metrics
 
 
 class RepoExistsError(APIException):
@@ -82,18 +83,36 @@ class IntegrationRepositoryProvider:
     ):
         result = self.build_repository_config(organization=organization, data=repo_config)
 
+        integration_id = result.get("integration_id")
+        external_id = result.get("external_id")
+
         repo_update_params = {
-            "external_id": result.get("external_id"),
+            "external_id": external_id,
             "url": result.get("url"),
             "config": result.get("config") or {},
             "provider": self.id,
-            "integration_id": result.get("integration_id"),
+            "integration_id": integration_id,
         }
 
-        # first check if there is a repository without an integration that matches
+        # first check if there is an existing hidden repository with an integration that matches
+        existing_repo = Repository.objects.filter(
+            organization_id=organization.id,
+            name=result["name"],
+            integration_id=integration_id,
+            external_id=external_id,
+            status=ObjectStatus.HIDDEN,
+        ).first()
+        if existing_repo:
+            existing_repo.status = ObjectStatus.ACTIVE
+            existing_repo.save()
+            metrics.incr("sentry.integration_repo_provider.repo_relink")
+            return result, existing_repo
+
+        # then check if there is a repository without an integration that matches
         repo = Repository.objects.filter(
             organization_id=organization.id, name=result["name"], integration_id=None
         ).first()
+
         if repo:
             if self.logger:
                 self.logger.info(

+ 26 - 5
tests/sentry/plugins/test_integration_repository.py

@@ -5,6 +5,7 @@ import pytest
 import responses
 from django.db import IntegrityError
 
+from sentry.constants import ObjectStatus
 from sentry.integrations.github.repository import GitHubRepositoryProvider
 from sentry.models import Repository
 from sentry.plugins.providers.integration_repository import RepoExistsError
@@ -14,6 +15,7 @@ from sentry.testutils.silo import region_silo_test
 
 
 @region_silo_test(stable=True)
+@patch("sentry.integrations.github.client.get_jwt", return_value=b"jwt_token_1")
 class IntegrationRepositoryTestCase(TestCase):
     @responses.activate
     def setUp(self):
@@ -43,7 +45,7 @@ class IntegrationRepositoryTestCase(TestCase):
     def provider(self):
         return GitHubRepositoryProvider("integrations:github")
 
-    def _create_repo(self):
+    def _create_repo(self, external_id=None):
         return Repository.objects.create(
             name=self.repo_name,
             provider="integrations:github",
@@ -51,9 +53,9 @@ class IntegrationRepositoryTestCase(TestCase):
             integration_id=self.integration.id,
             url="https://github.com/" + self.repo_name,
             config={"name": self.repo_name},
+            external_id=external_id if external_id else "123456",
         )
 
-    @patch("sentry.integrations.github.client.get_jwt", return_value=b"jwt_token_1")
     def test_create_repository(self, get_jwt):
         self.provider.create_repository(self.config, self.organization)
 
@@ -63,7 +65,6 @@ class IntegrationRepositoryTestCase(TestCase):
         assert repos[0].name == self.repo_name
         assert repos[0].provider == "integrations:github"
 
-    @patch("sentry.integrations.github.client.get_jwt", return_value=b"jwt_token_1")
     def test_create_repository__repo_exists(self, get_jwt):
         self._create_repo()
 
@@ -72,8 +73,7 @@ class IntegrationRepositoryTestCase(TestCase):
 
     @patch("sentry.models.Repository.objects.create")
     @patch("sentry.plugins.providers.IntegrationRepositoryProvider.on_delete_repository")
-    @patch("sentry.integrations.github.client.get_jwt", return_value=b"jwt_token_1")
-    def test_create_repository__delete_webhook(self, get_jwt, mock_on_delete, mock_repo):
+    def test_create_repository__delete_webhook(self, mock_on_delete, mock_repo, get_jwt):
         self._create_repo()
 
         mock_repo.side_effect = IntegrityError
@@ -81,3 +81,24 @@ class IntegrationRepositoryTestCase(TestCase):
 
         with pytest.raises(RepoExistsError):
             self.provider.create_repository(self.config, self.organization)
+
+    @patch("sentry.plugins.providers.integration_repository.metrics")
+    def test_create_repository__activates_existing_hidden_repo(self, mock_metrics, get_jwt):
+        repo = self._create_repo(external_id=self.config["external_id"])
+        repo.status = ObjectStatus.HIDDEN
+        repo.save()
+
+        self.provider.create_repository(self.config, self.organization)
+        repo.refresh_from_db()
+        assert repo.status == ObjectStatus.ACTIVE
+        mock_metrics.incr.assert_called_with("sentry.integration_repo_provider.repo_relink")
+
+    def test_create_repository__only_activates_hidden_repo(self, get_jwt):
+        repo = self._create_repo(external_id=self.config["external_id"])
+        repo.status = ObjectStatus.PENDING_DELETION
+        repo.save()
+
+        with pytest.raises(RepoExistsError):
+            self.provider.create_repository(self.config, self.organization)
+        repo.refresh_from_db()
+        assert repo.status == ObjectStatus.PENDING_DELETION