Commit 510930e9 authored by Tom Pillot's avatar Tom Pillot
Browse files

Mock github webhook with its signature

parent 19ed1af1
Pipeline #10324 failed with stage
in 20 seconds
import hashlib
import hmac
from hashlib import sha1
from pathlib import Path
from unittest import mock
......@@ -12,12 +12,17 @@ from rainboard.models import Project, Namespace, Forge
class GhTests(TestCase):
def post_github_event(self, event):
signature = 'sha1=' + hmac.new(force_bytes(settings.GITHUB_WEBHOOK_KEY),
digestmod=hashlib.sha1).hexdigest()
response = self.client.get(reverse('webhook'), HTTP_X_FORWARDED_FOR='140.82.112.1',
HTTP_X_HUB_SIGNATURE=signature, HTTP_X_GITHUB_EVENT=event)
def send_github_event(self, event, data=None):
encoded_data = self.client._encode_json({} if data is None else data, content_type='application/json')
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):
......@@ -30,17 +35,19 @@ class GhTests(TestCase):
self.assertEqual(response.status_code, 302)
# Signature not sha1
response = self.client.get(reverse('webhook'), HTTP_X_FORWARDED_FOR='140.82.112.1',
response = self.client.get(reverse('webhook'),
HTTP_X_FORWARDED_FOR='140.82.112.1',
HTTP_X_HUB_SIGNATURE='sha256=foo')
self.assertEqual(response.status_code, 501)
# Wrong signature
response = self.client.get(reverse('webhook'), HTTP_X_FORWARDED_FOR='140.82.112.1',
response = self.client.get(reverse('webhook'),
HTTP_X_FORWARDED_FOR='140.82.112.1',
HTTP_X_HUB_SIGNATURE='sha1=foo')
self.assertEqual(response.status_code, 403)
# Ping
response = self.post_github_event('ping')
response = self.send_github_event('ping')
self.assertEqual(response.status_code, 200)
def test_gl_webhook(self):
......@@ -53,20 +60,45 @@ class GhTests(TestCase):
self.assertEqual(response.status_code, 302)
# Wrong token
response = self.client.get(reverse('gl-webhook'), HTTP_X_FORWARDED_FOR='140.93.0.1',
HTTP_X_GITLAB_TOKEN='foo')
response = self.client.get(reverse('gl-webhook'), HTTP_X_FORWARDED_FOR='140.93.0.1', HTTP_X_GITLAB_TOKEN='foo')
self.assertEqual(response.status_code, 403)
# Ping
response = self.client.get(reverse('gl-webhook'), HTTP_X_FORWARDED_FOR='140.93.0.1',
HTTP_X_GITLAB_TOKEN=settings.GITLAB_WEBHOOK_KEY, HTTP_X_GITLAB_EVENT='ping')
response = self.client.get(reverse('gl-webhook'),
HTTP_X_FORWARDED_FOR='140.93.0.1',
HTTP_X_GITLAB_TOKEN=settings.GITLAB_WEBHOOK_KEY,
HTTP_X_GITLAB_EVENT='ping')
self.assertEqual(response.status_code, 200)
@mock.patch.object(Project, 'git_path')
def test_push(self, git_path):
git_path.return_value = Path('tmp')
namespace = Namespace.objects.get_or_create(name='tpillot')
namespace, _ = Namespace.objects.get_or_create(name='tpillot')
project, _ = Project.objects.get_or_create(name='example-adder',
main_namespace=Namespace.objects.get(name='tpillot'),
main_forge=Forge.objects.get(name='Gitlab'))
git_repo = project.git()
github = project.github()
last_commit = github.get_branch('master').commit.sha
# Push when both repos are already synced
response = self.send_github_event(
'push', {
'repository': {
'name': 'example-adder',
'owner': {
'name': 'tpillot'
}
},
'ref': 'refs/heads/master',
'after': last_commit
})
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), 'already synced')
# Push new commit on github
file = github.get_contents('README.md')
github.update_file('README.md', message='Test push on github', content=last_commit[:8], sha=file.sha)
# TODO: Make sure both repos are still synced
......@@ -158,6 +158,8 @@ def push(request: HttpRequest, source: SOURCES, rep: str) -> HttpResponse:
elif branch not in gl_remote.refs or str(gl_remote.refs[branch].commit) != commit:
logger.info(f'{namespace.slug}/{project.slug}: Pushing {commit} on {branch} on gitlab')
git_repo.git.push(gl_remote_name, branch)
else:
return HttpResponse('already synced')
except git.exc.GitCommandError:
# Probably failed because of a force push
logger.exception(f'{namespace.slug}/{project.slug}: Forge sync failed')
......
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