[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



On Mon, Jul 7, 2014 at 10:36 AM, Raphael Hertzog <hertzog@debian.org> wrote:
>> > On Sun, 06 Jul 2014, Andrew Starr-Bochicchio wrote:
>> >> +@python_2_unicode_compatible
>> >> +class DebciStatus(models.Model):
>> >> +    """
>> >> +    Model for debci status of packages.
>> >> +    """
>> >> +    package = models.OneToOneField(PackageName, related_name='debci_status')
>> >> +    status = JSONField()
>> >
>> > Please don't add a new model for this. Rather use a new "key" in
>> > PackageExtractedInfo.
>> >
>> > PackageExtractedInfo model should probably be renamed into something else
>> > but it's the better place to store this as we can then query most of the
>> > relevant information for a single package in a single query...
>>
>> Right. After I sent this off, I wondered if it needs to store this
>> information at all. Is enough to just store the information in the
>> action item?
>
> Possibly, yes. It really depends on whether you expect other parts of the
> package tracker to build upon this information or not.
>
> But we can always move it to a more appropriate place later on if we
> we have something that needs this information.

I went ahead and dropped it for now. It's all just stored in the
ActionItem. Easy enough to add it if we need it.

Updated patch attached. This time with some tests added as well.

Thanks!

-- Andrew Starr-Bochicchio

   Ubuntu Developer <https://launchpad.net/~andrewsomething>
   Debian Developer <http://qa.debian.org/developer.php?login=asb>
   PGP/GPG Key ID: D53FDCB1
From 2d23d7110111ca0cf449c4465c88ba4d91d037c2 Mon Sep 17 00:00:00 2001
From: Andrew Starr-Bochicchio <a.starr.b@gmail.com>
Date: Mon, 7 Jul 2014 23:18:20 -0400
Subject: [PATCH] Add support for showing Debci test failures as an action
 item. Closes: #753910
To: 753910@bugs.debian.org

---
 .../debian/templates/debian/debci-action-item.html | 10 +++
 distro_tracker/vendor/debian/tests.py              | 86 +++++++++++++++++++++
 distro_tracker/vendor/debian/tracker_tasks.py      | 87 ++++++++++++++++++++++
 3 files changed, 183 insertions(+)
 create mode 100644 distro_tracker/vendor/debian/templates/debian/debci-action-item.html

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/tests.py b/distro_tracker/vendor/debian/tests.py
index cd9abce..ca456b8 100644
--- a/distro_tracker/vendor/debian/tests.py
+++ b/distro_tracker/vendor/debian/tests.py
@@ -60,6 +60,7 @@ from distro_tracker.vendor.debian.tracker_tasks import RetrieveDebianMaintainers
 from distro_tracker.vendor.debian.tracker_tasks import RetrieveLowThresholdNmuTask
 from distro_tracker.vendor.debian.tracker_tasks import DebianWatchFileScannerUpdate
 from distro_tracker.vendor.debian.tracker_tasks import UpdateExcusesTask
+from distro_tracker.vendor.debian.tracker_tasks import UpdateDebciStatusTask
 from distro_tracker.vendor.debian.models import DebianContributor
 from distro_tracker.vendor.debian.models import UbuntuPackage
 from distro_tracker.vendor.debian.tracker_tasks import UpdateLintianStatsTask
@@ -4496,3 +4497,88 @@ class DebianSsoLoginTests(TestCase):
         self.client.get('/')
 
         self.assert_no_user_logged_in()
+
+
+class UpdateDebciStatusTaskTest(TestCase):
+    """
+    Tests for the :class:`distro_tracker.vendor.debian.tracker_tasks.UpdateDebciStatusTask` task.
+    """
+    def setUp(self):
+        self.dummy_package = SourcePackageName.objects.create(name='dummy-package')
+        self.other_package = SourcePackageName.objects.create(name='other-package')
+
+    def run_task(self):
+        """
+        Runs the debci status update task.
+        """
+        task = UpdateDebciStatusTask()
+        task.execute()
+
+    @mock.patch('distro_tracker.core.utils.http.requests')
+    def test_debci_status(self, mock_requests):
+        """
+        Tests that an ActionItem isn't created for a psssing debici status.
+        """
+        json_data = """[
+            {
+                "run_id": "20140705_145427",
+                "package": "dummy-package",
+                "version": "1.0-1",
+                "date": "2014-07-05 14:55:57",
+                "status": "pass",
+                "blame": [ ],
+                "previous_status": "pass",
+                "duration_seconds": "91",
+                "duration_human": "0h 1m 31s",
+                "message": "All tests passed"
+            },
+            {
+                "run_id": "20140705_212616",
+                "package": "other-package",
+                "version": "2.0-2",
+                "date": "2014-07-05 21:34:22",
+                "status": "fail",
+                "blame": [ ],
+                "previous_status": "fail",
+                "duration_seconds": "488",
+                "duration_human": "0h 8m 8s",
+                "message": "Tests failed"
+            },
+            {
+                "run_id": "20140705_143518",
+                "package": "another-package",
+                "version": "3.0-3",
+                "date": "2014-07-05 17:33:08",
+                "status": "fail",
+                "blame": [ ],
+                "previous_status": "fail",
+                "duration_seconds": "222",
+                "duration_human": "0h 3m 42s",
+                "message": "Tests failed"
+            }]
+        """
+        set_mock_response(mock_requests, text=json_data)
+
+        # Sanity check: there are no action items and two packages to start
+        self.assertEqual(0, ActionItem.objects.count())
+        self.assertEqual(2, SourcePackageName.objects.count())
+
+        self.run_task()
+
+        # The ActionItem is only added for failed tests for known packages.
+        self.assertEqual(1, ActionItem.objects.count())
+        self.assertEqual(0, self.dummy_package.action_items.count())
+        self.assertEqual(1, self.other_package.action_items.count())
+
+        # Check that the ActionItem contains the correct contents.
+        action_item = self.other_package.action_items.all()[0]
+        url = "http://ci.debian.net/#package/other-package";
+        log = "http://ci.debian.net/data/packages/unstable/amd64/o/other-package/latest-autopkgtest/log";
+        desc = ('Debci reports <a href="{url}"> failed tests</a> (<a href="{log}">log</a>)'
+            ).format(url=url, log=log)
+        self.assertEqual(action_item.short_description, desc)
+        self.assertEqual(action_item.extra_data['duration'], "0h 8m 8s")
+        self.assertEqual(action_item.extra_data['previous_status'], "fail")
+        self.assertEqual(action_item.extra_data['date'], "2014-07-05 21:34:22")
+        self.assertEqual(action_item.extra_data['url'], url)
+        self.assertEqual(action_item.extra_data['log'], log)
diff --git a/distro_tracker/vendor/debian/tracker_tasks.py b/distro_tracker/vendor/debian/tracker_tasks.py
index 0ea38d9..da17041 100644
--- a/distro_tracker/vendor/debian/tracker_tasks.py
+++ b/distro_tracker/vendor/debian/tracker_tasks.py
@@ -43,6 +43,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 +1939,89 @@ 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
+
+        with transaction.atomic():
+            packages = []
+            for result in all_debci_status:
+                if result['status'] == 'fail':
+                    try:
+                        package = SourcePackageName.objects.get(name=result['package'])
+                        packages.append(package)
+                        self.update_action_item(package, result)
+                    except SourcePackageName.DoesNotExist:
+                        pass
+
+            # Remove action items for packages without failing tests.
+            ActionItem.objects.delete_obsolete_items(
+                [self.debci_action_item_type], packages)
-- 
1.9.1


Reply to: