Skip to content

Update OAuth App to Use The RemoteRepositoryRelation Model #7675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
307a1cb
Add Initial Modeling with Through Model and Data Migration for Remote…
saadmk11 Oct 5, 2020
7bd1a5f
Improve data migration performance
saadmk11 Oct 7, 2020
9476a36
Logging, performance optimization for data migration
saadmk11 Oct 10, 2020
1bd03c7
Use TimeStampedModel model and follow django docs for migrating throu…
saadmk11 Oct 10, 2020
c3592eb
Updated data migrations to only migrate RemoteRepositories of recentl…
saadmk11 Nov 14, 2020
c6699fb
Do not remove fields from RemoteRepository Model
saadmk11 Nov 14, 2020
bf5c6b1
Do not Migrate Active Field
saadmk11 Nov 16, 2020
d90ecad
Rename RemoteRelation model to RemoteRepositoryRelation
saadmk11 Nov 16, 2020
2c74027
Merge pull request #7536 from saadmk11/remote-repo-normalization
humitos Nov 16, 2020
9f30059
Update oauth services to use the RemoteRepositoryRelation model
saadmk11 Nov 18, 2020
42a516d
Use remote relations on update_webhook function
saadmk11 Nov 19, 2020
48114e6
Lint fix
saadmk11 Nov 19, 2020
421bcae
Fix tests
saadmk11 Nov 19, 2020
afc7af0
lint fix
saadmk11 Nov 19, 2020
28c6a18
Add TODO for removing json field from RemoteRepository serializer
saadmk11 Nov 20, 2020
37d89af
Optimize remote_relations query
saadmk11 Nov 21, 2020
8d126db
Filter remote_relations according to loggedin user on update_webhook
saadmk11 Nov 24, 2020
dff138e
Only delete RemoteRepositoryRelation objects on remote repository sync
saadmk11 Nov 24, 2020
5d7c56f
Change RemoteRepositoryRelation related_name to remote_repository_rel…
saadmk11 Nov 24, 2020
c194ac7
Delete remote repository relation on sync without filtering with proj…
saadmk11 Nov 24, 2020
76eff0d
Make remoterepository and account unique together
saadmk11 Nov 24, 2020
77c1777
Fix sync_delete test
saadmk11 Nov 24, 2020
e714315
Merge branch 'remote-repository-normalization' into update-oauth-serv…
saadmk11 Nov 25, 2020
bf8a167
Rename oauth migrations
saadmk11 Nov 25, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion readthedocs/api/v2/views/model_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ def get_queryset(self):
)

query = query.filter(
remote_relations__account__provider__in=[
remote_repository_relations__account__provider__in=[
service.adapter.provider_id for service in registry
],
).distinct()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ class Migration(migrations.Migration):
'user',
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name='remote_relations',
related_name='remote_repository_relations',
to=settings.AUTH_USER_MODEL
),
),
(
'remoterepository',
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name='remote_relations',
related_name='remote_repository_relations',
to='oauth.RemoteRepository'
),
),
Expand Down Expand Up @@ -77,7 +77,7 @@ class Migration(migrations.Migration):
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name='remote_relations',
related_name='remote_repository_relations',
to='socialaccount.SocialAccount',
verbose_name='Connected account'
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
log = logging.getLogger(__name__)


def move_data_to_remote_relations(apps, schema_editor):
def move_data_to_remote_repository_relations(apps, schema_editor):
RemoteRepositoryRelation = apps.get_model('oauth', 'RemoteRepositoryRelation')

def remote_relations_generator(relations, batch_size):
def remote_repository_relations_generator(relations, batch_size):
for relation in relations.iterator(chunk_size=batch_size):
relation.account_id = relation.remoterepository.account_id
relation.admin = relation.remoterepository.admin
Expand Down Expand Up @@ -42,14 +42,14 @@ def remote_relations_generator(relations, batch_size):
)

