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

Bug#753910: [PATCH] Add support for showing Debci test failures as an action item. Closes: #753910



From: Andrew Starr-Bochicchio <asb@debian.org>

---
 distro_tracker/vendor/debian/models.py             | 13 +++
 .../debian/templates/debian/debci-action-item.html | 10 +++
 distro_tracker/vendor/debian/tracker_tasks.py      | 93 ++++++++++++++++++++++
 3 files changed, 116 insertions(+)
 create mode 100644 distro_tracker/vendor/debian/templates/debian/debci-action-item.html

diff --git a/distro_tracker/vendor/debian/models.py b/distro_tracker/vendor/debian/models.py
index b671db2..720d4ac 100644
--- a/distro_tracker/vendor/debian/models.py
+++ b/distro_tracker/vendor/debian/models.py
@@ -129,3 +129,16 @@ class UbuntuPackage(models.Model):
 
     def __str__(self):
         return "Ubuntu package info for {pkg}".format(pkg=self.package)
+
+
+@python_2_unicode_compatible
+class DebciStatus(models.Model):
+    """
+    Model for debci status of packages.
+    """
+    package = models.OneToOneField(PackageName, related_name='debci_status')
+    status = JSONField()
+
+    def __str__(self):
+        return 'Debci status for package {package}'.format(
+            package=self.package)
diff --git a/distro_tracker/vendor/debian/templates/debian/debci-action-item.html b/distro_tracker/vendor/debian/templates/debian/debci-action-item.html
new file mode 100644
index 0000000..7142e9f
--- /dev/null
+++ b/distro_tracker/vendor/debian/templates/debian/debci-action-item.html
@@ -0,0 +1,10 @@
+{% with duration=item.extra_data.duration %}
+{% with previous_status=item.extra_data.previous_status %}
+{% with date=item.extra_data.date %}
+<p><a href="http://ci.debian.net/";>Debci</a> reports
+<a href="{{ item.extra_data.url }}"> test failures </a> for this package
+(<a href="{{ item.extra_data.log }}">log</a>).</p>
+<p>The tests ran in {{duration}}</p>
+<p>Last run: {{date}}</p>
+<p>Previous status: <b>{{previous_status}}</b></p>
+{% endwith %}{% endwith %}{% endwith %}
diff --git a/distro_tracker/vendor/debian/tracker_tasks.py b/distro_tracker/vendor/debian/tracker_tasks.py
index 0ea38d9..5980626 100644
--- a/distro_tracker/vendor/debian/tracker_tasks.py
+++ b/distro_tracker/vendor/debian/tracker_tasks.py
@@ -35,6 +35,7 @@ from distro_tracker.vendor.debian.models import BuildLogCheckStats
 from distro_tracker.vendor.debian.models import PackageTransition
 from distro_tracker.vendor.debian.models import PackageExcuses
 from distro_tracker.vendor.debian.models import UbuntuPackage
+from distro_tracker.vendor.debian.models import DebciStatus
 from distro_tracker.core.utils.http import HttpCache
 from distro_tracker.core.utils.http import get_resource_content
 from .models import DebianContributor
@@ -43,6 +44,7 @@ from distro_tracker import vendor
 import re
 import SOAPpy
 import yaml
+import json
 from debian import deb822
 from debian.debian_support import AptPkgVersion
 from debian import debian_support
@@ -1938,3 +1940,94 @@ class UpdateNewQueuePackages(BaseTask):
                 })
 
             new_queue_info.save()
+
+
+class UpdateDebciStatusTask(BaseTask):
+    """
+    Updates packages' debci status.
+    """
+    ACTION_ITEM_TYPE_NAME = 'debci-failed-tests'
+    ITEM_DESCRIPTION = 'Debci reports <a href="{debci_url}"> failed tests</a> \
+        (<a href="{log_url}">log</a>)'
+    ITEM_FULL_DESCRIPTION_TEMPLATE = 'debian/debci-action-item.html'
+
+    def __init__(self, force_update=False, *args, **kwargs):
+        super(UpdateDebciStatusTask, self).__init__(*args, **kwargs)
+        self.force_update = force_update
+        self.debci_action_item_type = ActionItemType.objects.create_or_update(
+            type_name=self.ACTION_ITEM_TYPE_NAME,
+            full_description_template=self.ITEM_FULL_DESCRIPTION_TEMPLATE)
+
+    def set_parameters(self, parameters):
+        if 'force_update' in parameters:
+            self.force_update = parameters['force_update']
+
+    def get_debci_status(self):
+        url = 'http://ci.debian.net/data/status/unstable/amd64/packages.json'
+        cache = HttpCache(settings.DISTRO_TRACKER_CACHE_DIRECTORY)
+        response, updated = cache.update(url, force=self.force_update)
+        response.raise_for_status()
+        if not updated:
+            return
+        debci_status = json.loads(response.text)
+        return debci_status
+
+    def update_action_item(self, package, debci_status):
+        """
+        Updates the :class:`ActionItem` for the given package based on the
+        :class:`DebciStatus <distro_tracker.vendor.debian.models.DebciStatus`
+        If the package has test failures an :class:`ActionItem` is created.
+        """
+        debci_action_item = package.get_action_item_for_type(
+            self.debci_action_item_type.type_name)
+        if debci_status.get('status') == 'pass':
+            debci_action_item.delete()
+            return
+
+        if debci_action_item is None:
+            debci_action_item = ActionItem(
+                package=package,
+                item_type=self.debci_action_item_type)
+
+        package_name = debci_status.get('package')
+        url = 'http://ci.debian.net/#package/' + package_name
+        log = 'http://ci.debian.net/data/packages/unstable/amd64/' + \
+            package_name[:1] + "/" + package_name + '/latest-autopkgtest/log'
+        debci_action_item.short_description = self.ITEM_DESCRIPTION.format(
+            debci_url=url,
+            log_url=log)
+
+        debci_action_item.extra_data = {
+            'duration': debci_status.get('duration_human'),
+            'previous_status': debci_status.get('previous_status'),
+            'date': debci_status.get('date'),
+            'url': url,
+            'log': log,
+        }
+
+        debci_action_item.save()
+
+    def execute(self):
+        all_debci_status = self.get_debci_status()
+        if not all_debci_status:
+            return
+
+        # Discard all old
+        DebciStatus.objects.all().delete()
+
+        failures = []
+        packages = []
+        for result in all_debci_status:
+            if result['status'] == 'fail':
+                package = PackageName.objects.get(name=result['package'])
+                debci_status = DebciStatus(package=package,
+                                           status=result)
+                failures.append(debci_status)
+                packages.append(package)
+                self.update_action_item(package, result)
+
+        # Remove action items for packages without failing tests.
+        ActionItem.objects.delete_obsolete_items(
+            [self.debci_action_item_type], packages)
+
+        DebciStatus.objects.bulk_create(failures)
-- 
1.9.1


Reply to: