Repository: osbuild/osbuild
Pull request #1616 (2024-02-27 19:43:28)

stages/org.osbuild.gzip: add compression level option
Allow compression level to be specified instead of defaulting to 1. This is needed for CoreOS Assembler.

dustymabe: > This is needed for CoreOS Assembler.

To clarify: this is needed for building CoreOS disk images in order to maintain compatibility with the way the images are generated today using CoreOS Assembler.
bcl: This should also test that not including a level retains the previous behavior, setting it to -1.

Patch:
diff --git a/stages/org.osbuild.gzip b/stages/org.osbuild.gzip
index 66b1e678..60b71c5c 100755
--- a/stages/org.osbuild.gzip
+++ b/stages/org.osbuild.gzip
@@ -30,6 +30,13 @@ SCHEMA_2 = r"""
     "filename": {
       "description": "Filename to use for the compressed file",
       "type": "string"
+    },
+    "level": {
+      "description": "Compression level",
+      "type": "integer",
+      "minimum": 1,
+      "maximum": 9,
+      "default": 1
     }
   }
 }
@@ -48,13 +55,14 @@ def parse_input(inputs):
 
 def main(inputs, output, options):
     filename = options["filename"].lstrip("/")
+    level = options.get("level", 1)
 
     source = parse_input(inputs)
     target = os.path.join(output, filename)
 
     with open(target, "w", encoding="utf8") as f:
         cmd = [
-            "gzip", "--no-name", "--stdout", "-1", source
+            "gzip", "--no-name", "--stdout", f"-{level}", source
         ]
 
         subprocess.run(


Test patch:
diff --git a/stages/test/test_gzip.py b/stages/test/test_gzip.py
new file mode 100644
index 00000000..02b01051
--- /dev/null
+++ b/stages/test/test_gzip.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python3
+
+from unittest.mock import patch
+
+import pytest
+
+STAGE_NAME = "org.osbuild.gzip"
+
+
+@pytest.mark.parametrize("test_options,expected_level", [
+    # our default
+    ({}, "-1"),
+    # custom settings
+    ({"level": "1"}, "-1"),
+    ({"level": "6"}, "-6"),
+    ({"level": "9"}, "-9"),
+])
+@patch("subprocess.run")
+def test_gzip_compression_default_to_level1(mocked_run, tmp_path, stage_module, test_options, expected_level):
+    inp = {
+        "file": {
+            "path": "/input/file/path",
+            "data": {
+                "files": {
+                    "hash:value": "some-file",
+                }
+            },
+        },
+    }
+    output = tmp_path
+    options = {
+        "filename": "out.tar.gz",
+    }
+    options.update(test_options)
+
+    stage_module.main(inp, output, options)
+    assert len(mocked_run.call_args_list) == 1
+    args, kwargs = mocked_run.call_args_list[0]
+    assert args == (["gzip", "--no-name", "--stdout", expected_level, "/input/file/path/hash:value"],)
+    assert kwargs["check"]
+    assert kwargs["stdout"].name.endswith("out.tar.gz")
diff --git a/test/data/stages/gzip/b.json b/test/data/stages/gzip/b.json
index bb0d968f..fdb0a8ba 100644
--- a/test/data/stages/gzip/b.json
+++ b/test/data/stages/gzip/b.json
@@ -883,7 +883,8 @@
             }
           },
           "options": {
-            "filename": "compressed.gz"
+            "filename": "compressed.gz",
+            "level": 9
           }
         }
       ]
diff --git a/test/data/stages/gzip/b.mpp.yaml b/test/data/stages/gzip/b.mpp.yaml
index 9af0b4cc..7e7501c1 100644
--- a/test/data/stages/gzip/b.mpp.yaml
+++ b/test/data/stages/gzip/b.mpp.yaml
@@ -25,3 +25,4 @@ pipelines:
               sha256:f950375066d74787f31cbd8f9f91c71819357cad243fb9d4a0d9ef4fa76709e0: {}
         options:
           filename: compressed.gz
+          level: 9