Implement verified household TV updates and release tooling

This commit is contained in:
justinzeus 2026-11-07 18:50:43 +01:00
parent 152dac97c0
commit d171aaae9e
29 changed files with 2485 additions and 99 deletions

100
docker/test_tv_release.py Normal file
View file

@ -0,0 +1,100 @@
"""Exercise source cleanliness, monotonic codes and fail-closed signing prerequisites."""
import contextlib
import io
import os
import subprocess
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
import tv_release
class ReleaseInputTest(unittest.TestCase):
"""Use a disposable Git fixture, never a build or a real signing key."""
def setUp(self) -> None:
self.temporary = tempfile.TemporaryDirectory()
self.addCleanup(self.temporary.cleanup)
self.root = Path(self.temporary.name) / "source"
self.root.mkdir()
(self.root / "docker").mkdir()
(self.root / "docker/tv-version-codes").write_text("65 installed-opt\n")
self.git("init", "--quiet")
self.git("add", "docker/tv-version-codes")
self.git(
"-c",
"user.name=Fixture",
"-c",
"user.email=fixture@example.invalid",
"commit",
"--quiet",
"-m",
"Record used code",
)
self.previous_root = tv_release.ROOT
tv_release.ROOT = self.root
self.addCleanup(setattr, tv_release, "ROOT", self.previous_root)
def git(self, *args: str) -> str:
"""Run the isolated source fixture's actual Git commands."""
return subprocess.check_output(["git", *args], cwd=self.root, text=True).strip()
def test_new_code_identifies_clean_source(self) -> None:
self.assertEqual(
self.git("rev-parse", "HEAD"), tv_release.validate_inputs("1.1.1", 100001)
)
def test_reused_and_lower_codes_are_rejected(self) -> None:
for code in (1, 64, 65):
with self.subTest(code=code), self.assertRaises(ValueError):
tv_release.validate_inputs("1.1.1", code)
def test_dirty_source_is_rejected(self) -> None:
(self.root / "untracked").write_text("not part of the source commit")
with self.assertRaises(ValueError):
tv_release.validate_inputs("1.1.1", 100001)
def test_unparseable_version_and_invalid_codes_are_rejected(self) -> None:
for version, code in (
("1.1.1-opt", 100001),
("1.1.1", 0),
("1.1.1", 2100000001),
):
with (
self.subTest(version=version, code=code),
self.assertRaises(ValueError),
):
tv_release.validate_inputs(version, code)
def test_missing_signing_key_never_generates_identity(self) -> None:
key = Path(self.temporary.name) / "absent-key"
with (
patch.dict(os.environ, {"WOLFSKIN_DEBUG_KEYSTORE": str(key)}),
self.assertRaises(ValueError),
):
tv_release.release(
"1.1.1", 100001, Path(self.temporary.name) / "output", True
)
self.assertFalse(key.exists())
def test_dry_run_never_builds_tags_or_mutates_ledger(self) -> None:
key = Path(self.temporary.name) / "fixture-key-presence-only"
key.write_bytes(b"not an actual keystore; dry run must not open it")
output = Path(self.temporary.name) / "output"
with (
patch.dict(os.environ, {"WOLFSKIN_DEBUG_KEYSTORE": str(key)}),
contextlib.redirect_stdout(io.StringIO()),
):
tv_release.release("1.1.1", 100001, output, True)
self.assertFalse(output.exists())
self.assertEqual("", self.git("tag", "--list"))
self.assertEqual(
"65 installed-opt\n", (self.root / "docker/tv-version-codes").read_text()
)
if __name__ == "__main__":
unittest.main()