Repository: fedora-infra/bodhi

Issue:
updated_date on updateinfo is changed constantly, without any changes to the errata
Referred here by: https://pagure.io/releng/issue/10051#comment-719399

It appears that the "updated_date" fields on errata / advisories / updateinfo is updated daily, even without any changes to the actual metadata or package lists. This causes problems for repository management tools such as Pulp, which sees that the "updated_date" has changed, and that therefore the repository has changed, and that therefore the repository metadata needs to be regenerated each time (unnecessarily).

"updated_date" should preferably only be changed when the advisory itself has been updated. Changing it daily without changing the advisory, devalues its usefulness as a component of the metadata.

It would be very difficult to simply ignore "updated_date" because we semi-frequently encounter errata that were updated without changing the "version" metadata appropriately - and it becomes deeply problematic to work with updateinfo / errata / advisories if neither of these fields can be relied upon.

This seems to be true of both EPEL and Fedora.  This issue was reported to us by a user and filed in our issue here: https://pulp.plan.io/issues/8229

EPEL is more of a concern to us simply due to the number of Pulp / Katello / Satellite users who want to manage EPEL content. 


Discussion:

Resolving patch:
diff --git a/bodhi/server/metadata.py b/bodhi/server/metadata.py
--- a/bodhi/server/metadata.py
+++ b/bodhi/server/metadata.py
@@ -16,7 +16,6 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 """Create metadata files when composing repositories."""
-from datetime import datetime
 import logging
 import os
 import shelve
@@ -233,12 +232,13 @@ def add_update(self, update):
             # Sometimes we only set the date_pushed after it's pushed out, however,
             # it seems that Satellite does not like update entries without issued_date.
             # Since we know that we are pushing it now, and the next push will get the data
-            # correctly, let's just insert utcnow().
-            rec.issued_date = datetime.utcnow()
+            # correctly, let's just insert "date submitted".
+            rec.issued_date = update.date_submitted
         if update.date_modified:
             rec.updated_date = update.date_modified
         else:
-            rec.updated_date = datetime.utcnow()
+            # Likewise, if there is no date_modified, use date_submitted
+            rec.updated_date = update.date_submitted
 
         col = cr.UpdateCollection()
         col.name = update.release.long_name.encode('utf-8')


Test patch:
diff --git a/bodhi/tests/server/test_metadata.py b/bodhi/tests/server/test_metadata.py
--- a/bodhi/tests/server/test_metadata.py
+++ b/bodhi/tests/server/test_metadata.py
@@ -16,7 +16,7 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-from datetime import datetime, timedelta
+from datetime import datetime
 from hashlib import sha256
 from os.path import join, exists, basename
 from unittest import mock
@@ -125,38 +125,28 @@ def test_build_not_in_builds(self):
         assert pkg.filename == 'TurboGears-1.0.2.2-2.fc17.noarch.rpm'
 
     def test_date_modified_none(self):
-        """The metadata should use utcnow() if an update's date_modified is None."""
-        test_start_time = datetime.utcnow()
-        # The UpdateRecord's updated_date attribute strips microseconds, so let's force them to 0
-        # so our assertions at the end of this test will pass.
-        test_start_time = test_start_time - timedelta(microseconds=test_start_time.microsecond)
+        """The metadata should use date_submitted if an update's date_modified is None."""
         update = self.db.query(Update).one()
         update.date_modified = None
         md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                 close_shelf=False)
-
         md.add_update(update)
-
         md.shelf.close()
+
         assert len(md.uinfo.updates) == 1
-        assert test_start_time <= md.uinfo.updates[0].updated_date <= datetime.utcnow()
+        assert md.uinfo.updates[0].updated_date == update.date_submitted
 
     def test_date_pushed_none(self):
-        """The metadata should use utcnow() if an update's date_pushed is None."""
-        test_start_time = datetime.utcnow()
-        # The UpdateRecord's updated_date attribute strips microseconds, so let's force them to 0
-        # so our assertions at the end of this test will pass.
-        test_start_time = test_start_time - timedelta(microseconds=test_start_time.microsecond)
+        """The metadata should use date_submitted if an update's date_pushed is None."""
         update = self.db.query(Update).one()
         update.date_pushed = None
         md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                 close_shelf=False)
-
         md.add_update(update)
-
         md.shelf.close()
+
         assert len(md.uinfo.updates) == 1
-        assert test_start_time <= md.uinfo.updates[0].issued_date <= datetime.utcnow()
+        assert md.uinfo.updates[0].issued_date == update.date_submitted
 
     def test_rpm_with_arch(self):
         """Ensure that an RPM with a non 386 arch gets handled correctly."""