Skip to content

Commit

Permalink
add transfer repositories
Browse files Browse the repository at this point in the history
  • Loading branch information
jefer94 committed Aug 27, 2024
1 parent 36cf5a2 commit b11c5bb
Show file tree
Hide file tree
Showing 4 changed files with 613 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,53 @@ def github(self):
last_check = last.created_at

self.schedule_github_deletions(settings.github_username, last_check)
self.collect_transferred_orders()
self.transfer_ownership()
self.delete_github_repositories()

def check_path(self, obj: dict, *indexes: str) -> bool:
try:
value = obj
for index in indexes:
value = value[index]
return True
except KeyError:
return False

def get_username(self, owner: str, repo: str) -> Optional[str]:
repo = repo.lower()
for events in self.github_client.get_repo_events(owner, repo):
for event in events:
if self.check_path(event, "type") is False:
continue

if (
event["type"] == "watchEvent"
and self.check_path(event, "actor", "login")
and event["actor"]["login"].replace("-", "").lower() in repo
):
return event["actor"]["login"]

if (
event["type"] == "MemberEvent"
and self.check_path(event, "payload", "member", "login")
and event["payload"]["member"]["login"].replace("-", "").lower() in repo
):
return event["payload"]["member"]["login"]

if (
event["type"] == "IssuesEvent"
and self.check_path(event, "payload", "assignee", "login")
and event["payload"]["assignee"]["login"].replace("-", "").lower() in repo
):
return event["payload"]["assignee"]["login"]

if (
self.check_path(event, "actor", "login")
and event["actor"]["login"].replace("-", "").lower() in repo
):
return event["actor"]["login"]

def purge_deletion_orders(self):

page = 0
Expand All @@ -76,7 +121,7 @@ def delete_github_repositories(self):
while True:
qs = RepositoryDeletionOrder.objects.filter(
provider=RepositoryDeletionOrder.Provider.GITHUB,
status=RepositoryDeletionOrder.Status.PENDING,
status__in=[RepositoryDeletionOrder.Status.PENDING, RepositoryDeletionOrder.Status.TRANSFERRING],
created_at__lte=timezone.now() - relativedelta(months=2),
)[:100]

Expand All @@ -85,11 +130,23 @@ def delete_github_repositories(self):

for deletion_order in qs:
try:
self.github_client.delete_org_repo(
if self.github_client.repo_exists(
owner=deletion_order.repository_user, repo=deletion_order.repository_name
)
deletion_order.status = RepositoryDeletionOrder.Status.DELETED
deletion_order.save()
):
self.github_client.delete_org_repo(
owner=deletion_order.repository_user, repo=deletion_order.repository_name
)
deletion_order.status = RepositoryDeletionOrder.Status.DELETED
deletion_order.save()

elif deletion_order.status == RepositoryDeletionOrder.Status.TRANSFERRING:
deletion_order.status = RepositoryDeletionOrder.Status.TRANSFERRED
deletion_order.save()

else:
raise Exception(
f"Repository does not exist: {deletion_order.repository_user}/{deletion_order.repository_name}"
)

except Exception as e:
deletion_order.status = RepositoryDeletionOrder.Status.ERROR
Expand Down Expand Up @@ -175,3 +232,68 @@ def schedule_github_deletion(self, provider: str, user: str, repo_name: str):
RepositoryDeletionOrder.objects.get_or_create(
provider=provider, repository_user=user, repository_name=repo_name
)

def collect_transferred_orders(self):

ids = []

while True:
qs = RepositoryDeletionOrder.objects.filter(
provider=RepositoryDeletionOrder.Provider.GITHUB,
status=RepositoryDeletionOrder.Status.TRANSFERRING,
created_at__gt=timezone.now(),
).exclude(id__in=ids)[:100]

if qs.count() == 0:
break

for deletion_order in qs:
try:
ids.append(deletion_order.id)
if (
self.github_client.repo_exists(
owner=deletion_order.repository_user, repo=deletion_order.repository_name
)
is False
):
deletion_order.status = RepositoryDeletionOrder.Status.TRANSFERRED
deletion_order.save()

except Exception as e:
deletion_order.status = RepositoryDeletionOrder.Status.ERROR
deletion_order.status_text = str(e)
deletion_order.save()

def transfer_ownership(self):
ids = []

while True:
qs = RepositoryDeletionOrder.objects.filter(
provider=RepositoryDeletionOrder.Provider.GITHUB,
status=RepositoryDeletionOrder.Status.PENDING,
created_at__gt=timezone.now(),
).exclude(id__in=ids)[:100]

if qs.count() == 0:
break

for deletion_order in qs:
try:
if self.github_client.repo_exists(
owner=deletion_order.repository_user, repo=deletion_order.repository_name
):
new_owner = self.get_username(deletion_order.repository_user, deletion_order.repository_name)
if new_owner:
continue

res = self.github_client.transfer_repo(repo=deletion_order.repository_name, new_owner=new_owner)
if res["status"] == 202:
deletion_order.status = RepositoryDeletionOrder.Status.TRANSFERRING
deletion_order.save()

except Exception as e:
deletion_order.status = RepositoryDeletionOrder.Status.ERROR
deletion_order.status_text = str(e)
deletion_order.save()

ids.append(deletion_order.id)
5 changes: 2 additions & 3 deletions breathecode/assignments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ class Status(models.TextChoices):
PENDING = "PENDING", "Pending"
ERROR = "ERROR", "Error"
DELETED = "DELETED", "Deleted"
TRANSFERRED = "TRANSFERRED", "Transferred"
TRANSFERRING = "TRANSFERRING", "Transferring"
CANCELLED = "CANCELLED", "Cancelled"

provider = models.CharField(max_length=15, choices=Provider, default=Provider.GITHUB)
Expand All @@ -258,9 +260,6 @@ def save(self, *args, **kwargs):
self.full_clean()
super().save(*args, **kwargs)

# def __str__(self):
# return f'Learnpack event {self.event} {self.status} => Student: {self.student.id}'


class RepositoryWhiteList(models.Model):
Provider = Provider
Expand Down
Loading

0 comments on commit b11c5bb

Please sign in to comment.