Commit f4c98e2c authored by Tom Pillot's avatar Tom Pillot
Browse files

Test sync with push on gitlab

parent b6588a13
Pipeline #10396 failed with stage
in 1 minute and 12 seconds
import hmac
import time
from hashlib import sha1
from os import getenv
from pathlib import Path
from unittest import mock
import git
from autoslug.utils import slugify
......@@ -18,7 +15,7 @@ from rainboard.models import Project, Namespace, Forge
class GhTests(TestCase):
@classmethod
def setUpClass(cls):
"""Run only once, avoid getting the objects in each test."""
"""Run only once before the tests to avoid getting the objects in each test."""
super(GhTests, cls).setUpClass()
if getenv('GITLAB_PIPELINE_TOKEN'): # Inside gitlab pipeline
cls.namespace, _ = Namespace.objects.get_or_create(name='gsaurel',
......@@ -38,8 +35,7 @@ class GhTests(TestCase):
cls.gitlab = cls.project.gitlab()
@classmethod
@mock.patch.object(Project, 'git_path', return_value=Path('tmp'))
def tearDownClass(cls, mock_git_path):
def tearDownClass(cls):
"""Force both repos to be synced after the tests."""
print('Syncing both repos after the tests ...')
for branch in ('master', 'devel'):
......@@ -49,17 +45,28 @@ class GhTests(TestCase):
if last_commit_github != last_commit_gitlab:
print(f'{branch} is not synced, force pushing to github')
git_repo = cls.project.git()
with git_repo.config_writer() as cw:
cw.set_value('user', 'email', "you@example.com")
cw.set_value('user', 'name', "foo")
git_repo.git.reset('--hard')
git_repo.git.pull(f'gitlab/{cls.namespace.slug}', branch)
git_repo.git.reset('--hard', f'gitlab/{cls.namespace.slug}/{branch}')
try:
git_repo.git.push(f'github/{cls.namespace.slug}', branch, force=True)
git_repo.git.push('-f', f'github/{cls.namespace.slug}', branch)
except git.GitCommandError:
print(f'Failed to push on github {branch}')
def send_github_event(self, event, last_commit=''):
last_commit_github = cls.github.get_branch(branch).commit.sha
last_commit_gitlab = cls.gitlab.commits.list(ref_name=branch)[0].id
assert last_commit_github == last_commit_gitlab
def gh_webhook_event(self, event, last_commit=''):
"""Simulate receiving an event from a github webhook."""
data = {
'repository': {
'name': 'example-adder',
'owner': {
'name': 'Ozon2'
'name': self.namespace.slug_github
}
},
'ref': 'refs/heads/master',
......@@ -70,15 +77,35 @@ class GhTests(TestCase):
request_body = self.client._encode_data(encoded_data, content_type='application/json')
msg = force_bytes(request_body)
signature = 'sha1=' + hmac.new(force_bytes(settings.GITHUB_WEBHOOK_KEY), msg, digestmod=sha1).hexdigest()
response = self.client.post(reverse('webhook'),
data,
content_type='application/json',
HTTP_X_FORWARDED_FOR='140.82.112.1',
HTTP_X_HUB_SIGNATURE=signature,
HTTP_X_GITHUB_EVENT=event)
return response
def test_webhook(self):
return self.client.post(reverse('webhook'),
data,
content_type='application/json',
HTTP_X_FORWARDED_FOR='140.82.112.1',
HTTP_X_HUB_SIGNATURE=signature,
HTTP_X_GITHUB_EVENT=event)
def gl_webhook_event(self, event, last_commit=''):
"""Simulate receiving an event from a gitlab webhook."""
data = {
'repository': {
'name': 'example-adder',
},
'project': {
'namespace': self.namespace.slug_gitlab
},
'ref': 'refs/heads/master',
'after': last_commit
}
return self.client.post(reverse('gl-webhook'),
data,
content_type='application/json',
HTTP_X_FORWARDED_FOR='140.93.0.1',
HTTP_X_GITLAB_TOKEN=settings.GITLAB_WEBHOOK_KEY,
HTTP_X_GITLAB_EVENT=event)
def test_gh_webhook(self):
"""Test the security of the github webhook."""
# Not from github IP
response = self.client.get(reverse('webhook'), HTTP_X_FORWARDED_FOR='5.5.5.5')
self.assertEqual(response.status_code, 302)
......@@ -100,10 +127,12 @@ class GhTests(TestCase):
self.assertEqual(response.status_code, 403)
# Ping
response = self.send_github_event('ping')
response = self.gh_webhook_event('ping')
self.assertEqual(response.status_code, 200)
def test_gl_webhook(self):
"""Test the security of the gitlab webhook."""
# Not from gitlab IP
response = self.client.get(reverse('gl-webhook'), HTTP_X_FORWARDED_FOR='5.5.5.5')
self.assertEqual(response.status_code, 302)
......@@ -123,25 +152,46 @@ class GhTests(TestCase):
HTTP_X_GITLAB_EVENT='ping')
self.assertEqual(response.status_code, 200)
@mock.patch.object(Project, 'git_path', return_value=Path('tmp'))
def test_push(self, mock_git_path):
def test_push_already_synced(self):
"""Test push when both repos are already synced."""
last_commit = self.github.get_branch('master').commit.sha
# Push when both repos are already synced
response = self.send_github_event('push', last_commit)
response = self.gh_webhook_event('push', last_commit)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), 'already synced')
# Push new commit on github
def test_push_github(self):
"""Test sync after pushing to github."""
last_commit = self.github.get_branch('master').commit.sha
file = self.github.get_contents('README.md')
self.github.update_file('README.md', message='Test push on github', content=last_commit[:8], sha=file.sha)
self.github.update_file('README.md',
message='Test push on github',
content=last_commit[:8],
sha=file.sha,
branch='master')
last_commit_github = self.github.get_branch('master').commit.sha
self.assertNotEqual(last_commit, last_commit_github)
response = self.send_github_event('push', last_commit_github)
response = self.gh_webhook_event('push', last_commit_github)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), 'push event detected')
last_commit_gitlab = self.gitlab.commits.list()[0].id
last_commit_gitlab = self.gitlab.commits.list(ref_name='master')[0].id
self.assertEqual(last_commit_github, last_commit_gitlab)
def test_push_gitlab(self):
"""Test sync after pushing to gitlab."""
last_commit = self.gitlab.commits.list(ref_name='master')[0].id
file = self.gitlab.files.get(file_path='README.md', ref='master')
file.content = last_commit[:8]
file.save(branch='master', commit_message='Test push on gitlab')
last_commit_gitlab = self.gitlab.commits.list(ref_name='master')[0].id
self.assertNotEqual(last_commit, last_commit_gitlab)
response = self.gl_webhook_event('Push Hook', last_commit_gitlab)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), 'push event detected')
last_commit_github = self.github.get_branch('master').commit.sha
self.assertEqual(last_commit_github, last_commit_gitlab)
......@@ -222,7 +222,6 @@ class Project(Links, NamedModel, TimeStampedModel):
def github(self):
github_forge = Forge.objects.get(slug='github')
print(github_forge.token)
gh = Github(github_forge.token)
return gh.get_repo(f'{self.main_namespace.slug_github}/{self.slug}')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment