Repository: osbuild/osbuild
Pull request #1971 (2024-12-31 07:32:52)

Tools/osbuild-image-info: make `read_boot_entries()` more robust (HMS-5228)
`read_boot_entries()` could previously fail when trying to split lines in bootloader entries, which contained only "\n" and became an empty string after stripping whitespace characters. This is the case e.g. on F41 images.

Moreover, bootloader entries can contain comments as lines starting with "#", which were previously not ignored by the function and would end up in the parsed entry and could potentially fail to be split.

Add unit test covering the changes and expected behavior.

/jira-epic COMPOSER-2318

JIRA: [HMS-5228](https://issues.redhat.com/browse/HMS-5228)


Patch:
diff --git a/Schutzfile b/Schutzfile
index 8c3c6338..9451d875 100644
--- a/Schutzfile
+++ b/Schutzfile
@@ -19,7 +19,7 @@
           {
             "title": "fedora-updates",
             "name": "fedora-updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f39/f39-x86_64-updates-released-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f39/f39-x86_64-updates-released-20250101"
           }
         ],
         "aarch64": [
@@ -31,7 +31,7 @@
           {
             "title": "fedora-updates",
             "name": "fedora-updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f39/f39-aarch64-updates-released-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f39/f39-aarch64-updates-released-20250101"
           }
         ]
       }
@@ -50,7 +50,7 @@
           {
             "title": "fedora-updates",
             "name": "fedora-updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-x86_64-updates-released-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-x86_64-updates-released-20250101"
           }
         ],
         "aarch64": [
@@ -62,7 +62,7 @@
           {
             "title": "fedora-updates",
             "name": "fedora-updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-aarch64-updates-released-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-aarch64-updates-released-20250101"
           }
         ]
       }
@@ -81,7 +81,7 @@
           {
             "title": "fedora-updates",
             "name": "fedora-updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f41/f41-x86_64-updates-released-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f41/f41-x86_64-updates-released-20250101"
           }
         ],
         "aarch64": [
@@ -93,7 +93,7 @@
           {
             "title": "fedora-updates",
             "name": "fedora-updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f41/f41-aarch64-updates-released-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f41/f41-aarch64-updates-released-20250101"
           }
         ]
       }
@@ -107,34 +107,34 @@
           {
             "title": "baseos",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-x86_64-baseos-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-x86_64-baseos-20250101"
           },
           {
             "title": "appstream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-x86_64-appstream-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-x86_64-appstream-20250101"
           },
           {
             "title": "crb",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-x86_64-crb-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-x86_64-crb-20250101"
           }
         ],
         "aarch64": [
           {
             "title": "baseos",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-aarch64-baseos-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-aarch64-baseos-20250101"
           },
           {
             "title": "appstream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-aarch64-appstream-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-aarch64-appstream-20250101"
           },
           {
             "title": "crb",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-aarch64-crb-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el9/cs9-aarch64-crb-20250101"
           }
         ]
       }
@@ -148,34 +148,34 @@
           {
             "title": "baseos",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-x86_64-baseos-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-x86_64-baseos-20250101"
           },
           {
             "title": "appstream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-x86_64-appstream-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-x86_64-appstream-20250101"
           },
           {
             "title": "crb",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-x86_64-crb-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-x86_64-crb-20250101"
           }
         ],
         "aarch64": [
           {
             "title": "baseos",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-aarch64-baseos-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-aarch64-baseos-20250101"
           },
           {
             "title": "appstream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-aarch64-appstream-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-aarch64-appstream-20250101"
           },
           {
             "title": "crb",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-aarch64-crb-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/el10/cs10-aarch64-crb-20250101"
           }
         ]
       }
@@ -189,34 +189,34 @@
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-BaseOS",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.5-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.5-20250101"
           },
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-AppStream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.5-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.5-20250101"
           },
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-CRB",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-crb-n9.5-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-crb-n9.5-20250101"
           }
         ],
         "aarch64": [
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-BaseOS",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-baseos-n9.5-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-baseos-n9.5-20250101"
           },
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-AppStream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.5-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.5-20250101"
           },
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-CRB",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-crb-n9.5-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-crb-n9.5-20250101"
           }
         ]
       }
@@ -230,34 +230,34 @@
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-BaseOS",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.6-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.6-20250101"
           },
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-AppStream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.6-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.6-20250101"
           },
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-CRB",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-crb-n9.6-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-crb-n9.6-20250101"
           }
         ],
         "aarch64": [
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-BaseOS",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-baseos-n9.6-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-baseos-n9.6-20250101"
           },
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-AppStream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.6-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.6-20250101"
           },
           {
             "title": "RHEL-9-RPMREPO-NIGHTLY-CRB",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-crb-n9.6-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-crb-n9.6-20250101"
           }
         ]
       }
