From 58793c97a54731aef9949937f75d5264ef019e3d Mon Sep 17 00:00:00 2001 From: Jess MacQueen Date: Mon, 24 Apr 2017 17:24:10 -0700 Subject: [PATCH] delete commits when deleting repos --- .../organization_repository_details.py | 6 +-- src/sentry/tasks/deletion.py | 46 ++++++++++++++++ tests/sentry/tasks/test_deletion.py | 52 ++++++++++++++++++- 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/src/sentry/api/endpoints/organization_repository_details.py b/src/sentry/api/endpoints/organization_repository_details.py index 16525ebe816d02..6d13dd2fd70f63 100644 --- a/src/sentry/api/endpoints/organization_repository_details.py +++ b/src/sentry/api/endpoints/organization_repository_details.py @@ -12,7 +12,7 @@ from sentry.api.serializers import serialize from sentry.constants import ObjectStatus from sentry.models import Repository -from sentry.tasks.deletion import generic_delete +from sentry.tasks.deletion import delete_repository delete_logger = logging.getLogger('sentry.deletions.api') @@ -75,10 +75,8 @@ def delete(self, request, organization, repo_id): transaction_id = uuid4().hex countdown = 86400 - generic_delete.apply_async( + delete_repository.apply_async( kwargs={ - 'app_label': Repository._meta.app_label, - 'model_name': Repository._meta.model_name, 'object_id': repo.id, 'transaction_id': transaction_id, 'actor_id': request.user.id, diff --git a/src/sentry/tasks/deletion.py b/src/sentry/tasks/deletion.py index 9a77cd66eff8d9..bb09a2026c0608 100644 --- a/src/sentry/tasks/deletion.py +++ b/src/sentry/tasks/deletion.py @@ -504,3 +504,49 @@ def delete_objects(models, relation, transaction_id=None, limit=100, logger=None if has_more: return True return has_more + + +@instrumented_task(name='sentry.tasks.deletion.delete_repository', queue='cleanup', + default_retry_delay=60 * 5, max_retries=None) +@retry(exclude=(DeleteAborted,)) +def delete_repository(object_id, transaction_id=None, continuous=True, + actor_id=None, **kwargs): + from sentry.models import Commit, Repository, User + + try: + repo = Repository.objects.get(id=object_id) + except Repository.DoesNotExist: + return + + if repo.status == ObjectStatus.VISIBLE: + raise DeleteAborted + + if repo.status == ObjectStatus.PENDING_DELETION: + if actor_id: + actor = User.objects.get(id=actor_id) + else: + actor = None + repo.update(status=ObjectStatus.DELETION_IN_PROGRESS) + pending_delete.send(sender=Repository, instance=repo, actor=actor) + + has_more = delete_objects( + (Commit,), + transaction_id=transaction_id, + relation={'repository_id': repo.id}, + logger=logger, + ) + if has_more: + if continuous: + delete_repository.apply_async( + kwargs={'object_id': object_id, 'transaction_id': transaction_id}, + countdown=15, + ) + return + + repo_id = repo.id + repo.delete() + logger.info('object.delete.executed', extra={ + 'object_id': repo_id, + 'transaction_id': transaction_id, + 'model': Repository.__name__, + }) diff --git a/tests/sentry/tasks/test_deletion.py b/tests/sentry/tasks/test_deletion.py index 3518ef9e95e05c..f1c95273e9d1d9 100644 --- a/tests/sentry/tasks/test_deletion.py +++ b/tests/sentry/tasks/test_deletion.py @@ -16,7 +16,7 @@ ) from sentry.tasks.deletion import ( delete_api_application, delete_group, delete_organization, delete_project, - delete_tag_key, delete_team, generic_delete, revoke_api_tokens + delete_repository, delete_tag_key, delete_team, generic_delete, revoke_api_tokens ) from sentry.testutils import TestCase @@ -369,3 +369,53 @@ def test_deletes(self): generic_delete('sentry', 'project', object_id=project.id) assert not Project.objects.filter(id=project.id).exists() + + +class DeleteRepoTest(TestCase): + def test_does_not_delete_visible(self): + org = self.create_organization() + repo = Repository.objects.create( + status=ObjectStatus.VISIBLE, + provider='dummy', + organization_id=org.id, + name='example/example', + ) + + with self.tasks(): + with pytest.raises(DeleteAborted): + delete_repository(object_id=repo.id) + + repo = Repository.objects.get(id=repo.id) + assert repo.status == ObjectStatus.VISIBLE + + def test_deletes(self): + org = self.create_organization() + repo = Repository.objects.create( + status=ObjectStatus.PENDING_DELETION, + organization_id=org.id, + provider='dummy', + name='example/example', + ) + repo2 = Repository.objects.create( + status=ObjectStatus.PENDING_DELETION, + organization_id=org.id, + provider='dummy', + name='example/example2', + ) + commit = Commit.objects.create( + repository_id=repo.id, + organization_id=org.id, + key='1234abcd', + ) + commit2 = Commit.objects.create( + repository_id=repo2.id, + organization_id=org.id, + key='1234abcd', + ) + + with self.tasks(): + delete_repository(object_id=repo.id) + + assert not Repository.objects.filter(id=repo.id).exists() + assert not Commit.objects.filter(id=commit.id).exists() + assert Commit.objects.filter(id=commit2.id).exists()