Skip to content

Commit 9152bb6

Browse files
authored
Merge pull request #1 from galileo-press/sync-gitlab-repos
Sync gitlab repos
2 parents e4adb98 + aec6941 commit 9152bb6

File tree

3 files changed

+147
-5
lines changed

3 files changed

+147
-5
lines changed

docs/features.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ More information can be found in the :doc:`vcs` page.
1313
Auto-updating
1414
-------------
1515

16-
The :doc:`webhooks` page talks about the different ways you can ping RTD to let us know your project has been updated. We have official support for GitHub, and anywhere else we have a generic post-commit hook that allows you to POST to a URL to get your documentation built.
16+
The :doc:`webhooks` page talks about the different ways you can ping RTD to let us know your project has been updated. We have official support for GitHub, Bitbucket and GitLab, and anywhere else we have a generic post-commit hook that allows you to POST to a URL to get your documentation built.
1717

1818
Internationalization
1919
--------------------

docs/webhooks.rst

+13-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ worked with push knows, pushing a doc update to your repo and watching it get
99
updated within seconds is an awesome feeling.
1010

1111
GitHub
12-
---------
12+
------
1313

1414
If your project is hosted on GitHub, you can easily add a hook that will rebuild
1515
your docs whenever you push updates:
@@ -27,7 +27,7 @@ If you ever need to manually set the webhook on GitHub,
2727
you can point it at ``https://readthedocs.org/github``.
2828

2929
Bitbucket
30-
-----------
30+
---------
3131

3232
If your project is hosted on Bitbucket, you can easily add a hook that will rebuild
3333
your docs whenever you push updates:
@@ -40,6 +40,17 @@ your docs whenever you push updates:
4040
If you ever need to manually set the webhook on Bitbucket,
4141
you can point it at ``https://readthedocs.org/bitbucket``.
4242

43+
GitLab
44+
------
45+
46+
If your project is hosted on GitLab, you can manually set the webhook on Gitlab and
47+
point it at ``https://readthedocs.org/gitlab``:
48+
49+
* Click the settings icon for your project
50+
* Select "Webhooks"
51+
* Enter the above URL, select "Push events" and "Enable SSL verification"
52+
* Click "Add Webhook"
53+
4354
Others
4455
------
4556

readthedocs/rtd_tests/tests/test_oauth.py

+133-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from django.test import TestCase
22

33
from django.contrib.auth.models import User
4-
from allauth.socialaccount.models import SocialToken
4+
from mock import Mock
55

6+
from readthedocs.projects import constants
67
from readthedocs.projects.models import Project
78

8-
from readthedocs.oauth.services import GitHubService, BitbucketService
99
from readthedocs.oauth.models import RemoteRepository, RemoteOrganization
10+
from readthedocs.oauth.services import GitHubService, BitbucketService, GitLabService
1011

1112

