New release 4.9.0

(cherry picked from commit 5fbdefc5fc784a2ee632dc093c587e490c33593c)
This commit is contained in:
Lubomír Sedlář 2025-02-14 11:40:19 +02:00 committed by Stepan Oksanichenko
parent e9b29c87d5
commit afa2617a73
4 changed files with 13 additions and 877 deletions

View File

@ -1,776 +0,0 @@
From 1f4935685308a57bfcb149b9384b2f5984692075 Mon Sep 17 00:00:00 2001
From: Adam Williamson <awilliam@redhat.com>
Date: Wed, 15 Jan 2025 11:00:33 -0800
Subject: [PATCH 2/2] Protect against decoding errors with subprocess text mode
All these are calling subprocess in 'text mode', where it will
try to decode stdout/stderr using the default encoding (utf-8
for us). If it doesn't decode, subprocess will raise an exception
and kobo doesn't handle it, it just passes it along to us, so
things blow up - see https://pagure.io/releng/issue/12474 . To
avoid this, let's set `errors="replace"`, which tells the decoder
to replace invalid data with ? characters. This way we should get
as much of the output as can be read, and no crashes.
We also replace `universal_newlines=True` with `text=True` as
the latter is shorter, clearer, and what Python 3 subprocess
wants us to use, it considers `universal_newlines` to just be
a backwards-compatibility thing - "The universal_newlines argument
is equivalent to text and is provided for backwards compatibility"
Signed-off-by: Adam Williamson <awilliam@redhat.com>
---
pungi/__init__.py | 5 ++-
pungi/notifier.py | 3 +-
pungi/ostree/tree.py | 6 ++-
pungi/phases/ostree_container.py | 2 +-
pungi/util.py | 11 ++++--
pungi/wrappers/iso.py | 8 ++--
pungi/wrappers/kojiwrapper.py | 11 ++++--
pungi/wrappers/scm.py | 3 +-
pungi_utils/patch_iso.py | 5 ++-
pungi_utils/unified_isos.py | 3 +-
tests/test_iso_wrapper.py | 6 ++-
tests/test_koji_wrapper.py | 66 +++++++++++++++++++++-----------
tests/test_notifier.py | 3 +-
tests/test_ostree_script.py | 6 ++-
tests/test_patch_iso.py | 2 +-
tests/test_unified_isos.py | 2 +-
tests/test_util.py | 60 +++++++++++++++++++----------
17 files changed, 132 insertions(+), 70 deletions(-)
diff --git a/pungi/__init__.py b/pungi/__init__.py
index d4a48dca..8b672a72 100644
--- a/pungi/__init__.py
+++ b/pungi/__init__.py
@@ -16,7 +16,8 @@ def get_full_version():
proc = subprocess.Popen(
["git", "--git-dir=%s/.git" % location, "describe", "--tags"],
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
output, _ = proc.communicate()
return re.sub(r"-1.fc\d\d?", "", output.strip().replace("pungi-", ""))
@@ -24,7 +25,7 @@ def get_full_version():
import subprocess
proc = subprocess.Popen(
- ["rpm", "-q", "pungi"], stdout=subprocess.PIPE, universal_newlines=True
+ ["rpm", "-q", "pungi"], stdout=subprocess.PIPE, text=True, errors="replace"
)
(output, err) = proc.communicate()
if not err:
diff --git a/pungi/notifier.py b/pungi/notifier.py
index bef2ae63..a42c6184 100644
--- a/pungi/notifier.py
+++ b/pungi/notifier.py
@@ -104,7 +104,8 @@ class PungiNotifier(object):
workdir=workdir,
return_stdout=False,
show_cmd=True,
- universal_newlines=True,
+ text=True,
+ errors="replace",
logfile=logfile,
)
if ret != 0:
diff --git a/pungi/ostree/tree.py b/pungi/ostree/tree.py
index 1ba138b3..5da6fd7a 100644
--- a/pungi/ostree/tree.py
+++ b/pungi/ostree/tree.py
@@ -64,7 +64,8 @@ class Tree(OSTree):
show_cmd=True,
stdout=True,
logfile=log_file,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
finally:
os.umask(oldumask)
@@ -77,7 +78,8 @@ class Tree(OSTree):
show_cmd=True,
stdout=True,
logfile=log_file,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
def _update_ref(self):
diff --git a/pungi/phases/ostree_container.py b/pungi/phases/ostree_container.py
index c0179620..b752d16c 100644
--- a/pungi/phases/ostree_container.py
+++ b/pungi/phases/ostree_container.py
@@ -139,7 +139,7 @@ class OSTreeContainerThread(WorkerThread):
"--version=%s" % version,
]
- _, runroot_script = shortcuts.run(cmd, universal_newlines=True)
+ _, runroot_script = shortcuts.run(cmd, text=True, errors="replace")
default_packages = ["ostree", "rpm-ostree", "selinux-policy-targeted"]
additional_packages = config.get("runroot_packages", [])
diff --git a/pungi/util.py b/pungi/util.py
index fccdb228..4cde13d6 100644
--- a/pungi/util.py
+++ b/pungi/util.py
@@ -652,7 +652,11 @@ def run_unmount_cmd(cmd, max_retries=10, path=None, logger=None):
"""
for i in range(max_retries):
proc = subprocess.Popen(
- cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True
+ cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ errors="replace",
)
out, err = proc.communicate()
if proc.returncode == 0:
@@ -674,7 +678,8 @@ def run_unmount_cmd(cmd, max_retries=10, path=None, logger=None):
c,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
out, _ = proc.communicate()
logger.debug(
@@ -879,7 +884,7 @@ def git_ls_remote(baseurl, ref, credential_helper=None):
if credential_helper:
cmd.extend(["-c", "credential.useHttpPath=true"])
cmd.extend(["-c", "credential.helper=%s" % credential_helper])
- return run(cmd + ["ls-remote", baseurl, ref], universal_newlines=True)
+ return run(cmd + ["ls-remote", baseurl, ref], text=True, errors="replace")
def get_tz_offset():
diff --git a/pungi/wrappers/iso.py b/pungi/wrappers/iso.py
index 5a2533f8..2ca7a8db 100644
--- a/pungi/wrappers/iso.py
+++ b/pungi/wrappers/iso.py
@@ -227,7 +227,7 @@ def get_checkisomd5_cmd(iso_path, just_print=False):
def get_checkisomd5_data(iso_path, logger=None):
cmd = get_checkisomd5_cmd(iso_path, just_print=True)
- retcode, output = run(cmd, universal_newlines=True)
+ retcode, output = run(cmd, text=True, errors="replace")
items = [line.strip().rsplit(":", 1) for line in output.splitlines()]
items = dict([(k, v.strip()) for k, v in items])
md5 = items.get(iso_path, "")
@@ -283,13 +283,13 @@ def get_manifest_cmd(iso_name, xorriso=False, output_file=None):
def get_volume_id(path, xorriso=False):
if xorriso:
cmd = ["xorriso", "-indev", path]
- retcode, output = run(cmd, universal_newlines=True)
+ retcode, output = run(cmd, text=True, errors="replace")
for line in output.splitlines():
if line.startswith("Volume id"):
return line.split("'")[1]
else:
cmd = ["isoinfo", "-d", "-i", path]
- retcode, output = run(cmd, universal_newlines=True)
+ retcode, output = run(cmd, text=True, errors="replace")
for line in output.splitlines():
line = line.strip()
@@ -500,7 +500,7 @@ def mount(image, logger=None, use_guestmount=True):
else:
env = {}
cmd = ["mount", "-o", "loop", image, mount_dir]
- ret, out = run(cmd, env=env, can_fail=True, universal_newlines=True)
+ ret, out = run(cmd, env=env, can_fail=True, text=True, errors="replace")
if ret != 0:
# The mount command failed, something is wrong.
# Log the output and raise an exception.
diff --git a/pungi/wrappers/kojiwrapper.py b/pungi/wrappers/kojiwrapper.py
index 83c878a6..fecce1e1 100644
--- a/pungi/wrappers/kojiwrapper.py
+++ b/pungi/wrappers/kojiwrapper.py
@@ -294,7 +294,8 @@ class KojiWrapper(object):
show_cmd=True,
env=env,
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
# Look for first line that contains only a number. This is the ID of
@@ -430,7 +431,7 @@ class KojiWrapper(object):
while True:
retcode, output = run(
- cmd, can_fail=True, logfile=logfile, universal_newlines=True
+ cmd, can_fail=True, logfile=logfile, text=True, errors="replace"
)
if retcode == 0 or not (
@@ -463,7 +464,8 @@ class KojiWrapper(object):
logfile=log_file,
env=env,
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
match = re.search(r"Created task: (\d+)", output)
@@ -808,7 +810,8 @@ def get_buildroot_rpms(compose, task_id):
# local
retcode, output = run(
"rpm -qa --qf='%{name}-%{version}-%{release}.%{arch}\n'",
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
for i in output.splitlines():
if not i:
diff --git a/pungi/wrappers/scm.py b/pungi/wrappers/scm.py
index 9b4bc994..cfdd2907 100644
--- a/pungi/wrappers/scm.py
+++ b/pungi/wrappers/scm.py
@@ -56,7 +56,8 @@ class ScmBase(kobo.log.LoggingBase):
workdir=cwd,
can_fail=True,
stdin_data="",
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
if retcode != 0:
self.log_error("Output was: %r" % output)
diff --git a/pungi_utils/patch_iso.py b/pungi_utils/patch_iso.py
index 469736dd..13dddf58 100644
--- a/pungi_utils/patch_iso.py
+++ b/pungi_utils/patch_iso.py
@@ -25,7 +25,7 @@ from pungi.wrappers import iso
def sh(log, cmd, *args, **kwargs):
log.info("Running: %s", " ".join(shlex.quote(x) for x in cmd))
- ret, out = shortcuts.run(cmd, *args, universal_newlines=True, **kwargs)
+ ret, out = shortcuts.run(cmd, *args, text=True, errors="replace", **kwargs)
if out:
log.debug("%s", out)
return ret, out
@@ -35,7 +35,8 @@ def get_lorax_dir(default="/usr/share/lorax"):
try:
_, out = shortcuts.run(
["python3", "-c" "import pylorax; print(pylorax.find_templates())"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
return out.strip()
except Exception:
diff --git a/pungi_utils/unified_isos.py b/pungi_utils/unified_isos.py
index 517921b7..a692e3b0 100644
--- a/pungi_utils/unified_isos.py
+++ b/pungi_utils/unified_isos.py
@@ -394,7 +394,8 @@ class UnifiedISO(object):
iso.get_mkisofs_cmd(
iso_path, [source_dir], volid=volid, exclude=["./lost+found"]
),
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
# implant MD5
diff --git a/tests/test_iso_wrapper.py b/tests/test_iso_wrapper.py
index 28ea976e..c7770413 100644
--- a/tests/test_iso_wrapper.py
+++ b/tests/test_iso_wrapper.py
@@ -63,7 +63,8 @@ class TestIsoUtils(unittest.TestCase):
[
mock.call(
["/usr/bin/checkisomd5", "--md5sumonly", "dummy.iso"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -79,7 +80,8 @@ class TestIsoUtils(unittest.TestCase):
[
mock.call(
["/usr/bin/checkisomd5", "--md5sumonly", "dummy.iso"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
diff --git a/tests/test_koji_wrapper.py b/tests/test_koji_wrapper.py
index 9e0a5c17..e06d19c5 100644
--- a/tests/test_koji_wrapper.py
+++ b/tests/test_koji_wrapper.py
@@ -529,7 +529,8 @@ class RunrootKojiWrapperTest(KojiWrapperBaseTestCase):
buffer_size=-1,
logfile=None,
show_cmd=True,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -558,7 +559,8 @@ class RunrootKojiWrapperTest(KojiWrapperBaseTestCase):
buffer_size=-1,
logfile=None,
show_cmd=True,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -582,7 +584,8 @@ class RunrootKojiWrapperTest(KojiWrapperBaseTestCase):
buffer_size=-1,
logfile=None,
show_cmd=True,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -615,7 +618,8 @@ class RunrootKojiWrapperTest(KojiWrapperBaseTestCase):
buffer_size=-1,
logfile=None,
show_cmd=True,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -641,7 +645,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
show_cmd=True,
env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -671,7 +676,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
"PYTHONUNBUFFERED": "1",
},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -694,7 +700,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
logfile="logfile",
env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -717,7 +724,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
logfile=None,
env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -740,7 +748,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
logfile=None,
env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -765,13 +774,15 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
logfile=None,
env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["koji", "--profile=custom-koji", "watch-task", "1234"],
can_fail=True,
logfile=None,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
],
)
@@ -795,13 +806,15 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
logfile=None,
env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["koji", "--profile=custom-koji", "watch-task", "1234"],
can_fail=True,
logfile=None,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
],
)
@@ -826,25 +839,29 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
logfile=None,
env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["koji", "--profile=custom-koji", "watch-task", "1234"],
can_fail=True,
logfile=None,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["koji", "--profile=custom-koji", "watch-task", "1234"],
can_fail=True,
logfile=None,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["koji", "--profile=custom-koji", "watch-task", "1234"],
can_fail=True,
logfile=None,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
],
)
@@ -870,19 +887,22 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
logfile=None,
env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["koji", "--profile=custom-koji", "watch-task", "1234"],
can_fail=True,
logfile=None,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["koji", "--profile=custom-koji", "watch-task", "1234"],
can_fail=True,
logfile=None,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
],
)
@@ -907,13 +927,15 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase):
logfile=None,
env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"},
buffer_size=-1,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["koji", "--profile=custom-koji", "watch-task", "1234"],
can_fail=True,
logfile=None,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
],
)
diff --git a/tests/test_notifier.py b/tests/test_notifier.py
index e5584cc6..53ea4c94 100644
--- a/tests/test_notifier.py
+++ b/tests/test_notifier.py
@@ -70,7 +70,8 @@ class TestNotifier(unittest.TestCase):
can_fail=True,
return_stdout=False,
workdir=None,
- universal_newlines=True,
+ text=True,
+ errors="replace",
show_cmd=True,
logfile=self.logfile,
)
diff --git a/tests/test_ostree_script.py b/tests/test_ostree_script.py
index 6276f729..b2f37a37 100644
--- a/tests/test_ostree_script.py
+++ b/tests/test_ostree_script.py
@@ -67,7 +67,8 @@ class OstreeTreeScriptTest(helpers.PungiTestCase):
logfile=self.topdir + "/logs/Atomic/create-ostree-repo.log",
show_cmd=True,
stdout=True,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
]
+ extra_calls,
@@ -136,7 +137,8 @@ class OstreeTreeScriptTest(helpers.PungiTestCase):
logfile=self.topdir + "/logs/Atomic/ostree-summary.log",
show_cmd=True,
stdout=True,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
diff --git a/tests/test_patch_iso.py b/tests/test_patch_iso.py
index 87e052d0..4ba10206 100644
--- a/tests/test_patch_iso.py
+++ b/tests/test_patch_iso.py
@@ -34,7 +34,7 @@ class TestSh(unittest.TestCase):
patch_iso.sh(log, ["ls"], foo="bar")
self.assertEqual(
mock_run.call_args_list,
- [mock.call(["ls"], foo="bar", universal_newlines=True)],
+ [mock.call(["ls"], foo="bar", text=True, errors="replace")],
)
self.assertEqual(log.info.call_args_list, [mock.call("Running: %s", "ls")])
self.assertEqual(log.debug.call_args_list, [mock.call("%s", "ok")])
diff --git a/tests/test_unified_isos.py b/tests/test_unified_isos.py
index bf095d9c..134306e1 100755
--- a/tests/test_unified_isos.py
+++ b/tests/test_unified_isos.py
@@ -610,7 +610,7 @@ class TestCreateiso(PungiTestCase):
self.assertEqual(
run.mock_calls,
[
- mock.call(self.mkisofs_cmd, universal_newlines=True),
+ mock.call(self.mkisofs_cmd, text=True, errors="replace"),
mock.call(iso.get_implantisomd5_cmd.return_value),
mock.call(iso.get_manifest_cmd.return_value),
]
diff --git a/tests/test_util.py b/tests/test_util.py
index cf281c8a..00f875fd 100644
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -25,7 +25,8 @@ class TestGitRefResolver(unittest.TestCase):
self.assertEqual(url, "https://git.example.com/repo.git?somedir#CAFEBABE")
run.assert_called_once_with(
["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
@mock.patch("pungi.util.run")
@@ -39,7 +40,8 @@ class TestGitRefResolver(unittest.TestCase):
self.assertEqual(url, "https://git.example.com/repo.git?somedir#CAFEBABE")
run.assert_called_once_with(
GIT_WITH_CREDS + ["ls-remote", "https://git.example.com/repo.git", "HEAD"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
@mock.patch("pungi.util.run")
@@ -53,7 +55,8 @@ class TestGitRefResolver(unittest.TestCase):
self.assertEqual(url, "https://git.example.com/repo.git?somedir#CAFEBABE")
run.assert_called_once_with(
["git", "ls-remote", "https://git.example.com/repo.git", "refs/heads/f24"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
def test_resolve_ref_with_commit_id(self):
@@ -72,7 +75,8 @@ class TestGitRefResolver(unittest.TestCase):
self.assertEqual(ref, "CAFEBABE")
run.assert_called_once_with(
["git", "ls-remote", "https://git.example.com/repo.git", "master"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
@mock.patch("pungi.util.run")
@@ -84,7 +88,8 @@ class TestGitRefResolver(unittest.TestCase):
self.assertEqual(ref, "CAFEBABE")
run.assert_called_once_with(
["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
@mock.patch("pungi.util.run")
@@ -110,7 +115,8 @@ class TestGitRefResolver(unittest.TestCase):
run.assert_called_once_with(
["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
@mock.patch("pungi.util.run")
@@ -121,7 +127,8 @@ class TestGitRefResolver(unittest.TestCase):
run.assert_called_once_with(
["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
self.assertEqual(url, "https://git.example.com/repo.git?#CAFEBABE")
@@ -133,7 +140,8 @@ class TestGitRefResolver(unittest.TestCase):
run.assert_called_once_with(
["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
self.assertEqual(url, "git+https://git.example.com/repo.git#CAFEBABE")
@@ -153,7 +161,8 @@ class TestGitRefResolver(unittest.TestCase):
"https://git.example.com/repo.git",
"refs/heads/my-branch",
],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
self.assertIn("ref does not exist in remote repo", str(ctx.exception))
@@ -171,7 +180,8 @@ class TestGitRefResolver(unittest.TestCase):
[
mock.call(
["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"],
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
]
* 2,
@@ -600,7 +610,8 @@ class TestUnmountCmd(unittest.TestCase):
cmd,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -621,7 +632,8 @@ class TestUnmountCmd(unittest.TestCase):
cmd,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
],
)
@@ -643,7 +655,8 @@ class TestUnmountCmd(unittest.TestCase):
cmd,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
]
* 3,
@@ -668,7 +681,8 @@ class TestUnmountCmd(unittest.TestCase):
cmd,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
)
]
* 3,
@@ -707,37 +721,43 @@ class TestUnmountCmd(unittest.TestCase):
cmd,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
cmd,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
cmd,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["ls", "-lA", "/path"],
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["fuser", "-vm", "/path"],
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
mock.call(
["lsof", "+D", "/path"],
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
+ errors="replace",
),
]
self.assertEqual(mockPopen.call_args_list, expected)
--
2.47.1

View File

@ -1,91 +0,0 @@
From 3cb8992d56f2cee8a7cb151253125e30931ccd6d Mon Sep 17 00:00:00 2001
From: Adam Williamson <awilliam@redhat.com>
Date: Dec 12 2024 01:52:40 +0000
Subject: Use new container and bootable-container productmd types
In https://github.com/release-engineering/productmd/pull/181 I
added new `bootable-container` and `container` types to
productmd. This makes pungi always use the bootable-container
type for ostree_container images (previously 'ociarchive'), and
default to using the container type for Kiwi-built oci.tar.xz
container images (previously 'docker').
This is a significant change for anything that relies on
productmd/fedfind conventions to 'identify' images, as these
images will now have a different identity. But I think it's a
valuable improvement in their identities. 'ociarchive' never made
any sense as an image 'type' - it's a format - and 'docker'
wasn't a very good type for images that are explicitly OCI
container images, not Docker-native ones. We also can now easily
distinguish between 'regular' container images and ones that are
intended to be bootable.
Signed-off-by: Adam Williamson <awilliam@redhat.com>
---
diff --git a/pungi/phases/kiwibuild.py b/pungi/phases/kiwibuild.py
index 400ea6a..9b75dd7 100644
--- a/pungi/phases/kiwibuild.py
+++ b/pungi/phases/kiwibuild.py
@@ -25,6 +25,7 @@ KIWIEXTENSIONS = [
("fex", ["squashfs.xz"], "squashfs.xz"),
("fex", ["squashfs.gz"], "squashfs.gz"),
("fex", ["squashfs"], "squashfs"),
+ ("container", ["oci.tar.xz"], "tar.xz"),
]
@@ -242,13 +243,15 @@ class RunKiwiBuildThread(WorkerThread):
def _find_type_and_format(path):
- for type_, suffixes in EXTENSIONS.items():
- for suffix in suffixes:
- if path.endswith(suffix):
- return type_, suffix
# these are our kiwi-exclusive mappings for images whose extensions
- # aren't quite the same as imagefactory
+ # aren't quite the same as imagefactory. they come first as we
+ # want our oci.tar.xz mapping to win over the tar.xz one in
+ # EXTENSIONS
for type_, suffixes, format_ in KIWIEXTENSIONS:
if any(path.endswith(suffix) for suffix in suffixes):
return type_, format_
+ for type_, suffixes in EXTENSIONS.items():
+ for suffix in suffixes:
+ if path.endswith(suffix):
+ return type_, suffix
return None, None
diff --git a/pungi/phases/ostree_container.py b/pungi/phases/ostree_container.py
index c50633d..c017962 100644
--- a/pungi/phases/ostree_container.py
+++ b/pungi/phases/ostree_container.py
@@ -164,9 +164,9 @@ class OSTreeContainerThread(WorkerThread):
# Update image manifest
img = Image(compose.im)
- # Get the manifest type from the config if supplied, otherwise we
- # determine the manifest type based on the koji output
- img.type = "ociarchive"
+ # these are hardcoded as they should always be correct, we
+ # could potentially allow overriding them via config though
+ img.type = "bootable-container"
img.format = "ociarchive"
img.path = os.path.relpath(fullpath, compose.paths.compose.topdir())
img.mtime = util.get_mtime(fullpath)
diff --git a/setup.py b/setup.py
index fd249c0..839400b 100755
--- a/setup.py
+++ b/setup.py
@@ -56,7 +56,7 @@ setup(
"jsonschema",
"kobo",
"lxml",
- "productmd>=1.23",
+ "productmd>=1.43",
"dogpile.cache",
],
extras_require={':python_version=="2.7"': ["enum34", "lockfile"]},

View File

@ -1,20 +1,13 @@
%{?python_enable_dependency_generator}
Name: pungi
Version: 4.8.0
Release: 3%{?dist}.alma.1
Version: 4.9.0
Release: 1%{?dist}.alma.1
Summary: Distribution compose tool
License: GPL-2.0-only
URL: https://pagure.io/pungi
Source0: %{name}-%{version}.tar.bz2
# https://pagure.io/pungi/pull-request/1810
# Use container and bootable-container productmd types
Patch: 1810.patch
# https://pagure.io/pungi/pull-request/1812
# https://pagure.io/releng/issue/12474
# Avoid crashing if command output cannot be decoded as utf-8
Patch: 0002-Protect-against-decoding-errors-with-subprocess-text.patch
BuildRequires: make
BuildRequires: python3-pytest
@ -179,6 +172,16 @@ gzip _build/man/pungi.1
%{_bindir}/%{name}-cache-cleanup
%changelog
* Fri Feb 14 2025 Lubomír Sedlář <lsedlar@redhat.com> - 4.9.0-1
- buildinstall: Add support for rootfs-type lorax option (lsedlar)
- scm: Stop trying to download src arch (lsedlar)
- extra_isos: Provide arch to extra files getter (lsedlar)
- Move temporary buildinstall download to work/ (lsedlar)
- Download extra files from container registry (lsedlar)
- Remove python 2.7 dependencies from setup.py (lsedlar)
- util: Drop dead code (lsedlar)
- Directly import mock from unittest (lsedlar)
* Thu Jan 16 2025 Adam Williamson <awilliam@redhat.com> - 4.8.0-3
- Backport PR #1812 to fix crash on subprocess unicode decode error

View File

@ -1 +1 @@
SHA512 (pungi-4.8.0.tar.bz2) = 8ba996b2aeed47ef3b155fc3523519a5570fc191b0a4d779afa3ec3a0fb028ea6a21804ab195ef11eb97010042007f4aa483de51c36568653c8a2fe178b7b4ef
SHA512 (pungi-4.9.0.tar.bz2) = 43a21594d36e49b81aa600f5194080cf491f429cad2f07934524a3e0d1cdcfeff3eeb3740aa3454c8889d50a46e113556eb3b90af69ce83ee654cb2e80b03469