Repository: osbuild/osbuild
Pull request #218 (2020-01-28 11:47:54)

Add a unit test to verify `STAGE_OPTS` has valid json
Loads `stages` and `assembler` stages as modules and tries to load the json and fail if that fails. Fix the invalid json in `STAGE_OPTS` of the stages that the test discovered.


Patch:
diff --git a/stages/org.osbuild.dnf b/stages/org.osbuild.dnf
index dbdb1188..b64b15ff 100755
--- a/stages/org.osbuild.dnf
+++ b/stages/org.osbuild.dnf
@@ -132,7 +132,7 @@ STAGE_OPTS = """
   "module_platform_id": {
     "description": "DNF's module_platform_id option. Corresponds to PLATFORM_ID from /etc/os-release",
     "type": "string"
-  },
+  }
 }
 """
 
diff --git a/stages/org.osbuild.error b/stages/org.osbuild.error
index 51c8b9fe..a615063c 100755
--- a/stages/org.osbuild.error
+++ b/stages/org.osbuild.error
@@ -11,7 +11,7 @@ wasting time.
 STAGE_OPTS = """
 "properties": {
   "returncode": {
-    "description": "What to return code to use"
+    "description": "What to return code to use",
     "type": "number",
     "default": 255
   }
diff --git a/stages/org.osbuild.grub2 b/stages/org.osbuild.grub2
index 670c01c3..d157106d 100755
--- a/stages/org.osbuild.grub2
+++ b/stages/org.osbuild.grub2
@@ -73,13 +73,12 @@ STAGE_OPTS = """
     "description": "Include UEFI boot support",
     "type": "object",
     "required": ["vendor"],
-      "properties": {
-        "vendor": {
-          "type": "string",
-           "description": "The vendor of the UEFI binaries (this is us)",
-           "examples": ["fedora"],
-           "pattern": "^(.+)$"
-        }
+    "properties": {
+      "vendor": {
+        "type": "string",
+         "description": "The vendor of the UEFI binaries (this is us)",
+         "examples": ["fedora"],
+         "pattern": "^(.+)$"
       }
     }
   }


Test patch:
diff --git a/test/test_osbuild.py b/test/test_osbuild.py
index 20c36381..f26a6488 100644
--- a/test/test_osbuild.py
+++ b/test/test_osbuild.py
@@ -1,7 +1,9 @@
-
-import osbuild
+import importlib.util
+import json
+import os
 import unittest
 
+import osbuild
 
 class TestDescriptions(unittest.TestCase):
     def test_canonical(self):
@@ -74,6 +76,29 @@ class TestDescriptions(unittest.TestCase):
               }
             })
 
+    def test_stageinfo(self):
+        def list_stages(base):
+            return [(base, f) for f in os.listdir(base) if f.startswith("org.osbuild")]
+
+        def load_module(base, name):
+            loader = importlib.machinery.SourceFileLoader(name, f"{base}/{name}")
+            spec = importlib.util.spec_from_loader(loader.name, loader)
+            mod = importlib.util.module_from_spec(spec)
+            loader.exec_module(mod)
+            return mod
+
+        stages = list_stages("stages")
+        stages += list_stages("assemblers")
+
+        for stage in stages:
+            base, name = stage
+            m = load_module(base, name)
+            try:
+                json.loads("{" + m.STAGE_OPTS + "}")
+            except json.decoder.JSONDecodeError as e:
+                msg = f"Stage '{base}/{name}' has invalid STAGE_OPTS\n\t" + str(e)
+                self.fail(msg)
+
 
 if __name__ == "__main__":
     unittest.main()