1213
class GitHubOAuthTests(TestCase):
@@ -279,3 +280,133 @@ def test_import_with_no_token(self):
279280
'''User without a Bitbucket SocialToken does not return a service'''
280281
services = BitbucketService.for_user(self.user)
281282
self.assertEqual(services, [])
283+
284+
285+
class GitLabOAuthTests(TestCase):
286+
287+
fixtures = ["eric", "test_data"]
288+
289+
repo_response_data = {
290+
'forks_count': 12,
291+
'container_registry_enabled': None,
292+
'web_url': 'https://gitlab.com/testorga/testrepo',
293+
'wiki_enabled': True,
294+
'public_builds': True,
295+
'id': 2,
296+
'merge_requests_enabled': True,
297+
'archived': False,
298+
'snippets_enabled': False,
299+
'http_url_to_repo': 'https://gitlab.com/testorga/testrepo.git',
300+
'namespace': {
301+
'share_with_group_lock': False,
302+
'name': 'Test Orga',
303+
'created_at': '2014-07-11T13:38:53.510Z',
304+
'description': '',
305+
'updated_at': '2014-07-11T13:38:53.510Z',
306+
'avatar': {
307+
'url': None
308+
},
309+
'path': 'testorga',
310+
'visibility_level': 20,
311+
'id': 5,
312+
'owner_id': None
313+
},
314+
'star_count': 0,
315+
'avatar_url': 'http://placekitten.com/50/50',
316+
'issues_enabled': True,
317+
'path_with_namespace': 'testorga/testrepo',
318+
'public': True,
319+
'description': 'Test Repo',
320+
'default_branch': 'master',
321+
'ssh_url_to_repo': '[email protected]:testorga/testrepo.git',
322+
'path': 'testrepo',
323+
'visibility_level': 20,
324+
'permissions': {
325+
'group_access': {
326+
'notification_level': 3,
327+
'access_level': 40
328+
},
329+
'project_access': None
330+
},
331+
'open_issues_count': 2,
332+
'last_activity_at': '2016-03-01T09:22:34.344Z',
333+
'name': 'testrepo',
334+
'name_with_namespace': 'testorga / testrepo',
335+
'created_at': '2015-11-02T13:52:42.821Z',
336+
'builds_enabled': True,
337+
'creator_id': 5,
338+
'shared_runners_enabled': True,
339+
'tag_list': []
340+
}
341+
342+
def setUp(self):
343+
self.client.login(username='eric', password='test')
344+
self.user = User.objects.get(pk=1)
345+
self.project = Project.objects.get(slug='pip')
346+
self.org = RemoteOrganization.objects.create(slug='testorga', json='')
347+
self.privacy = self.project.version_privacy_level
348+
self.service = GitLabService(user=self.user, account=None)
349+
350+
def get_private_repo_data(self):
351+
"""Manipulate repo response data to get private repo data."""
352+
data = self.repo_response_data.copy()
353+
data.update({
354+
'visibility_level': 10,
355+
'public': False,
356+
})
357+
return data
358+
359+
def test_make_project_pass(self):
360+
repo = self.service.create_repository(
361+
self.repo_response_data, organization=self.org, privacy=self.privacy)
362+
self.assertIsInstance(repo, RemoteRepository)
363+
self.assertEqual(repo.name, 'testrepo')
364+
self.assertEqual(repo.full_name, 'testorga / testrepo')
365+
self.assertEqual(repo.description, 'Test Repo')
366+
self.assertEqual(repo.avatar_url, 'http://placekitten.com/50/50')
367+
self.assertIn(self.user, repo.users.all())
368+
self.assertEqual(repo.organization, self.org)
369+
self.assertEqual(repo.clone_url, 'https://gitlab.com/testorga/testrepo.git')
370+
self.assertEqual(repo.ssh_url, '[email protected]:testorga/testrepo.git')
371+
self.assertEqual(repo.html_url, 'https://gitlab.com/testorga/testrepo')
372+
373+
def test_make_private_project_fail(self):
374+
repo = self.service.create_repository(
375+
self.get_private_repo_data(), organization=self.org, privacy=self.privacy)
376+
self.assertIsNone(repo)
377+
378+
def test_make_private_project_success(self):
379+
repo = self.service.create_repository(
380+
self.get_private_repo_data(), organization=self.org, privacy=constants.PRIVATE)
381+
self.assertIsInstance(repo, RemoteRepository)
382+
self.assertTrue(repo.private, True)
383+
384+
def test_make_organization(self):
385+
org = self.service.create_organization(self.repo_response_data['namespace'])
386+
self.assertIsInstance(org, RemoteOrganization)
387+
self.assertEqual(org.slug, 'testorga')
388+
self.assertEqual(org.name, 'Test Orga')
389+
self.assertEqual(org.avatar_url, '/media/images/fa-users.svg')
390+
self.assertEqual(org.url, 'https://gitlab.com/testorga')
391+
392+
def test_sync_skip_archived_repo(self):
393+
data = self.repo_response_data
394+
data['archived'] = True
395+
create_repo_mock = Mock()
396+
create_orga_mock = Mock()
397+
setattr(self.service, 'paginate', Mock(return_value=[data]))
398+
setattr(self.service, 'create_repository', create_repo_mock)
399+
setattr(self.service, 'create_organization', create_orga_mock)
400+
self.service.sync()
401+
self.assertFalse(create_repo_mock.called)
402+
self.assertFalse(create_orga_mock.called)
403+
404+
def test_sync_create_repo_and_orga(self):
405+
create_repo_mock = Mock()
406+
create_orga_mock = Mock(return_value=self.org)
407+
setattr(self.service, 'paginate', Mock(return_value=[self.repo_response_data]))
408+
setattr(self.service, 'create_repository', create_repo_mock)
409+
setattr(self.service, 'create_organization', create_orga_mock)
410+
self.service.sync()
411+
create_repo_mock.assert_called_once_with(self.repo_response_data, organization=self.org)
412+
create_orga_mock.assert_called_once_with(self.repo_response_data['namespace'])

0 commit comments

Comments
 (0)