Repository: osbuild/osbuild
Pull request #1832 (2024-08-05 14:01:03)

osbuild add new `-q`, `--quiet` option
Current osbuild will always print some non output even when run with `--monitor=JSONSeqMonitor` because of the unconditional `print/sys.stdout.write()` in `main_cli.py`.

This commit adds a new `-q` option to silence this so that something like osbuild-composer can run `osbuild -q --monitor=JSONSeqMonitor` to get pure json-seq output during the build.

The use-case is to run `osbuild --monitor-fd` from e.g. bib and osbuild-composer so that we get pure json from the monitor-fd and anything that goes on std{out,err} can be logged as it is most likely error output.

Companion PR for https://github.com/osbuild/osbuild/pull/1831 - not strictly needed but makes things (IMHO) cleaner.

github-actions[bot]: This PR is stale because it has been open 30 days with no activity. Remove "Stale" label or comment or this will be closed in 7 days.

Patch:
diff --git a/osbuild/main_cli.py b/osbuild/main_cli.py
index d76a8a8d..89d83e21 100644
--- a/osbuild/main_cli.py
+++ b/osbuild/main_cli.py
@@ -103,6 +103,8 @@ def parse_arguments(sys_argv: List[str]) -> argparse.Namespace:
     # nargs='?' const='*' means `--break` is equivalent to `--break=*`
     parser.add_argument("--break", dest='debug_break', type=str, nargs='?', const='*',
                         help="open debug shell when executing stage. Accepts stage name or id or * (for all)")
+    parser.add_argument("--quiet", "-q", action="store_true",
+                        help="suppress normal output")
 
     return parser.parse_args(sys_argv[1:])
 
@@ -162,7 +164,7 @@ def osbuild_cli() -> int:
 
     monitor_name = args.monitor
     if not monitor_name:
-        monitor_name = "NullMonitor" if args.json else "LogMonitor"
+        monitor_name = "NullMonitor" if (args.json or args.quiet) else "LogMonitor"
 
     try:
         with ObjectStore(args.store) as object_store:
@@ -201,7 +203,7 @@ def osbuild_cli() -> int:
                 r = fmt.output(manifest, r, object_store)
                 json.dump(r, sys.stdout)
                 sys.stdout.write("\n")
-            else:
+            elif not args.quiet:
                 if r["success"]:
                     for name, pl in manifest.pipelines.items():
                         print(f"{name + ':': <10}\t{pl.id}")


Test patch:
diff --git a/test/run/test_noop.py b/test/run/test_noop.py
index fb92a123..57af1e88 100644
--- a/test/run/test_noop.py
+++ b/test/run/test_noop.py
@@ -3,9 +3,12 @@
 #
 
 import json
+import os
 
 import pytest
 
+import osbuild.main_cli
+
 from .. import test
 
 
@@ -64,3 +67,20 @@ def test_noop2(osb):
 @pytest.mark.skipif(not test.TestBase.can_bind_mount(), reason="root-only")
 def test_noop_v2(osb, tmp_path, jsondata):
     osb.compile(jsondata, output_dir=tmp_path, exports=["noop"])
+
+
+def test_noop_cli(monkeypatch, capfd, tmp_path, jsondata):
+    fake_manifest = tmp_path / "manifest.json"
+    fake_manifest.write_text(jsondata)
+
+    monkeypatch.setattr("sys.argv", [
+        "arg0",
+        "--libdir=.", os.fspath(fake_manifest),
+        f"--store={tmp_path}",
+        "--quiet",
+    ])
+    ret_code = osbuild.main_cli.osbuild_cli()
+    assert ret_code == 0
+
+    captured = capfd.readouterr()
+    assert captured.out == ""