Skip to content

Instantly share code, notes, and snippets.

@humitos
Last active June 29, 2022 15:20
Show Gist options
  • Save humitos/414c8ff7a4c16776d23e108aef184ce8 to your computer and use it in GitHub Desktop.
Save humitos/414c8ff7a4c16776d23e108aef184ce8 to your computer and use it in GitHub Desktop.
Connect `Project` to `RemoteRepository`
# Script to connect `Project` to `RemoteRepository` without the user intervention.
#
# We will only connect them if:
# - the `Project` is not connected to a `RemoteRepository` already
# - we are able to find the final URL based on `Project.repo`
# - a `RemoteRepository` object exists in our database with `html_url` or `ssh_url` matching the final URL
# - at least one project's admin (on Read the Docs) is admin of the VCS repository
#
import requests
from django.conf import settings
from django.db.models import Sum, Q
from readthedocs.projects.models import Project
from readthedocs.core.permissions import AdminPermission
from readthedocs.oauth.models import RemoteRepository
NUMBER_PROJECTS = 100
projects = Project.objects.annotate(spam_score=Sum("spam_rules__value")).filter(
spam_score__lt=settings.RTD_SPAM_THRESHOLD_DENY_ON_ROBOTS,
remote_repository__isnull=True,
)[:NUMBER_PROJECTS]
print(f'Projects to reconnect: {projects.count()}')
def get_final_url(project):
final_url = None
url = project.repo
if "@" in url:
# NOTE: Do we need to convert this? After checking with
# community/commercial data it seems it's not required and it will
# match with `RemoteRepository.ssh_url`
#
# url = convert_to_https(url)
final_url = url
if url.startswith("http"):
try:
response = requests.head(project.repo, allow_redirects=True)
final_url = response.url
except requests.exceptions.TooManyRedirects:
print('Too many redirects')
return final_url
def get_remote_repository(project, url):
return RemoteRepository.objects.filter(
Q(html_url=url) | Q(ssh_url=url),
remote_repository_relations__user__in=AdminPermission.admins(project),
remote_repository_relations__admin=True,
).first()
def connect_remote_repository(project):
url = get_final_url(project)
remote_repository = get_remote_repository(project, url)
if not url:
print('URL not found for this project.')
return
if not remote_repository:
print(f'RemoteRepository not found for this project. url={url}')
return
if project.remote_repository:
print(f'WARNING: project already connected to RemoteRepository: {project.remote_repository.pk}')
print(f' slug: {project.slug}')
print(f' remoterepository:')
print(f' {remote_repository.full_name}')
print(f' {remote_repository.pk}')
print(f' url: {url}')
# TODO: save the connection when we are ready
for project in projects:
print(f'Connecting: {project.slug}')
connect_remote_repository(project)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment