[damned-lies] Create a new webhook API endpoint to rebuild moduel branches after commits



commit 79aed38ed68ffb19797990f0bc46a965bed2e2a1
Author: Claude Paroz <claude 2xlibre net>
Date:   Wed Sep 11 13:27:28 2019 +0200

    Create a new webhook API endpoint to rebuild moduel branches after commits

 api/urls.py     |  3 +++
 api/views.py    | 32 ++++++++++++++++++++++++++++++--
 common/utils.py |  8 ++++++++
 common/views.py | 10 +++-------
 4 files changed, 44 insertions(+), 9 deletions(-)
---
diff --git a/api/urls.py b/api/urls.py
index fba4dfb8..8bd27070 100644
--- a/api/urls.py
+++ b/api/urls.py
@@ -20,4 +20,7 @@ urlpatterns = [
         views.ModuleLangStatsView.as_view(),
         name='api-module-lang-stats'
     ),
+    # Used by a GitLab webhook to signal a commit for that module/branch
+    path('modules/<name:module_name>/branches/<name:branch_name>/ping', views.rebuild_branch,
+        name='api-module-rebuild'),
 ]
diff --git a/api/views.py b/api/views.py
index 84a3719e..c99c3bea 100644
--- a/api/views.py
+++ b/api/views.py
@@ -1,10 +1,16 @@
-from django.http import Http404, JsonResponse
+import traceback
+from threading import Thread
+
+from django.core.mail import mail_admins
+from django.http import Http404, HttpResponseForbidden, JsonResponse
 from django.shortcuts import get_object_or_404
 from django.urls import reverse
+from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import View
 
+from common.utils import check_gitlab_request
 from languages.models import Language
-from stats.models import Module, Release
+from stats.models import Branch, Module, Release
 from teams.models import Team
 from vertimus.views import get_vertimus_state
 
@@ -199,6 +205,28 @@ class ModuleLangStatsView(View):
         })
 
 
+# CSRF skipped, verification using a secret token.
+@csrf_exempt
+def rebuild_branch(request, module_name, branch_name):
+    verified = check_gitlab_request(request)
+    if not verified:
+        return HttpResponseForbidden()
+
+    branch = get_object_or_404(Branch, module__name=module_name, name=branch_name)
+    # Run effective work in a separate thread to prevent timeouts
+    thread = Thread(target=rebuild_branch_real, args=(branch,))
+    thread.start()
+    return JsonResponse({'result': 'OK'})
+
+
+def rebuild_branch_real(branch):
+    try:
+        branch.update_stats(force=False)
+    except Exception as exc:
+        tbtext = traceback.format_exc()
+        mail_admins("Error while updating %s %s" % (branch.module.name, branch.name), tbtext)
+
+
 def serialize_instance(instance, field_names):
     data = {}
     for field in field_names:
diff --git a/common/utils.py b/common/utils.py
index 157c1079..2355040b 100644
--- a/common/utils.py
+++ b/common/utils.py
@@ -93,3 +93,11 @@ def send_mail(subject, message, **kwargs):
     if not subject.startswith(settings.EMAIL_SUBJECT_PREFIX):
         subject = '%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject)
     EmailMessage(subject, message, **kwargs).send()
+
+
+def check_gitlab_request(request):
+    return (
+        request.method == 'POST' and
+        request.META.get('HTTP_X_GITLAB_EVENT') == 'Push Hook' and
+        request.META.get('HTTP_X_GITLAB_TOKEN') == settings.GITLAB_TOKEN
+    )
diff --git a/common/views.py b/common/views.py
index 84236356..3bda4e1b 100644
--- a/common/views.py
+++ b/common/views.py
@@ -15,7 +15,7 @@ from django.views.decorators.csrf import csrf_exempt
 from people.models import Person, obfuscate_email
 from teams.models import Role
 from people.forms import LoginForm, RegistrationForm
-from .utils import get_user_locale, run_shell_command
+from .utils import check_gitlab_request, get_user_locale, run_shell_command
 
 
 def index(request):
@@ -113,12 +113,8 @@ def help(request, topic, modal):
 # CSRF skipped, verification using a secret token.
 @csrf_exempt
 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
-    )
+    """GitLab Webhook endpoint to update code after a repository push."""
+    verified = check_gitlab_request(request)
     if not verified:
         return HttpResponseForbidden()
 


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