diff options
| author | Danilo M. <danix@danix.xyz> | 2026-11-09 18:18:29 +0100 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-11-09 18:18:29 +0100 |
| commit | f4411cf679b8ec7557233490601f3c1875a32113 (patch) | |
| tree | 7032ef854d2bf58666b1addeb52ff0b45822fcbf | |
| parent | 2e86bcdc2132e7772e20e9f4426e3f079a07e5e0 (diff) | |
| download | deck-it-f4411cf679b8ec7557233490601f3c1875a32113.tar.gz deck-it-f4411cf679b8ec7557233490601f3c1875a32113.zip | |
feat: sb-builder status module
| -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() |