batch_size = 1000
remote_relations = remote_relations_generator(
remote_repository_relations = remote_repository_relations_generator(
relations_queryset, batch_size
)

# Follows Example from django docs
# https://docs.djangoproject.com/en/2.2/ref/models/querysets/#bulk-create
while True:
batch = list(islice(remote_relations, batch_size))
batch = list(islice(remote_repository_relations, batch_size))

if not batch:
break
Expand All @@ -72,5 +72,5 @@ class Migration(migrations.Migration):
]

operations = [
migrations.RunPython(move_data_to_remote_relations),
migrations.RunPython(move_data_to_remote_repository_relations),
]
6 changes: 3 additions & 3 deletions readthedocs/oauth/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,18 +206,18 @@ def matches(self, user):
class RemoteRepositoryRelation(TimeStampedModel):
remoterepository = models.ForeignKey(
RemoteRepository,
related_name='remote_relations',
related_name='remote_repository_relations',
on_delete=models.CASCADE
)
user = models.ForeignKey(
User,
related_name='remote_relations',
related_name='remote_repository_relations',
on_delete=models.CASCADE
)
account = models.ForeignKey(
SocialAccount,
verbose_name=_('Connected account'),
related_name='remote_relations',
related_name='remote_repository_relations',
null=True,
blank=True,
on_delete=models.SET_NULL,
Expand Down
7 changes: 4 additions & 3 deletions readthedocs/oauth/services/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,12 @@ def sync(self):
all_remote_repositories = remote_repositories + remote_repositories_organizations
repository_full_names = [r.full_name for r in all_remote_repositories if r is not None]
(
self.user.oauth_repositories
self.user.remote_repository_relations
.exclude(
Q(full_name__in=repository_full_names) | Q(project__isnull=False)
Q(remoterepository__full_name__in=repository_full_names) |
Q(remoterepository__project__isnull=False)
)
.filter(remote_relations__account=self.account)
.filter(account=self.account)
.delete()
)

Expand Down
7 changes: 4 additions & 3 deletions readthedocs/oauth/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ def update_webhook(project, integration, request=None):

updated = False
try:
remote_relations = project.remote_repository.remote_relations.filter(
account__isnull=False
remote_repository_relations = project.remote_repository.remote_repository_relations.filter(
account__isnull=False,
user=request.user
).select_related('account')

for relation in remote_relations:
for relation in remote_repository_relations:
service = service_cls(request.user, relation.account)
updated, __ = service.update_webhook(project, integration)

Expand Down
2 changes: 1 addition & 1 deletion readthedocs/rtd_tests/tests/test_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ def test_make_project_pass(self):
)
self.assertEqual(repo.ssh_url, '[email protected]:testorga/testrepo.git')
self.assertEqual(repo.html_url, 'https://gitlab.com/testorga/testrepo')
self.assertTrue(repo.remote_relations.first().admin)
self.assertTrue(repo.remote_repository_relations.first().admin)
self.assertFalse(repo.private)

def test_make_private_project_fail(self):
Expand Down
10 changes: 6 additions & 4 deletions readthedocs/rtd_tests/tests/test_oauth_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,16 @@ def test_sync_delete_stale(self, mock_request):
)

self.assertEqual(RemoteRepository.objects.count(), 3)
self.assertEqual(RemoteRepositoryRelation.objects.count(), 3)
self.assertEqual(RemoteOrganization.objects.count(), 1)

self.service.sync()

# After calling .sync, old-repository should be deleted,
# project-linked-repository should be conserved, and only the one
# returned by the API should be present (organization/repository)
self.assertEqual(RemoteRepository.objects.count(), 2)
# After calling .sync, old-repository remote relation should be deleted,
# project-linked-repository remote relation should be conserved,
# and only the one's returned by the API should be present (organization/repository)
self.assertEqual(RemoteRepository.objects.count(), 3)
self.assertEqual(RemoteRepositoryRelation.objects.count(), 2)
self.assertTrue(RemoteRepository.objects.filter(full_name='organization/repository').exists())
self.assertTrue(RemoteRepository.objects.filter(full_name='organization/project-linked-repository').exists())
self.assertEqual(RemoteOrganization.objects.count(), 0)
Expand Down