feat: Track yt-dlp releases in cinema-tools updates

This commit is contained in:
pleb
2026-10-22 08:24:21 -07:00
parent 1becf8366d
commit 455c9fd2c6
5 changed files with 278 additions and 14 deletions
+108
View File
@@ -2085,6 +2085,114 @@ instance = "1.40.8"
self.assertEqual(updated_lock.plugins[0].download_url, "https://example.invalid/Example-v2.zip")
self.assertIn("GitHub release digest matched", updated_lock.plugins[0].reason or "")
def _cinema_tools_lock(self) -> Lockfile:
return Lockfile(
beat_saber_version="1.44.1",
instance="1.44.1",
plugins=(
LockedPlugin(
id="cinema-tools",
repo=None,
tag="yt-dlp-2026.07.04-ffmpeg-8.1.2",
asset="CinemaTools-yt-dlp-2026.07.04-ffmpeg-8.1.2.zip",
sha256="old",
install_strategy="root-zip",
reason="Helper-managed Windows executable bundle.",
),
),
)
def _yt_dlp_releases(self, tag: str) -> list[dict[str, object]]:
return [
{
"tag_name": tag,
"html_url": f"https://github.com/yt-dlp/yt-dlp/releases/tag/{tag}",
"published_at": "2026-10-01T00:00:00Z",
"assets": [
{"name": "yt-dlp", "browser_download_url": "https://example.invalid/yt-dlp"},
{
"name": "yt-dlp.exe",
"browser_download_url": f"https://example.invalid/{tag}/yt-dlp.exe",
"digest": "sha256:" + "a" * 64,
},
],
}
]
def test_update_check_reports_cinema_tools_yt_dlp_update(self) -> None:
repos: list[str] = []
def fetch(repo: str) -> list[dict[str, object]]:
repos.append(repo)
return self._yt_dlp_releases("2026.10.01")
result = check_updates(registry=Registry(), lockfile=self._cinema_tools_lock(), fetch_releases=fetch)
plugin = result["plugins"][0]
self.assertEqual(repos, ["yt-dlp/yt-dlp"])
self.assertEqual(plugin["status"], "update")
self.assertEqual(plugin["latestTag"], "yt-dlp-2026.10.01-ffmpeg-8.1.2")
self.assertEqual(plugin["latestAsset"], "CinemaTools-yt-dlp-2026.10.01-ffmpeg-8.1.2.zip")
self.assertEqual(plugin["latestYtDlpSha256"], "a" * 64)
self.assertEqual(result["summary"]["updates"], 1)
def test_update_check_reports_cinema_tools_current(self) -> None:
result = check_updates(
registry=Registry(),
lockfile=self._cinema_tools_lock(),
fetch_releases=lambda _repo: self._yt_dlp_releases("2026.07.04"),
)
self.assertEqual(result["plugins"][0]["status"], "current")
self.assertEqual(result["summary"]["current"], 1)
def test_update_command_rebuilds_cinema_tools_bundle(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
work = Path(tmp)
state = work / "state"
instance = work / "instance"
lock_path = work / "locks" / "1.44.1.lock.toml"
instance.mkdir()
built: list[tuple[str, str]] = []
def build(plugin: dict[str, object], destination: Path) -> dict[str, object]:
built.append((str(plugin["latestYtDlpVersion"]), str(plugin["latestYtDlpSha256"])))
destination.parent.mkdir(parents=True, exist_ok=True)
with ZipFile(destination, "w") as archive:
archive.writestr("Libs/yt-dlp.exe", b"new yt-dlp")
archive.writestr("Libs/ffmpeg.exe", b"ffmpeg")
return {"path": str(destination), "sha256": sha256_file(destination)}
def download(_url: str, _destination: Path) -> dict[str, object]:
raise AssertionError("recipe bundles must not be downloaded directly")
result = run_update(
instance="1.44.1",
instance_path=instance,
registry=Registry(),
lockfile=self._cinema_tools_lock(),
lock_path=lock_path,
state_root=state,
repo_root=work,
selected={"cinema-tools"},
fetch_releases=lambda _repo: self._yt_dlp_releases("2026.10.01"),
download_asset=download,
build_recipe_asset=build,
)
self.assertEqual(built, [("2026.10.01", "a" * 64)])
plan = json.loads(Path(result["planPath"]).read_text(encoding="utf-8"))
self.assertEqual(
sorted(change["target"] for change in plan["changes"]),
["Libs/ffmpeg.exe", "Libs/yt-dlp.exe"],
)
locked = load_lockfile(lock_path).plugins[0]
self.assertEqual(locked.tag, "yt-dlp-2026.10.01-ffmpeg-8.1.2")
self.assertEqual(locked.asset, "CinemaTools-yt-dlp-2026.10.01-ffmpeg-8.1.2.zip")
self.assertIsNone(locked.download_url)
self.assertIn("--yt-dlp-version 2026.10.01", locked.reason or "")
self.assertEqual(result["updated"][0]["toTag"], "yt-dlp-2026.10.01-ffmpeg-8.1.2")
def test_update_command_prepares_beatmods_update(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
work = Path(tmp)