Commit 5ad49dc6 authored by Guilhem Saurel's avatar Guilhem Saurel
Browse files

Merge branch 'dashboard-apps-patch-master' into 'master'

Sync GitHub and GitLab projects

See merge request !3
parents efa76df3 1aca9ebb
Pipeline #10533 passed with stage
in 8 minutes and 8 seconds
.env
db.sqlite3
__pycache__/
.idea
\ No newline at end of file
......@@ -21,6 +21,6 @@ build:
image: docker
script:
- docker build -t ${DOCKER_TAG} .
- docker run --rm -e SECRET_KEY -e GITHUB_WEBHOOK_KEY -e GITLAB_WEBHOOK_KEY -e PYTHONWARNINGS ${DOCKER_TAG} ./manage.py migrate
- docker run --rm -e SECRET_KEY -e GITHUB_WEBHOOK_KEY -e GITLAB_WEBHOOK_KEY -e PYTHONWARNINGS ${DOCKER_TAG} ./manage.py test
- docker run --rm -e SECRET_KEY -e GITHUB_WEBHOOK_KEY -e GITLAB_WEBHOOK_KEY -e GITHUB_PIPELINE_TOKEN -e GITLAB_PIPELINE_TOKEN -e PYTHONWARNINGS ${DOCKER_TAG} ./manage.py migrate
- docker run --rm -e SECRET_KEY -e GITHUB_WEBHOOK_KEY -e GITLAB_WEBHOOK_KEY -e GITHUB_PIPELINE_TOKEN -e GITLAB_PIPELINE_TOKEN -e PYTHONWARNINGS ${DOCKER_TAG} ./manage.py test
- docker push ${DOCKER_TAG}
......@@ -16,3 +16,5 @@ requests = "*"
GitPython = "*"
djangorestframework = "<3.12"
django-auth-ldap = "*"
python-gitlab = "*"
pygithub = "*"
{
"_meta": {
"hash": {
"sha256": "ebc0e3256d27ac65f467c43f53c16fc14ff58f693d277ee43b17892592d33474"
"sha256": "8f167f313807117a90141a02ab8a2b9c7af2afa7f69bde38c3cae894ffda51e7"
},
"pipfile-spec": 6,
"requires": {},
......@@ -16,11 +16,11 @@
"default": {
"asgiref": {
"hashes": [
"sha256:8036f90603c54e93521e5777b2b9a39ba1bad05773fcf2d208f0299d1df58ce5",
"sha256:9ca8b952a0a9afa61d30aa6d3d9b570bb3fd6bafcf7ec9e6bed43b936133db1c"
"sha256:7e51911ee147dd685c3c8b805c0ad0cb58d360987b56953878f8c06d2d1c6f1a",
"sha256:9fc6fb5d39b8af147ba40765234fa822b39818b12cc80b35ad9b0cef3a476aed"
],
"markers": "python_version >= '3.5'",
"version": "==3.2.7"
"version": "==3.2.10"
},
"beautifulsoup4": {
"hashes": [
......@@ -32,10 +32,10 @@
},
"certifi": {
"hashes": [
"sha256:5ad7e9a056d25ffa5082862e36f119f7f7cec6457fa07ee2f8c339814b80c9b1",
"sha256:9cd41137dc19af6a5e03b630eefe7d1f458d964d406342dd3edf625839b944cc"
"sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3",
"sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"
],
"version": "==2020.4.5.2"
"version": "==2020.6.20"
},
"chardet": {
"hashes": [
......@@ -44,13 +44,21 @@
],
"version": "==3.0.4"
},
"deprecated": {
"hashes": [
"sha256:525ba66fb5f90b07169fdd48b6373c18f1ee12728ca277ca44567a367d9d7f74",
"sha256:a766c1dccb30c5f6eb2b203f87edd1d8588847709c78589e1521d769addc8218"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.2.10"
},
"django": {
"hashes": [
"sha256:5052b34b34b3425233c682e0e11d658fd6efd587d11335a0203d827224ada8f2",
"sha256:e1630333248c9b3d4e38f02093a26f1e07b271ca896d73097457996e0fae12e8"
"sha256:31a5fbbea5fc71c99e288ec0b2f00302a0a92c44b13ede80b73a6a4d6d205582",
"sha256:5457fc953ec560c5521b41fad9e6734a4668b7ba205832191bbdff40ec61073c"
],
"index": "pypi",
"version": "==3.0.7"
"version": "==3.0.8"
},
"django-auth-ldap": {
"hashes": [
......@@ -62,18 +70,18 @@
},
"django-autoslug": {
"hashes": [
"sha256:026b525beed3e259532d23f2bff768c1e5f4d238caa4e99db223f9d5d232cb57",
"sha256:08065b662e05fa5ad8b9cff2b54d17481bd31672ea2a4e7e607267f692384b83"
"sha256:26459eeddec207e307c55777a10fc25d17f4978753695340b16a17ed248a6f70",
"sha256:bae66c27d35615f472865b99c4d107f3b3add3d22ee337e84960fc07694abd45"
],
"version": "==1.9.7"
"version": "==1.9.8"
},
"django-bootstrap4": {
"hashes": [
"sha256:7baf22ab8570b5147b566b3431738c4f3558604ad7a8140f69d784a04c9eb1c8",
"sha256:f1fbe0ab1e6357072642b25c0e7473b3bfe31d9f28eaacad237474a94f8df792"
"sha256:1c0a931b4245a0dcd5051ea1b244ac130a328374ce8e85254c75eb072a737201",
"sha256:32cc0f914ace4cef935c0d3f786dde2a52f0ea1be72153f6e356c0aa8f3925e1"
],
"markers": "python_version >= '3.6' and python_version < '4.0'",
"version": "==2.0.1"
"markers": "python_version < '4.0' and python_full_version >= '3.6.0'",
"version": "==2.2.0"
},
"django-filter": {
"hashes": [
......@@ -109,19 +117,19 @@
},
"gitpython": {
"hashes": [
"sha256:e107af4d873daed64648b4f4beb89f89f0cfbe3ef558fc7821ed2331c2f8da1a",
"sha256:ef1d60b01b5ce0040ad3ec20bc64f783362d41fa0822a2742d3586e1f49bb8ac"
"sha256:2db287d71a284e22e5c2846042d0602465c7434d910406990d5b74df4afb0858",
"sha256:fa3b92da728a457dd75d62bb5f3eb2816d99a7fe6c67398e260637a40e3fafb5"
],
"index": "pypi",
"version": "==3.1.3"
"version": "==3.1.7"
},
"idna": {
"hashes": [
"sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
"sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
"sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.9"
"version": "==2.10"
},
"ndh": {
"hashes": [
......@@ -133,46 +141,69 @@
},
"pyasn1": {
"hashes": [
"sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba",
"sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2",
"sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359",
"sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576",
"sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf",
"sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7",
"sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
"sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12",
"sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576",
"sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00",
"sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8",
"sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86",
"sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3",
"sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359",
"sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00",
"sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12",
"sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776",
"sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"
"sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba",
"sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2",
"sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"
],
"version": "==0.4.8"
},
"pyasn1-modules": {
"hashes": [
"sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8",
"sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199",
"sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45",
"sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405",
"sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4",
"sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb",
"sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811",
"sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed",
"sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4",
"sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e",
"sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74",
"sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb",
"sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45",
"sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd",
"sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8",
"sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d",
"sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0",
"sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e",
"sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed"
"sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d",
"sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405"
],
"version": "==0.2.8"
},
"pygithub": {
"hashes": [
"sha256:8375a058ec651cc0774244a3bc7395cf93617298735934cdd59e5bcd9a1df96e",
"sha256:d2d17d1e3f4474e070353f201164685a95b5a92f5ee0897442504e399c7bc249"
],
"index": "pypi",
"version": "==1.51"
},
"pyjwt": {
"hashes": [
"sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e",
"sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"
],
"version": "==1.7.1"
},
"python-gitlab": {
"hashes": [
"sha256:6461e0662cacceb795fb3ffd225391133cc11e0e760d0caf1c998c7ba955c771",
"sha256:e240b5c371d9e98c46c980d878c3f03cd83f3da6cda01d533db27fa3e0dd474f"
],
"index": "pypi",
"version": "==2.4.0"
},
"python-ldap": {
"hashes": [
"sha256:7d1c4b15375a533564aad3d3deade789221e450052b21ebb9720fb822eccdb8e"
"sha256:4711cacf013e298754abd70058ccc995758177fb425f1c2d30e71adfc1d00aa5"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==3.2.0"
"version": "==3.3.1"
},
"pytz": {
"hashes": [
......@@ -183,11 +214,11 @@
},
"requests": {
"hashes": [
"sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
"sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
"sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b",
"sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"
],
"index": "pypi",
"version": "==2.23.0"
"version": "==2.24.0"
},
"smmap": {
"hashes": [
......@@ -215,11 +246,17 @@
},
"urllib3": {
"hashes": [
"sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527",
"sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"
"sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a",
"sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'",
"version": "==1.25.10"
},
"wrapt": {
"hashes": [
"sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
"version": "==1.25.9"
"version": "==1.12.1"
}
},
"develop": {
......@@ -239,11 +276,11 @@
},
"ipython": {
"hashes": [
"sha256:0ef1433879816a960cd3ae1ae1dc82c64732ca75cec8dab5a4e29783fb571d0e",
"sha256:1b85d65632211bf5d3e6f1406f3393c8c429a47d7b947b9a87812aa5bce6595c"
"sha256:2dbcc8c27ca7d3cfe4fcdff7f45b27f9a8d3edfa70ff8024a71c7a8eb5f09d64",
"sha256:9f4fcb31d3b2c533333893b9172264e4821c1ac91839500f31bd43f2c59b3ccf"
],
"index": "pypi",
"version": "==7.15.0"
"version": "==7.16.1"
},
"ipython-genutils": {
"hashes": [
......@@ -254,19 +291,19 @@
},
"jedi": {
"hashes": [
"sha256:cd60c93b71944d628ccac47df9a60fec53150de53d42dc10a7fc4b5ba6aae798",
"sha256:df40c97641cb943661d2db4c33c2e1ff75d491189423249e989bcea4464f3030"
"sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20",
"sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==0.17.0"
"version": "==0.17.2"
},
"parso": {
"hashes": [
"sha256:158c140fc04112dc45bca311633ae5033c2c2a7b732fa33d0955bad8152a8dd0",
"sha256:908e9fae2144a076d72ae4e25539143d40b8e3eafbaeae03c1bfe226f4cdf12c"
"sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea",
"sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.7.0"
"version": "==0.7.1"
},
"pexpect": {
"hashes": [
......@@ -323,10 +360,10 @@
},
"wcwidth": {
"hashes": [
"sha256:79375666b9954d4a1a10739315816324c3e73110af9d0e102d906fdb0aec009f",
"sha256:8c6b5b6ee1360b842645f336d9e5d68c55817c26d3050f46b235ef2bc650e48f"
"sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784",
"sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"
],
"version": "==0.2.4"
"version": "==0.2.5"
},
"yapf": {
"hashes": [
......
......@@ -8,7 +8,7 @@ from rest_framework import permissions
def ip_laas(request: HttpRequest) -> bool:
"""check if request comes from settings.LAAS_NETWORKS."""
forwarded_for = ip_address(request.META.get('HTTP_X_FORWARDED_FOR'))
forwarded_for = ip_address(request.META.get('HTTP_X_FORWARDED_FOR').split(', ')[0])
return any(forwarded_for in ip_network(net) for net in settings.LAAS_NETWORKS)
......
......@@ -28,6 +28,7 @@ SERVER_EMAIL = f'{EMAIL_USER}+{PROJECT}@{EMAIL_FQDN}'
DEFAULT_FROM_EMAIL = f'{PROJECT_VERBOSE} <{EMAIL_USER}@{EMAIL_FQDN}>'
EMAIL_BACKEND = 'django.core.mail.backends.%s' % ('filebased.EmailBackend' if DEBUG else 'smtp.EmailBackend')
EMAIL_SUBJECT_PREFIX = f'[{PROJECT_VERBOSE}] '
EMAIL_FILE_PATH = 'email/'
ADMINS = ((os.environ.get('ADMIN_NAME',
f'{PROJECT_VERBOSE} webmaster'), os.environ.get('ADMIN_MAIL', f'webmaster@{DOMAIN_NAME}')), )
......@@ -141,12 +142,19 @@ LOGGING = {
'level': 'DEBUG',
'class': 'logging.NullHandler',
},
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
'gh': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
......
import hmac
import re
import git
from hashlib import sha1
from os import getenv
from autoslug.utils import slugify
from django.conf import settings
from django.test import TestCase
from django.urls import reverse
from django.utils.encoding import force_bytes
from rainboard.models import Project, Namespace, Forge
def redact_token(func):
"""Decorator used to prevent git from leaking tokens in exception messages."""
def wrapped_function(*args, **kwargs):
try:
return func(*args, **kwargs)
except git.GitCommandError as e:
e.stderr = re.sub(r'://.*@', '://[REDACTED]@', e.stderr)
raise e
return wrapped_function
class GhTests(TestCase):
@classmethod
def setUpClass(cls):
"""Run only once before the tests to avoid getting the objects in each test."""
super(GhTests, cls).setUpClass()
cls.namespace, _ = Namespace.objects.get_or_create(name='gsaurel',
slug_gitlab=slugify('gsaurel'),
slug_github=slugify('hrp2-14'))
cls.project, _ = Project.objects.get_or_create(name='rainboard-tests',
main_namespace=Namespace.objects.get(name='gsaurel'),
main_forge=Forge.objects.get(name='Gitlab'))
cls.github = cls.project.github()
cls.gitlab = cls.project.gitlab()
# Cleanup previous test
for pr in cls.github.get_pulls(state="open"):
pr.edit(state="closed")
gh_branches = [b.name for b in cls.github.get_branches()]
gl_branches = [b.name for b in cls.gitlab.branches.list()]
for branch_name in gl_branches:
if branch_name.startswith('pr/'):
cls.gitlab.branches.delete(branch_name)
for branch_name in ['test-branch-gitlab', 'test-branch-github']:
if branch_name in gh_branches:
cls.github.get_git_ref(f'heads/{branch_name}').delete()
if branch_name in gl_branches:
cls.gitlab.branches.delete(branch_name)
def assertSync(self, branch):
"""Raise an exception if the branch is not synced between both repos."""
last_commit_github = self.github.get_branch(branch).commit.sha
last_commit_gitlab = self.gitlab.commits.list(ref_name=branch)[0].id
self.assertEqual(last_commit_github, last_commit_gitlab)
@redact_token
def sync(self):
"""Force both repos to be synced."""
for branch in ('master', 'devel'):
last_commit_github = self.github.get_branch(branch).commit.sha
last_commit_gitlab = self.gitlab.commits.list(ref_name=branch)[0].id
if last_commit_github != last_commit_gitlab:
print(f'sync: {branch} is not synced, force pushing commit {last_commit_gitlab} on github')
git_repo = self.project.git()
# Create the remotes if necessary
gl_remote_name = f'gitlab/{self.namespace.slug}'
gh_remote_name = f'github/{self.namespace.slug}'
if gl_remote_name not in git_repo.remotes:
git_repo.create_remote(gl_remote_name, url=self.project.remote_url_gitlab())
if gh_remote_name not in git_repo.remotes:
git_repo.create_remote(gh_remote_name, url=self.project.remote_url_github())
# Force push the latest gitlab commit on github
git_repo.remote(gl_remote_name).fetch()
git_repo.git.push('-f', gh_remote_name, f'{last_commit_gitlab}:{branch}')
self.assertSync(branch)
@redact_token
def gh_webhook_event(self, event, last_commit='', branch='master', pr_action='', pr_number='', pr_login=''):
"""Simulate receiving an event from a github webhook."""
data = {
'repository': {
'name': self.project.slug,
'owner': {
'login': self.namespace.slug_github
}
},
'ref': f'refs/heads/{branch}',
'after': last_commit,
'action': pr_action,
'number': pr_number,
'pull_request': {
'head': {
'repo': {
'owner': {
'login': pr_login
},
'clone_url': self.project.remote_url_github()
},
'sha': last_commit
}
}
}
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()
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)
@redact_token
def gl_webhook_event(self, event, last_commit='', branch='master', status=''):
"""Simulate receiving an event from a gitlab webhook."""
data = {
'repository': {
'name': self.project.slug,
},
'project': {
'name': self.project.slug,
'path_with_namespace': f'{self.namespace.slug_gitlab}/{self.project.slug}'
},
'ref': f'refs/heads/{branch}',
'after': last_commit,
'object_attributes': {
'ref': branch,
'sha': last_commit,
'status': status,
'id': 1
}
}
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)
# No signature
response = self.client.get(reverse('webhook'), HTTP_X_FORWARDED_FOR='140.82.112.1')
self.assertEqual(response.status_code, 302)
# Signature not sha1
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',
HTTP_X_HUB_SIGNATURE='sha1=foo')
self.assertEqual(response.status_code, 403)
# 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)
# No token
response = self.client.get(reverse('gl-webhook'), HTTP_X_FORWARDED_FOR='140.93.0.1')
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')
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')
self.assertEqual(response.status_code, 200)
def test_push_already_synced(self):
"""Test push when both repos are already synced."""
self.sync()
last_commit = self.github.get_branch('master').commit.sha
response = self.gh_webhook_event('push', last_commit)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), 'already synced')
def push_github(self, branch):
"""Test sync after pushing to the given branch on github."""
self.sync()
last_commit = self.github.get_branch(branch).commit.sha
file = self.github.get_contents('README.md', branch)
self.github.update_file('README.md',
message=f'Test push on github {branch}',
content=last_commit[:8],
sha=file.sha,
branch=branch)
last_commit_github = self.github.get_branch(branch).commit.sha
self.assertNotEqual(last_commit, last_commit_github)
response = self.gh_webhook_event('push', last_commit_github, branch)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), 'push event detected')
last_commit_gitlab = self.gitlab.commits.list(ref_name=branch)[0].id
self.assertEqual(last_commit_github, last_commit_gitlab)
def test_push_github_master(self):
"""Test sync after pushing to github on master."""
self.push_github('master')
def test_push_github_devel(self):
"""Test sync after pushing to github on devel."""
self.push_github('devel')
def push_gitlab(self, branch):
"""Test sync after pushing to the given branch on gitlab."""
self.sync()
last_commit = self.gitlab.commits.list(ref_name=branch)[0].id
# Push a new commit to gitlab
file = self.gitlab.files.get(file_path='README.md', ref=branch)
file.content = last_commit[:8]
file.save(branch=branch, commit_message=f'Test push on gitlab {branch}')
last_commit_gitlab = self.gitlab.commits.list(ref_name=branch)[0].id
self.assertNotEqual(last_commit, last_commit_gitlab)
response = self.gl_webhook_event('Push Hook', last_commit_gitlab, branch)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), 'push event detected')
last_commit_github = self.github.get_branch(branch).commit.sha
self.assertEqual(last_commit_github, last_commit_gitlab)