@@ -271,34 +271,34 @@
           {
             "title": "RHEL-10-RPMREPO-NIGHTLY-BaseOS",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-x86_64-baseos-n10.0-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-x86_64-baseos-n10.0-20250101"
           },
           {
             "title": "RHEL-10-RPMREPO-NIGHTLY-AppStream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-x86_64-appstream-n10.0-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-x86_64-appstream-n10.0-20250101"
           },
           {
             "title": "RHEL-10-RPMREPO-NIGHTLY-CRB",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-x86_64-crb-n10.0-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-x86_64-crb-n10.0-20250101"
           }
         ],
         "aarch64": [
           {
             "title": "RHEL-10-RPMREPO-NIGHTLY-BaseOS",
             "name": "baseos",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-aarch64-baseos-n10.0-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-aarch64-baseos-n10.0-20250101"
           },
           {
             "title": "RHEL-10-RPMREPO-NIGHTLY-AppStream",
             "name": "appstream",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-aarch64-appstream-n10.0-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-aarch64-appstream-n10.0-20250101"
           },
           {
             "title": "RHEL-10-RPMREPO-NIGHTLY-CRB",
             "name": "crb",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-aarch64-crb-n10.0-20241210"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el10/el10-aarch64-crb-n10.0-20250101"
           }
         ]
       }
diff --git a/schutzbot/team_ssh_keys.txt b/schutzbot/team_ssh_keys.txt
index 30f393b0..442af190 100644
--- a/schutzbot/team_ssh_keys.txt
+++ b/schutzbot/team_ssh_keys.txt
@@ -8,5 +8,5 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDY/ylCrPBzil4TnZR4tWULpz3QgfBMQyEnMOHDAJNp
 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjNynFZPCEPVDyOB2yzrww5kxwK6MAb1D0GN5yP8y/iw+gtx+Hj3CqojHMTa/9r3q3R1TMgCITdvzAiKylbx/owV8bgXS1p8je2KirWx3o/Dy80AYsas2F+sodm5/FOz6LvcUZw2vZiVs1wp8dz7ak+pm6Xg7xa7511xO4T/HStzNUE/XSPYmC9LNJ+uVWTiCjTWlZxp1JcDVfO7k69F60u8D42e1Ty60IeNeJItX/o8FUjB/rMAAJRpjFpd/uyfPTWamjNoVzrB7chFxaemg2Nf8na6PHLAx8Gcxz2fdnnsg+M5vr6z0yVYz1cc8VOhYynQm9iISvTt6bDVEbWc2T thozza@redhat.com
 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOSn7aXhxrfFHWDyAYZSGHJIyfq1NIClqibdtL4H5cB8 jrusz@fedora
 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHUHIBlCKLUnlc4rVEnNAX913iEzVCFkN49yntwXi5Ye dustymabe@redhat.com dustymabe-ed25519-ci-osbuild
-ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIAYU2wzSk9r1l3iOwsvaJXCsfQIUga3xzShZJAM1zHv achilleas@Ruby
-ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPqEtsCdSozq0DT8sOazpizsBP65Ni6SMqrQA85Wnfs1 achilleas@Jack
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIAYU2wzSk9r1l3iOwsvaJXCsfQIUga3xzShZJAM1zHv akoutsou-R@redhat.com
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM+4pso8s0M0hKFW6XoEvM6loZp0C7D9ZlmwXQbhxyV0 akoutsou-i@redhat.com
diff --git a/schutzbot/terraform b/schutzbot/terraform
index e2e956d4..fb2f0e3b 100644
--- a/schutzbot/terraform
+++ b/schutzbot/terraform
@@ -1,1 +1,1 @@
-b580d2cf18c8745e883490010d5b6a3c5d8e3e20
+2c51ba92065231c4986894cc2bc214dea1b2c157
\ No newline at end of file
diff --git a/stages/org.osbuild.erofs b/stages/org.osbuild.erofs
index e52f2c6a..e15ec5c7 100755
--- a/stages/org.osbuild.erofs
+++ b/stages/org.osbuild.erofs
@@ -21,9 +21,13 @@ def main(inputs, output_dir, options):
             method += f",{compression['level']}"
         cmd += ["-z", method]
 
-    options = options.get("options")
-    if options:
-        cmd += ["-E", ",".join(options)]
+    erofs_options = options.get("options")
+    if erofs_options:
+        cmd += ["-E", ",".join(erofs_options)]
+
+    cluster_size = options.get("cluster-size")
+    if cluster_size:
+        cmd += ["-C", f"{cluster_size}"]
 
     subprocess.run(cmd, check=True)
 
