diff options
| -rw-r--r-- | deckit/modules/sbbuilder.py | 36 | ||||
| -rw-r--r-- | tests/test_sbbuilder.py | 29 |
2 files changed, 65 insertions, 0 deletions
diff --git a/deckit/modules/sbbuilder.py b/deckit/modules/sbbuilder.py new file mode 100644 index 0000000..3a48a1d --- /dev/null +++ b/deckit/modules/sbbuilder.py @@ -0,0 +1,36 @@ +"""sb-builder build progress, read-only over ssh. + +The build VM's `sbb-remote jobs` already returns JSON; this module runs it over +the configured ssh host alias and relays it. Nothing here writes to the VM. +""" + +import json +import subprocess + +from ..module import Module + + +def _run(cmd, timeout=5): + try: + return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout).stdout + except (OSError, subprocess.TimeoutExpired): + return "" + + +def make(cfg: dict) -> Module: + host = cfg.get("sbbuilder", {}).get("host", "buildsystem") + run = cfg.get("run", _run) + + def state(): + try: + out = run(["ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=4", + host, "sbb-remote", "jobs"]) + except OSError: + return {"offline": True} + try: + data = json.loads(out) + except (ValueError, TypeError): + return {"offline": True} + return {"offline": False, "jobs": data.get("jobs", [])} + + return Module(name="sbbuilder", title="Builds", state=state) diff --git a/tests/test_sbbuilder.py b/tests/test_sbbuilder.py new file mode 100644 index 0000000..5c5438e --- /dev/null +++ b/tests/test_sbbuilder.py @@ -0,0 +1,29 @@ +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) + +import json +import unittest + +import deckit.modules.sbbuilder as sbb + + +class Fail(unittest.TestCase): + def test_offline_on_ssh_failure(self): + def boom(cmd, timeout=5): + raise OSError("no route") + self.assertTrue(sbb.make({"sbbuilder": {"host": "buildsystem"}, "run": boom}).state()["offline"]) + + +class Ok(unittest.TestCase): + def test_parses_jobs(self): + out = json.dumps({"jobs": [{"id": "20261109-101010-build", "status": "running"}]}) + st = sbb.make({"sbbuilder": {"host": "buildsystem"}, + "run": lambda cmd, timeout=5: out}).state() + self.assertFalse(st["offline"]) + self.assertEqual(st["jobs"][0]["status"], "running") + + +if __name__ == "__main__": + unittest.main() |
