[damned-lies] Add webhook to automatically update code



commit 6ab6f34e2ea24f578346ada1e47428df3feef1fe
Author: Claude Paroz <claude 2xlibre net>
Date:   Tue Apr 24 15:16:18 2018 +0200

    Add webhook to automatically update code

 common/tests.py        |   20 ++++++++++++++++++++
 common/views.py        |   23 +++++++++++++++++++++--
 damnedlies/settings.py |    2 ++
 damnedlies/urls.py     |    3 +++
 4 files changed, 46 insertions(+), 2 deletions(-)
---
diff --git a/common/tests.py b/common/tests.py
index ce14382..f766218 100644
--- a/common/tests.py
+++ b/common/tests.py
@@ -3,6 +3,7 @@ from datetime import datetime, timedelta
 from unittest import skipUnless
 from unittest.mock import MagicMock, patch
 
+from django.conf import settings
 from django.core.management import call_command
 from django.test import TestCase
 from django.urls import reverse
@@ -61,6 +62,25 @@ class CommonTest(TestCase):
         for role in Role.objects.filter(person=jt):
             self.assertFalse(role.is_active)
 
+    def test_pull_code(self):
+        push_data = {
+            "object_kind": "push",
+            "ref": "refs/heads/master",
+            # Gitlab will send a lot more, but we don't care.
+        }
+        with patch('common.views.run_shell_command', return_value=(0, '', '')) as rsc_patched:
+            with patch('common.views.call_command') as cc_patched:
+                response = self.client.post('/pull_code/', data=push_data)
+                self.assertEqual(response.status_code, 403)
+                response = self.client.post(
+                    '/pull_code/', data=push_data,
+                    HTTP_X_GITLAB_EVENT='Push Hook',
+                    HTTP_X_GITLAB_TOKEN=settings.GITLAB_TOKEN,
+                )
+        self.assertEqual(rsc_patched.call_count, 2)
+        self.assertEqual(cc_patched.call_count, 1)
+        self.assertEqual(response.content, b'OK')
+
 
 class LcSortedTest(TestCase):
 
diff --git a/common/views.py b/common/views.py
index 3b2100b..0e2bd57 100644
--- a/common/views.py
+++ b/common/views.py
@@ -1,7 +1,10 @@
+from pathlib import Path
+
 from django.conf import settings
 from django.contrib.auth import login, authenticate
 from django.contrib import messages
-from django.http import HttpResponseRedirect, Http404
+from django.core.management import call_command
+from django.http import HttpResponse, HttpResponseForbidden, HttpResponseRedirect, Http404
 from django.shortcuts import render
 from django.template.loader import get_template, TemplateDoesNotExist
 from django.urls import reverse
@@ -11,7 +14,7 @@ from django.utils.translation import ugettext as _
 from people.models import Person, obfuscate_email
 from teams.models import Role
 from people.forms import LoginForm, RegistrationForm
-from common.utils import get_user_locale
+from .utils import get_user_locale, run_shell_command
 
 
 def index(request):
@@ -115,3 +118,19 @@ def help(request, topic, modal):
     return render(request, template, {
         'base': 'base_modal.html' if modal and int(modal) else 'base.html'
     })
+
+
+def pull_code(request):
+    """GitLab Webhok endpoint to update code after a repository push."""
+    verified = (
+        request.method == 'POST' and
+        request.META.get('HTTP_X_GITLAB_EVENT') == 'Push Hook' and
+        request.META.get('HTTP_X_GITLAB_TOKEN') == settings.GITLAB_TOKEN
+    )
+    if not verified:
+        return HttpResponseForbidden()
+
+    run_shell_command(['git', 'pull', '--rebase'])
+    call_command('compile-trans', verbosity=0)
+    run_shell_command(['touch', 'wsgi.py'], cwd=Path(settings.BASE_DIR) / 'damnedlies')
+    return HttpResponse('OK')
diff --git a/damnedlies/settings.py b/damnedlies/settings.py
index 61bb81b..b6c3355 100644
--- a/damnedlies/settings.py
+++ b/damnedlies/settings.py
@@ -171,6 +171,8 @@ GETTEXT_ITS_DATA = {
     ],
 }
 
+GITLAB_TOKEN = 'fill_with_real_token'
+
 try:
     from .local_settings import *
 except ImportError:
diff --git a/damnedlies/urls.py b/damnedlies/urls.py
index 7943ef8..e24bdf3 100644
--- a/damnedlies/urls.py
+++ b/damnedlies/urls.py
@@ -50,6 +50,9 @@ urlpatterns = [
         auth_views.password_reset_complete,
         name='password_reset_complete'),
 
+    # Webhook endpoint
+    url(r'^pull_code/$', common_views.pull_code),
+
     url(r'^teams/', include('teams.urls')),
     url(r'^people/', include('people.urls')),
     url(# users is the hardcoded url in the contrib.auth User class, making it identical to /people


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]