diff --git a/stages/org.osbuild.erofs.meta.json b/stages/org.osbuild.erofs.meta.json
index 51ee70bb..0f675189 100644
--- a/stages/org.osbuild.erofs.meta.json
+++ b/stages/org.osbuild.erofs.meta.json
@@ -28,7 +28,8 @@
               "enum": [
                 "lz4",
                 "lz4hc",
-                "lzma"
+                "lzma",
+                "zstd"
               ]
             },
             "level": {
@@ -37,6 +38,10 @@
             }
           }
         },
+        "cluster-size": {
+          "description": "Maximum size of the compress physical cluster in bytes",
+          "type": "number"
+        },
         "options": {
           "description": "Extended options for the filesystem, see mkfs.erofs(1)",
           "type": "array",
diff --git a/tools/osbuild-image-info b/tools/osbuild-image-info
index c082017b..7cb9aaf4 100755
--- a/tools/osbuild-image-info
+++ b/tools/osbuild-image-info
@@ -366,7 +366,14 @@ def read_boot_entries(boot_dir):
     entries = []
     for conf in glob.glob(f"{boot_dir}/loader/entries/*.conf"):
         with open(conf) as f:
-            entries.append(dict(line.strip().split(" ", 1) for line in f))
+            entry = dict()
+            for line in f:
+                line = line.strip()
+                if not line or line.startswith("#"):
+                    continue
+                key, value = line.split(" ", 1)
+                entry[key] = value
+            entries.append(entry)
 
     return sorted(entries, key=lambda e: e["title"])
 


Test patch:
diff --git a/stages/test/test_erofs.py b/stages/test/test_erofs.py
index 3b41519f..d74bde2d 100644
--- a/stages/test/test_erofs.py
+++ b/stages/test/test_erofs.py
@@ -15,6 +15,7 @@ TEST_INPUT = [
     ({"compression": {"method": "lz4hc", "level": 9}}, ["-z", "lz4hc,9"]),
     ({"options": ["dedupe"]}, ["-E", "dedupe"]),
     ({"options": ["all-fragments", "force-inode-compact"]}, ["-E", "all-fragments,force-inode-compact"]),
+    ({"cluster-size": 131072, "options": ["dedupe"]}, ["-E", "dedupe", "-C", "131072"]),
 ]
 
 
diff --git a/tools/test/test_osbuild_image_info.py b/tools/test/test_osbuild_image_info.py
new file mode 100644
index 00000000..1386217a
--- /dev/null
+++ b/tools/test/test_osbuild_image_info.py
@@ -0,0 +1,137 @@
+import pytest
+
+from osbuild.testutil import make_fake_tree
+from osbuild.testutil.imports import import_module_from_path
+
+osbuild_image_info = import_module_from_path("osbuild_image_info", "tools/osbuild-image-info")
+
+
+@pytest.mark.parametrize("fake_tree,entries", (
+    # no entries
+    ({}, []),
+    # one entry
+    (
+        {
+            "/boot/loader/entries/0649288e52434223afde4c36460a375e-6.11.9-100.fc39.x86_64.conf": """title Fedora Linux (6.11.9-100.fc39.x86_64) 39 (Thirty Nine)
+version 6.11.9-100.fc39.x86_64
+linux /boot/vmlinuz-6.11.9-100.fc39.x86_64
+initrd /boot/initramfs-6.11.9-100.fc39.x86_64.img
+options root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8
+grub_users $grub_users
+grub_arg --unrestricted
+grub_class fedora""",
+        },
+        [
+            {
+                "title": "Fedora Linux (6.11.9-100.fc39.x86_64) 39 (Thirty Nine)",
+                "version": "6.11.9-100.fc39.x86_64",
+                "linux": "/boot/vmlinuz-6.11.9-100.fc39.x86_64",
+                "initrd": "/boot/initramfs-6.11.9-100.fc39.x86_64.img",
+                "options": "root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8",
+                "grub_users": "$grub_users",
+                "grub_arg": "--unrestricted",
+                "grub_class": "fedora",
+            },
+        ]
+    ),
+    # two entries
+    (
+        {
+            "/boot/loader/entries/0649288e52434223afde4c36460a375e-6.11.9-100.fc39.x86_64.conf": """title Fedora Linux (6.11.9-100.fc39.x86_64) 39 (Thirty Nine)
+version 6.11.9-100.fc39.x86_64
+linux /boot/vmlinuz-6.11.9-100.fc39.x86_64
+initrd /boot/initramfs-6.11.9-100.fc39.x86_64.img
+options root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8
+grub_users $grub_users
+grub_arg --unrestricted
+grub_class fedora""",
+            "/boot/loader/entries/0649288e52434223afde4c36460a375e-6.11.9-101.fc39.x86_64.conf": """title Fedora Linux (6.11.9-101.fc39.x86_64) 39 (Thirty Nine)
+version 6.11.9-101.fc39.x86_64
+linux /boot/vmlinuz-6.11.9-101.fc39.x86_64
+initrd /boot/initramfs-6.11.9-101.fc39.x86_64.img
+options root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8
+grub_users $grub_users
+grub_arg --unrestricted
+grub_class fedora""",
+        },
+        [
+            {
+                "title": "Fedora Linux (6.11.9-100.fc39.x86_64) 39 (Thirty Nine)",
+                "version": "6.11.9-100.fc39.x86_64",
+                "linux": "/boot/vmlinuz-6.11.9-100.fc39.x86_64",
+                "initrd": "/boot/initramfs-6.11.9-100.fc39.x86_64.img",
+                "options": "root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8",
+                "grub_users": "$grub_users",
+                "grub_arg": "--unrestricted",
+                "grub_class": "fedora",
+            },
+            {
+                "title": "Fedora Linux (6.11.9-101.fc39.x86_64) 39 (Thirty Nine)",
+                "version": "6.11.9-101.fc39.x86_64",
+                "linux": "/boot/vmlinuz-6.11.9-101.fc39.x86_64",
+                "initrd": "/boot/initramfs-6.11.9-101.fc39.x86_64.img",
+                "options": "root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8",
+                "grub_users": "$grub_users",
+                "grub_arg": "--unrestricted",
+                "grub_class": "fedora",
+            },
+        ]
+    ),
+    # one entry with extra newlines
+    (
+        {
+            "/boot/loader/entries/0649288e52434223afde4c36460a375e-6.11.9-100.fc39.x86_64.conf": """title Fedora Linux (6.11.9-100.fc39.x86_64) 39 (Thirty Nine)
+version 6.11.9-100.fc39.x86_64
+linux /boot/vmlinuz-6.11.9-100.fc39.x86_64
+initrd /boot/initramfs-6.11.9-100.fc39.x86_64.img
+options root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8
+grub_users $grub_users
+grub_arg --unrestricted
+grub_class fedora
+
+""",
+        },
+        [
+            {
+                "title": "Fedora Linux (6.11.9-100.fc39.x86_64) 39 (Thirty Nine)",
+                "version": "6.11.9-100.fc39.x86_64",
+                "linux": "/boot/vmlinuz-6.11.9-100.fc39.x86_64",
+                "initrd": "/boot/initramfs-6.11.9-100.fc39.x86_64.img",
+                "options": "root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8",
+                "grub_users": "$grub_users",
+                "grub_arg": "--unrestricted",
+                "grub_class": "fedora",
+            },
+        ]
+    ),
+    # one entry with comments
+    (
+        {
+            "/boot/loader/entries/0649288e52434223afde4c36460a375e-6.11.9-100.fc39.x86_64.conf": """title Fedora Linux (6.11.9-100.fc39.x86_64) 39 (Thirty Nine)
+# this is a very useful comment
+version 6.11.9-100.fc39.x86_64
+linux /boot/vmlinuz-6.11.9-100.fc39.x86_64
+initrd /boot/initramfs-6.11.9-100.fc39.x86_64.img
+options root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8
+# this is another very useful comment
+grub_users $grub_users
+grub_arg --unrestricted
+grub_class fedora""",
+        },
+        [
+            {
+                "title": "Fedora Linux (6.11.9-100.fc39.x86_64) 39 (Thirty Nine)",
+                "version": "6.11.9-100.fc39.x86_64",
+                "linux": "/boot/vmlinuz-6.11.9-100.fc39.x86_64",
+                "initrd": "/boot/initramfs-6.11.9-100.fc39.x86_64.img",
+                "options": "root=UUID=a7e970a5-14fb-4a8a-ab09-603d1ac3fee9 ro crashkernel=auto net.ifnames=0 rhgb console=tty0 console=ttyS0,115200n8",
+                "grub_users": "$grub_users",
+                "grub_arg": "--unrestricted",
+                "grub_class": "fedora",
+            },
+        ]
+    ),
+))
+def test_read_boot_entries(tmp_path, fake_tree, entries):
+    make_fake_tree(tmp_path, fake_tree)
+    assert osbuild_image_info.read_boot_entries(tmp_path / "boot") == entries