feat(firmware-info): архивируй сборки по хешу и дате

Создай в postcompile CCS и Keil папку по commit исходников и UTC-времени precompile. Сохрани точные образы, manifest, SHA-256 и метаданные, сохраняя прежние выходные файлы. Опиши копирование каталогов в SETGUI и проверь разные даты, целостность и Git-метаданные.
This commit is contained in:
2026-10-08 15:31:13 +03:00
parent 8fc2e1b5cf
commit da055c2787
5 changed files with 158 additions and 3 deletions

View File

@@ -0,0 +1,72 @@
"""Tests for preserving exact firmware bytes under pre-build provenance folders."""
import json
from pathlib import Path
import sys
import tempfile
import unittest
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "tools"))
from identity import archive_build, build_folder_name, verify
class ArchiveTests(unittest.TestCase):
def metadata(self, stamp="2026-10-08T12:30:00+00:00"):
return {"source": {"commit": "a1b2c3d4" + "0" * 32, "dirty": False},
"templates": {"commit": None, "dirty": None},
"build_id": "NOGIT000", "built_at_utc": stamp,
"version": [1, 2, 3]}
def test_snapshot_preserves_image_and_records_exact_sha(self):
with tempfile.TemporaryDirectory() as root:
root = Path(root)
image = root / "firmware.bin"
payload = bytes(range(256))
image.write_bytes(payload)
metadata = root / "metadata.json"
metadata.write_text(json.dumps(self.metadata()), encoding="utf-8")
result = archive_build(image, metadata, root / "out")
folder = Path(result["directory"])
self.assertEqual(folder.name, "a1b2c3d4_2026-10-08_12-30-00_UTC")
self.assertEqual((folder / image.name).read_bytes(), payload)
self.assertEqual(image.read_bytes(), payload)
self.assertEqual(json.loads((folder / "firmware_identity.json").read_text()), self.metadata())
manifest = folder / (image.name + ".manifest.json")
self.assertEqual(verify(folder / image.name, manifest)["size_bytes"], 256)
(folder / image.name).write_bytes(b"corrupted")
with self.assertRaises(ValueError):
verify(folder / image.name, manifest)
def test_prebuild_times_keep_two_builds_separate(self):
with tempfile.TemporaryDirectory() as root:
root = Path(root)
image, metadata = root / "firmware.hex", root / "metadata.json"
image.write_bytes(b":00000001FF\r\n")
folders = []
for stamp in ("2026-10-08T12:30:00+00:00", "2026-10-08T12:31:00+00:00"):
metadata.write_text(json.dumps(self.metadata(stamp)), encoding="utf-8")
folders.append(Path(archive_build(image, metadata, root / "out")["directory"]))
self.assertNotEqual(folders[0], folders[1])
self.assertTrue(all((folder / image.name).is_file() for folder in folders))
def test_offset_normalizes_to_utc_and_dirty_is_visible(self):
metadata = self.metadata("2026-10-08T15:30:00+03:00")
metadata["source"]["dirty"] = True
self.assertEqual(build_folder_name(metadata), "a1b2c3d4+_2026-10-08_12-30-00_UTC")
def test_archive_without_git_has_explicit_placeholder(self):
metadata = self.metadata()
metadata["source"]["commit"] = None
self.assertEqual(build_folder_name(metadata), "NOGIT000_2026-10-08_12-30-00_UTC")
def test_invalid_provenance_cannot_be_a_folder_name(self):
metadata = self.metadata()
metadata["source"]["commit"] = "../outside"
with self.assertRaises(ValueError):
build_folder_name(metadata)
metadata = self.metadata("2026-10-08T12:30:00")
with self.assertRaises(ValueError):
build_folder_name(metadata)
if __name__ == "__main__":
unittest.main()