feat(deploy): build worker shadow artifact
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import tarfile
|
||||
from pathlib import Path
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
|
||||
BUILDER_PATH = REPOSITORY_ROOT / "scripts/build_m4_worker_shadow_artifact.py"
|
||||
SPEC = importlib.util.spec_from_file_location("m4_worker_shadow_builder", BUILDER_PATH)
|
||||
assert SPEC is not None and SPEC.loader is not None
|
||||
BUILDER = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(BUILDER)
|
||||
|
||||
|
||||
def _sha256(value: bytes) -> str:
|
||||
return hashlib.sha256(value).hexdigest()
|
||||
|
||||
|
||||
def _regular_files(archive: tarfile.TarFile) -> dict[str, bytes]:
|
||||
result: dict[str, bytes] = {}
|
||||
for member in archive.getmembers():
|
||||
if not member.isfile():
|
||||
continue
|
||||
extracted = archive.extractfile(member)
|
||||
assert extracted is not None
|
||||
result[member.name] = extracted.read()
|
||||
return result
|
||||
|
||||
|
||||
def test_worker_shadow_artifact_is_deterministic_narrow_and_data_only(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
patch_id = "mission-core-m4-detector-shadow-unit-001"
|
||||
first = BUILDER.build_artifact(patch_id, tmp_path / "first")
|
||||
second = BUILDER.build_artifact(patch_id, tmp_path / "second")
|
||||
first_bytes = Path(first["artifact"]).read_bytes()
|
||||
second_bytes = Path(second["artifact"]).read_bytes()
|
||||
|
||||
assert first_bytes == second_bytes
|
||||
assert first["sha256"] == _sha256(first_bytes)
|
||||
assert first["sha256"] == second["sha256"]
|
||||
assert first["payload_files"] == list(BUILDER.PAYLOAD_FILES)
|
||||
|
||||
with tarfile.open(first["artifact"], "r:gz") as archive:
|
||||
members = archive.getmembers()
|
||||
names = [member.name for member in members]
|
||||
regular = _regular_files(archive)
|
||||
|
||||
assert names == [
|
||||
"manifest.env",
|
||||
"files.txt",
|
||||
"payload",
|
||||
"payload/m4-recorded-realtime-baseline-v1.json",
|
||||
"payload/mission-core-worker-shadow-v1.json",
|
||||
f"payload/{BUILDER.WHEEL_NAME}",
|
||||
]
|
||||
assert (
|
||||
regular["manifest.env"]
|
||||
== (f"id={patch_id}\ncomponent=mission-core-worker\ntype=shadow-release\n").encode()
|
||||
)
|
||||
assert regular["files.txt"].decode().splitlines() == list(BUILDER.PAYLOAD_FILES)
|
||||
assert _sha256(regular[f"payload/{BUILDER.WHEEL_NAME}"]) == (BUILDER.EXPECTED_WHEEL_SHA256)
|
||||
assert _sha256(regular["payload/m4-recorded-realtime-baseline-v1.json"]) == (
|
||||
BUILDER.EXPECTED_BASELINE_SHA256
|
||||
)
|
||||
descriptor = json.loads(regular["payload/mission-core-worker-shadow-v1.json"])
|
||||
assert descriptor["patch_id"] == patch_id
|
||||
assert descriptor["code_revision"] == first["code_revision"]
|
||||
assert descriptor["container"]["public_ports"] is False
|
||||
assert descriptor["rollback"] == {
|
||||
"durable_worker_action": "none",
|
||||
"preserve_failed_evidence": True,
|
||||
"remove_candidate_container": True,
|
||||
"remove_unaccepted_release": True,
|
||||
"triton_action": "none",
|
||||
}
|
||||
all_bytes = b"\n".join(regular.values())
|
||||
assert b"PRIVATE KEY" not in all_bytes
|
||||
assert b"password=" not in all_bytes.lower()
|
||||
assert not any(
|
||||
Path(name).name.startswith(".env")
|
||||
or "/secrets/" in name
|
||||
or "/runtime/" in name
|
||||
or "/recordings/" in name
|
||||
for name in names
|
||||
)
|
||||
|
||||
|
||||
def test_worker_shadow_descriptor_pins_external_inputs_and_preserves_e15() -> None:
|
||||
rendered = BUILDER.render_descriptor(
|
||||
"mission-core-m4-detector-shadow-unit-002",
|
||||
"c" * 40,
|
||||
)
|
||||
descriptor = json.loads(rendered)
|
||||
|
||||
assert descriptor["schema_version"] == ("nodedc.mission-core-worker.shadow-release/v1")
|
||||
assert descriptor["transition"] == "m4-detector-shadow-v1"
|
||||
assert descriptor["host"] == {
|
||||
"node": "DESKTOP-OPJ8J04",
|
||||
"worker_id": "worker-006",
|
||||
}
|
||||
assert set(descriptor["inputs"]) == {
|
||||
"camera_index",
|
||||
"camera_summary",
|
||||
"source_pack",
|
||||
"source_pack_manifest",
|
||||
"valid_fov_mask",
|
||||
"video",
|
||||
"yolox_config",
|
||||
"yolox_model",
|
||||
}
|
||||
assert all(len(value["sha256"]) == 64 for value in descriptor["inputs"].values())
|
||||
assert [item["id"] for item in descriptor["dependencies"]] == [
|
||||
"pyav-media",
|
||||
"opencv-packages",
|
||||
"pillow-packages",
|
||||
]
|
||||
assert descriptor["predecessor"]["durable_worker"]["name"] == (
|
||||
"ndc-mission-core-perception-worker"
|
||||
)
|
||||
assert descriptor["predecessor"]["triton"]["name"] == ("ndc-mission-core-triton")
|
||||
assert descriptor["acceptance"] == {
|
||||
"class_routing_used": False,
|
||||
"expected_frames": 4489,
|
||||
"failed_frames": 0,
|
||||
"minimum_end_to_end_fps": 10.004,
|
||||
}
|
||||
Reference in New Issue
Block a user