Coverage for .github / scripts / verify_inference_streaming_bundle_freshness.py: 100.00%
57 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-09-14 22:07 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-09-14 22:07 +0000
1#!/usr/bin/env python3
2"""CI-only regression for the real ignored inference streaming bundle.
4The check deliberately damages ``lambda/inference-streaming-proxy-build`` and
5then enters the production ``StackManager.synth`` and ``StackManager.diff``
6paths. Only ``_run_cdk`` is mocked, so no CDK process runs during this check;
7the real pinned npm builder must repair the real ignored asset both times.
8"""
10from __future__ import annotations
12import json
13import subprocess
14import sys
15from pathlib import Path
16from unittest.mock import patch
18_PROJECT_ROOT = Path(__file__).resolve().parents[2]
19sys.path.insert(0, str(_PROJECT_ROOT))
21from cli.stacks import StackManager # noqa: E402
23_PACKAGE_FILES = ("index.mjs", "package.json", "package-lock.json")
26def _dependency_markers(source_dir: Path, build_dir: Path) -> tuple[Path, ...]:
27 package_data = json.loads((source_dir / "package.json").read_text(encoding="utf-8"))
28 dependencies = package_data.get("dependencies")
29 if not isinstance(dependencies, dict) or not dependencies:
30 raise AssertionError("Inference streaming package has no production dependencies")
31 return tuple(
32 build_dir / "node_modules" / name / "package.json" for name in sorted(dependencies)
33 )
36def _transitive_dependency_file(source_dir: Path, build_dir: Path) -> Path:
37 package_data = json.loads((source_dir / "package.json").read_text(encoding="utf-8"))
38 direct_dependencies = set(package_data.get("dependencies", {}))
39 for marker in sorted((build_dir / "node_modules").rglob("package.json")):
40 relative = marker.relative_to(build_dir / "node_modules")
41 if len(relative.parts) < 2:
42 continue
43 package_name = (
44 "/".join(relative.parts[:2]) if relative.parts[0].startswith("@") else relative.parts[0]
45 )
46 if package_name not in direct_dependencies:
47 return marker
48 raise AssertionError("Inference streaming bundle has no transitive dependency marker")
51def _assert_fresh(manager: StackManager, source_dir: Path, build_dir: Path) -> None:
52 if not manager._inference_streaming_build_is_fresh(source_dir, build_dir):
53 raise AssertionError("Inference streaming bundle is not source-current")
54 for name in _PACKAGE_FILES:
55 if (build_dir / name).read_bytes() != (source_dir / name).read_bytes():
56 raise AssertionError(f"Inference streaming bundle did not restore {name}")
57 for marker in _dependency_markers(source_dir, build_dir):
58 if not marker.is_file():
59 raise AssertionError(
60 f"Inference streaming bundle did not restore dependency marker {marker}"
61 )
64def main() -> None:
65 project_root = _PROJECT_ROOT
66 source_dir = project_root / "lambda" / "inference-streaming-proxy"
67 build_dir = project_root / "lambda" / "inference-streaming-proxy-build"
68 manager = object.__new__(StackManager)
69 manager.project_root = project_root
71 _assert_fresh(manager, source_dir, build_dir)
73 stale_handler = (source_dir / "index.mjs").read_bytes() + b"\n// deliberate CI staleness\n"
74 (build_dir / "index.mjs").write_bytes(stale_handler)
75 if manager._inference_streaming_build_is_fresh(source_dir, build_dir):
76 raise AssertionError("Changed handler bytes were incorrectly accepted as fresh")
78 synth_result = subprocess.CompletedProcess(
79 args=["cdk", "synth"],
80 returncode=0,
81 stdout="mocked synth",
82 stderr="",
83 )
84 with patch.object(manager, "_run_cdk", return_value=synth_result) as run_cdk:
85 if manager.synth("gco-api-gateway") != "mocked synth":
86 raise AssertionError("Unexpected mocked synth result")
87 run_cdk.assert_called_once_with(
88 ["synth", "gco-api-gateway", "--quiet"], capture_output=True
89 )
90 _assert_fresh(manager, source_dir, build_dir)
92 transitive_marker = _transitive_dependency_file(source_dir, build_dir)
93 transitive_relative = transitive_marker.relative_to(build_dir)
94 transitive_marker.unlink()
95 if manager._inference_streaming_build_is_fresh(source_dir, build_dir):
96 raise AssertionError(
97 f"Missing transitive dependency file was accepted as fresh: {transitive_relative}"
98 )
100 diff_result = subprocess.CompletedProcess(
101 args=["cdk", "diff"],
102 returncode=1,
103 stdout="",
104 stderr="mocked diff",
105 )
106 with patch.object(manager, "_run_cdk", return_value=diff_result) as run_cdk:
107 if manager.diff("gco-api-gateway") != "mocked diff":
108 raise AssertionError("Unexpected mocked diff result")
109 run_cdk.assert_called_once_with(
110 ["diff", "--no-color", "gco-api-gateway"], capture_output=True
111 )
112 _assert_fresh(manager, source_dir, build_dir)
113 if not (build_dir / transitive_relative).is_file():
114 raise AssertionError(f"Inference streaming bundle did not restore {transitive_relative}")
116 print("Real inference streaming bundle freshness verified for synth and diff")
119if __name__ == "__main__":
120 main()