pungi: add patches for making the output reproducible
This commit is contained in:
parent
45c201932b
commit
94ccc1a19a
@ -0,0 +1,45 @@
|
|||||||
|
From 1b0ff7f98bdce87deb7bc61d6c227be21fa43a94 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
|
||||||
|
<marmarek@invisiblethingslab.com>
|
||||||
|
Date: Thu, 4 Oct 2018 23:36:15 +0200
|
||||||
|
Subject: [PATCH 1/6] Use $SOURCE_DATE_EPOCH (if set) in discinfo file
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
Organization: Invisible Things Lab
|
||||||
|
Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
|
||||||
|
This helps the output image to be reproducible.
|
||||||
|
|
||||||
|
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
---
|
||||||
|
pungi/compose_metadata/discinfo.py | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/pungi/compose_metadata/discinfo.py b/pungi/compose_metadata/discinfo.py
|
||||||
|
index df61ca0..758feef 100644
|
||||||
|
--- a/pungi/compose_metadata/discinfo.py
|
||||||
|
+++ b/pungi/compose_metadata/discinfo.py
|
||||||
|
@@ -32,6 +32,7 @@ __all__ = (
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
+import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
@@ -43,7 +44,10 @@ def write_discinfo(file_path, description, arch, disc_numbers=None, timestamp=No
|
||||||
|
if not isinstance(disc_numbers, list):
|
||||||
|
raise TypeError("Invalid type: disc_numbers type is %s; expected: <list>" % type(disc_numbers))
|
||||||
|
if not timestamp:
|
||||||
|
- timestamp = "%f" % time.time()
|
||||||
|
+ if 'SOURCE_DATE_EPOCH' in os.environ:
|
||||||
|
+ timestamp = os.environ['SOURCE_DATE_EPOCH']
|
||||||
|
+ else:
|
||||||
|
+ timestamp = "%f" % time.time()
|
||||||
|
with open(file_path, "w") as f:
|
||||||
|
f.write("%s\n" % timestamp)
|
||||||
|
f.write("%s\n" % description)
|
||||||
|
--
|
||||||
|
2.17.1
|
||||||
|
|
49
pungi/0002-Use-xorriso-instead-of-genisoimage.patch
Normal file
49
pungi/0002-Use-xorriso-instead-of-genisoimage.patch
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
From d33b8f9995070d68472c25779dfa543d6d7535db Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
|
||||||
|
<marmarek@invisiblethingslab.com>
|
||||||
|
Date: Thu, 4 Oct 2018 23:37:35 +0200
|
||||||
|
Subject: [PATCH 2/6] Use xorriso instead of genisoimage
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
Organization: Invisible Things Lab
|
||||||
|
Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
|
||||||
|
xorriso make the image reproducible (given the same input files),
|
||||||
|
including support for SOURCE_DATE_EPOCH in various metadata.
|
||||||
|
|
||||||
|
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
---
|
||||||
|
pungi.spec | 2 +-
|
||||||
|
pungi/gather.py | 2 +-
|
||||||
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pungi.spec b/pungi.spec
|
||||||
|
index 6a23a63..d7bdc66 100644
|
||||||
|
--- a/pungi.spec
|
||||||
|
+++ b/pungi.spec
|
||||||
|
@@ -35,7 +35,7 @@ Requires: jigdo
|
||||||
|
Requires: cvs
|
||||||
|
Requires: yum-utils
|
||||||
|
Requires: isomd5sum
|
||||||
|
-Requires: genisoimage
|
||||||
|
+Requires: xorriso
|
||||||
|
Requires: gettext
|
||||||
|
Requires: syslinux
|
||||||
|
Requires: git
|
||||||
|
diff --git a/pungi/gather.py b/pungi/gather.py
|
||||||
|
index 20cc33d..15dfcee 100644
|
||||||
|
--- a/pungi/gather.py
|
||||||
|
+++ b/pungi/gather.py
|
||||||
|
@@ -1709,7 +1709,7 @@ class Pungi(PungiBase):
|
||||||
|
clean=True) # This is risky...
|
||||||
|
|
||||||
|
# setup the base command
|
||||||
|
- mkisofs = ['/usr/bin/mkisofs']
|
||||||
|
+ mkisofs = ['/usr/bin/xorriso', '-as', 'mkisofs']
|
||||||
|
mkisofs.extend(['-v', '-U', '-J', '-R', '-T', '-m', 'repoview', '-m', 'boot.iso']) # common mkisofs flags
|
||||||
|
|
||||||
|
x86bootargs = ['-b', 'isolinux/isolinux.bin', '-c', 'isolinux/boot.cat',
|
||||||
|
--
|
||||||
|
2.17.1
|
||||||
|
|
34
pungi/0003-Use-constant-MBR-ID-for-isohybrid.patch
Normal file
34
pungi/0003-Use-constant-MBR-ID-for-isohybrid.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
From 61ed5d6ea5b1beedb59b3962d0df99f0b3c69402 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
|
||||||
|
<marmarek@invisiblethingslab.com>
|
||||||
|
Date: Thu, 4 Oct 2018 23:38:57 +0200
|
||||||
|
Subject: [PATCH 3/6] Use constant MBR ID for isohybrid
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
Organization: Invisible Things Lab
|
||||||
|
Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
|
||||||
|
If not set explicitly, isohybrid choose it randomly, which harm
|
||||||
|
reproducibility.
|
||||||
|
|
||||||
|
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
---
|
||||||
|
pungi/gather.py | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/pungi/gather.py b/pungi/gather.py
|
||||||
|
index 15dfcee..6f52bc6 100644
|
||||||
|
--- a/pungi/gather.py
|
||||||
|
+++ b/pungi/gather.py
|
||||||
|
@@ -1731,6 +1731,7 @@ class Pungi(PungiBase):
|
||||||
|
ppcbootargs.append('-hfs-bless') # must be last
|
||||||
|
|
||||||
|
isohybrid = ['/usr/bin/isohybrid']
|
||||||
|
+ isohybrid.extend(['--id', '42'])
|
||||||
|
|
||||||
|
# Check the size of the tree
|
||||||
|
# This size checking method may be bunk, accepting patches...
|
||||||
|
--
|
||||||
|
2.17.1
|
||||||
|
|
67
pungi/0004-Make-sure-.treeinfo-file-is-sorted.patch
Normal file
67
pungi/0004-Make-sure-.treeinfo-file-is-sorted.patch
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
From 57e49f366a34e3d8fdb020d7f19bc2fec8547ec9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
|
||||||
|
<marmarek@invisiblethingslab.com>
|
||||||
|
Date: Thu, 4 Oct 2018 23:42:19 +0200
|
||||||
|
Subject: [PATCH 4/6] Make sure .treeinfo file is sorted
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
Organization: Invisible Things Lab
|
||||||
|
Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
|
||||||
|
OrderedDict used by default by ConfigParser isn't enough because order
|
||||||
|
of entries being added may not be deterministic (depends on directory
|
||||||
|
list order). To solve this problem, use SortedDict as a base.
|
||||||
|
|
||||||
|
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
---
|
||||||
|
pungi.spec | 2 ++
|
||||||
|
pungi/gather.py | 5 +++++
|
||||||
|
2 files changed, 7 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/pungi.spec b/pungi.spec
|
||||||
|
index d7bdc66..dcb1986 100644
|
||||||
|
--- a/pungi.spec
|
||||||
|
+++ b/pungi.spec
|
||||||
|
@@ -17,6 +17,7 @@ BuildRequires: python-jsonschema
|
||||||
|
BuildRequires: python-enum34
|
||||||
|
BuildRequires: python2-dnf
|
||||||
|
BuildRequires: python2-multilib
|
||||||
|
+BuildRequires: python2-dict-sorted
|
||||||
|
|
||||||
|
Requires: createrepo >= 0.4.11
|
||||||
|
Requires: yum => 3.4.3-28
|
||||||
|
@@ -44,6 +45,7 @@ Requires: libguestfs-tools-c
|
||||||
|
Requires: python-enum34
|
||||||
|
Requires: python2-dnf
|
||||||
|
Requires: python2-multilib
|
||||||
|
+Requires: python2-dict-sorted
|
||||||
|
|
||||||
|
BuildArch: noarch
|
||||||
|
|
||||||
|
diff --git a/pungi/gather.py b/pungi/gather.py
|
||||||
|
index 6f52bc6..1035036 100644
|
||||||
|
--- a/pungi/gather.py
|
||||||
|
+++ b/pungi/gather.py
|
||||||
|
@@ -26,6 +26,7 @@ import urlgrabber.progress
|
||||||
|
import subprocess
|
||||||
|
import createrepo
|
||||||
|
import ConfigParser
|
||||||
|
+from sdict import AlphaSortedDict
|
||||||
|
from fnmatch import fnmatch
|
||||||
|
|
||||||
|
import arch as arch_module
|
||||||
|
@@ -95,6 +96,10 @@ def is_package(po):
|
||||||
|
class MyConfigParser(ConfigParser.ConfigParser):
|
||||||
|
"""A subclass of ConfigParser which does not lowercase options"""
|
||||||
|
|
||||||
|
+ def __init__(self, *args, **kwargs):
|
||||||
|
+ kwargs['dict_type'] = AlphaSortedDict
|
||||||
|
+ ConfigParser.ConfigParser.__init__(self, *args, **kwargs)
|
||||||
|
+
|
||||||
|
def optionxform(self, optionstr):
|
||||||
|
return optionstr
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.1
|
||||||
|
|
60
pungi/0005-Set-repodata-mtime-to-SOURCE_DATE_EPOCH.patch
Normal file
60
pungi/0005-Set-repodata-mtime-to-SOURCE_DATE_EPOCH.patch
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
From 8eaee0ada8caa8b509b96867b06b876ef606d64f Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
|
||||||
|
<marmarek@invisiblethingslab.com>
|
||||||
|
Date: Thu, 4 Oct 2018 23:44:06 +0200
|
||||||
|
Subject: [PATCH 5/6] Set repodata mtime to SOURCE_DATE_EPOCH
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
Organization: Invisible Things Lab
|
||||||
|
Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
|
||||||
|
repodata/repomd.xml include timestamps of all the other repodata files.
|
||||||
|
Even when those files are created reproducibly, they have current
|
||||||
|
modification time. In general case this is a good thing (ease checking
|
||||||
|
if repodata cache is up to date). But in case of composing installation
|
||||||
|
image, it breaks reproducibility.
|
||||||
|
Avoid this by reseting mtime of repodata/* to $SOURCE_DATE_EPOCH, just
|
||||||
|
before creating repomd.xml.
|
||||||
|
|
||||||
|
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
---
|
||||||
|
pungi/gather.py | 12 ++++++++++++
|
||||||
|
1 file changed, 12 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/pungi/gather.py b/pungi/gather.py
|
||||||
|
index 1035036..dbe38f7 100644
|
||||||
|
--- a/pungi/gather.py
|
||||||
|
+++ b/pungi/gather.py
|
||||||
|
@@ -25,6 +25,7 @@ import logging
|
||||||
|
import urlgrabber.progress
|
||||||
|
import subprocess
|
||||||
|
import createrepo
|
||||||
|
+import glob
|
||||||
|
import ConfigParser
|
||||||
|
from sdict import AlphaSortedDict
|
||||||
|
from fnmatch import fnmatch
|
||||||
|
@@ -1409,9 +1410,20 @@ class Pungi(PungiBase):
|
||||||
|
conf.baseurl = baseurl
|
||||||
|
if compress_type:
|
||||||
|
conf.compress_type = compress_type
|
||||||
|
+ if 'SOURCE_DATE_EPOCH' in os.environ:
|
||||||
|
+ conf.revision = os.environ['SOURCE_DATE_EPOCH']
|
||||||
|
repomatic = createrepo.MetaDataGenerator(conf)
|
||||||
|
self.logger.info('Making repodata')
|
||||||
|
repomatic.doPkgMetadata()
|
||||||
|
+
|
||||||
|
+ # set mtime to $SOURCE_DATE_EPOCH, do that just before creating
|
||||||
|
+ # repomd.xml, because it includes timestamps of referenced files
|
||||||
|
+ if 'SOURCE_DATE_EPOCH' in os.environ:
|
||||||
|
+ s_d_e = int(os.environ['SOURCE_DATE_EPOCH'])
|
||||||
|
+ for repo_file in glob.glob(
|
||||||
|
+ os.path.join(conf.outputdir, conf.tempdir, "*")):
|
||||||
|
+ os.utime(repo_file, (s_d_e, s_d_e))
|
||||||
|
+
|
||||||
|
repomatic.doRepoMetadata()
|
||||||
|
repomatic.doFinalMove()
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.1
|
||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
From aaae0547c9bfefac7aa0d431cc4065eb369a7605 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
|
||||||
|
<marmarek@invisiblethingslab.com>
|
||||||
|
Date: Fri, 5 Oct 2018 15:26:36 +0200
|
||||||
|
Subject: [PATCH 6/6] Monkey patch createrepo to clamp repodata mtime
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
Organization: Invisible Things Lab
|
||||||
|
Cc: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
|
||||||
|
Unfortunately some files are created during repomatic.doRepoMetadata(),
|
||||||
|
so clamping mtime before the call isn't enough. To limit changes to just
|
||||||
|
one component, monkey patch createrepo function.
|
||||||
|
|
||||||
|
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
|
||||||
|
---
|
||||||
|
pungi/gather.py | 19 +++++++++++++++++++
|
||||||
|
1 file changed, 19 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/pungi/gather.py b/pungi/gather.py
|
||||||
|
index dbe38f7..9963dc6 100644
|
||||||
|
--- a/pungi/gather.py
|
||||||
|
+++ b/pungi/gather.py
|
||||||
|
@@ -1424,6 +1424,25 @@ class Pungi(PungiBase):
|
||||||
|
os.path.join(conf.outputdir, conf.tempdir, "*")):
|
||||||
|
os.utime(repo_file, (s_d_e, s_d_e))
|
||||||
|
|
||||||
|
+ # unfortunately the above is not enough, because some files are created
|
||||||
|
+ # during doRepoMetadata(). This include:
|
||||||
|
+ # - compressed sqlite versions of the metadata - needed by repoview
|
||||||
|
+ # - group file (compressed and not) - this is needed, so the timestamp
|
||||||
|
+ # problem needs to be solved anyway
|
||||||
|
+ orig_createRepoDataObject = repomatic._createRepoDataObject
|
||||||
|
+ def wrapped_createRepoDataObject(*args, **kwargs):
|
||||||
|
+ repodata = orig_createRepoDataObject(*args, **kwargs)
|
||||||
|
+ if int(repodata.timestamp) > s_d_e:
|
||||||
|
+ repodata.timestamp = str(s_d_e)
|
||||||
|
+ return repodata
|
||||||
|
+ repomatic._createRepoDataObject = wrapped_createRepoDataObject
|
||||||
|
+
|
||||||
|
+ orig_compressFile = createrepo.utils.compressFile
|
||||||
|
+ def wrapped_compressFile(source, dest, compress_type):
|
||||||
|
+ orig_compressFile(source, dest, compress_type)
|
||||||
|
+ os.utime(dest, (s_d_e, s_d_e))
|
||||||
|
+ createrepo.utils.compressFile = wrapped_compressFile
|
||||||
|
+
|
||||||
|
repomatic.doRepoMetadata()
|
||||||
|
repomatic.doFinalMove()
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.1
|
||||||
|
|
@ -14,6 +14,13 @@ Patch3: disable-efi.patch
|
|||||||
Patch4: Hacky-way-to-pass-gpgkey-to-lorax.patch
|
Patch4: Hacky-way-to-pass-gpgkey-to-lorax.patch
|
||||||
#Patch5: fix-recursive-partition-table-on-iso-image.patch
|
#Patch5: fix-recursive-partition-table-on-iso-image.patch
|
||||||
#Patch6: disable-upgrade.patch
|
#Patch6: disable-upgrade.patch
|
||||||
|
Patch7: 0001-Use-SOURCE_DATE_EPOCH-if-set-in-discinfo-file.patch
|
||||||
|
Patch8: 0002-Use-xorriso-instead-of-genisoimage.patch
|
||||||
|
Patch9: 0003-Use-constant-MBR-ID-for-isohybrid.patch
|
||||||
|
Patch10: 0004-Make-sure-.treeinfo-file-is-sorted.patch
|
||||||
|
Patch11: 0005-Set-repodata-mtime-to-SOURCE_DATE_EPOCH.patch
|
||||||
|
Patch12: 0006-Monkey-patch-createrepo-to-clamp-repodata-mtime.patch
|
||||||
|
|
||||||
BuildRequires: python-nose, python-mock
|
BuildRequires: python-nose, python-mock
|
||||||
BuildRequires: python-devel, python-setuptools, python2-productmd >= 1.3
|
BuildRequires: python-devel, python-setuptools, python2-productmd >= 1.3
|
||||||
BuildRequires: python-lockfile, kobo, kobo-rpmlib, python-kickstart, createrepo_c
|
BuildRequires: python-lockfile, kobo, kobo-rpmlib, python-kickstart, createrepo_c
|
||||||
@ -24,6 +31,7 @@ BuildRequires: python-jsonschema
|
|||||||
BuildRequires: python-enum34
|
BuildRequires: python-enum34
|
||||||
BuildRequires: python2-dnf
|
BuildRequires: python2-dnf
|
||||||
BuildRequires: python2-multilib
|
BuildRequires: python2-multilib
|
||||||
|
BuildRequires: python2-dict-sorted
|
||||||
|
|
||||||
#deps for doc building
|
#deps for doc building
|
||||||
BuildRequires: python-sphinx, texlive-latex-bin-bin, texlive-collection-fontsrecommended
|
BuildRequires: python-sphinx, texlive-latex-bin-bin, texlive-collection-fontsrecommended
|
||||||
@ -52,7 +60,7 @@ Requires: koji >= 1.10.1-13
|
|||||||
Requires: cvs
|
Requires: cvs
|
||||||
Requires: yum-utils
|
Requires: yum-utils
|
||||||
Requires: isomd5sum
|
Requires: isomd5sum
|
||||||
Requires: genisoimage
|
Requires: xorriso
|
||||||
Requires: gettext
|
Requires: gettext
|
||||||
# this is x86 only
|
# this is x86 only
|
||||||
#Requires: syslinux
|
#Requires: syslinux
|
||||||
@ -61,6 +69,7 @@ Requires: python-jsonschema
|
|||||||
Requires: python-enum34
|
Requires: python-enum34
|
||||||
Requires: python2-dnf
|
Requires: python2-dnf
|
||||||
Requires: python2-multilib
|
Requires: python2-multilib
|
||||||
|
Requires: python2-dict-sorted
|
||||||
|
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
|
|
||||||
@ -86,6 +95,12 @@ notification to Fedora Message Bus.
|
|||||||
%patch4 -p1
|
%patch4 -p1
|
||||||
#%%patch5 -p1
|
#%%patch5 -p1
|
||||||
#%%patch6 -p1
|
#%%patch6 -p1
|
||||||
|
%patch7 -p1
|
||||||
|
%patch8 -p1
|
||||||
|
%patch9 -p1
|
||||||
|
%patch10 -p1
|
||||||
|
%patch11 -p1
|
||||||
|
%patch12 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%{__python} setup.py build
|
%{__python} setup.py build
|
||||||
|
Loading…
Reference in New Issue
Block a user