From 6298ad9aa210f31f8561661379eefb04fec9affa Mon Sep 17 00:00:00 2001 From: Dusk-92 Date: Thu, 27 Aug 2026 15:08:48 +0200 Subject: [PATCH] ci: remove one-time bundled fallback refresh --- .../workflows/refresh-bundled-fallbacks.yml | 312 ------------------ 1 file changed, 312 deletions(-) delete mode 100644 .github/workflows/refresh-bundled-fallbacks.yml diff --git a/.github/workflows/refresh-bundled-fallbacks.yml b/.github/workflows/refresh-bundled-fallbacks.yml deleted file mode 100644 index a282532..0000000 --- a/.github/workflows/refresh-bundled-fallbacks.yml +++ /dev/null @@ -1,312 +0,0 @@ -name: One-time bundled fallback refresh - -on: - push: - branches: - - feature/client-tweaks - paths: - - .github/workflows/refresh-bundled-fallbacks.yml - -permissions: - contents: write - -jobs: - refresh: - runs-on: ubuntu-latest - steps: - - name: Checkout feature branch - uses: actions/checkout@v4 - with: - ref: feature/client-tweaks - fetch-depth: 0 - - - name: Refresh bundled files from upstream - shell: bash - run: | - set -euo pipefail - python - <<'PY' - import hashlib - import io - import json - import os - import shutil - import tempfile - import urllib.request - import zipfile - from pathlib import Path - - ROOT = Path.cwd() - PAYLOAD = ROOT / "Payload" - FALLBACK = PAYLOAD / "Fallback" - UA = {"User-Agent": "Dusk-92-Modernization-Tool-Fallback-Refresh"} - - metadata = {"schema": 1, "components": {}} - - def get_bytes(url): - req = urllib.request.Request(url, headers=UA) - with urllib.request.urlopen(req, timeout=180) as r: - return r.read() - - def get_json(url): - return json.loads(get_bytes(url).decode("utf-8")) - - def latest(repo): - data = get_json(f"https://api.github.com/repos/{repo}/releases/latest") - if data.get("draft") or data.get("prerelease"): - raise RuntimeError(f"{repo}: latest release is not stable") - return data - - def asset(release, exact=None, predicate=None): - for a in release.get("assets", []): - name = a.get("name", "") - if exact and name.lower() == exact.lower(): - return a - if predicate and predicate(name): - return a - raise RuntimeError(f"Asset not found in {release.get('html_url')}") - - def write_bytes(path, data): - path = Path(path) - path.parent.mkdir(parents=True, exist_ok=True) - path.write_bytes(data) - - def validate_pe(path): - data = Path(path).read_bytes() - if len(data) < 1024 or data[:2] != b"MZ": - raise RuntimeError(f"Invalid PE binary: {path}") - - def extract_zip(data): - temp = Path(tempfile.mkdtemp(prefix="modernization_refresh_")) - with zipfile.ZipFile(io.BytesIO(data)) as z: - for info in z.infolist(): - dest = (temp / info.filename).resolve() - if temp.resolve() not in dest.parents and dest != temp.resolve(): - raise RuntimeError(f"Unsafe zip path: {info.filename}") - z.extractall(temp) - return temp - - def find_file(root, name): - matches = [p for p in Path(root).rglob("*") if p.is_file() and p.name.lower() == name.lower()] - if not matches: - raise RuntimeError(f"{name} not found") - return matches[0] - - def find_dir(root, name): - matches = [p for p in Path(root).rglob("*") if p.is_dir() and p.name.lower() == name.lower()] - if not matches: - raise RuntimeError(f"{name} directory not found") - return matches[0] - - def replace_dir(src, dest): - dest = Path(dest) - if dest.exists(): - shutil.rmtree(dest) - dest.parent.mkdir(parents=True, exist_ok=True) - shutil.copytree(src, dest) - - def sha256(path): - h = hashlib.sha256() - with open(path, "rb") as f: - for chunk in iter(lambda: f.read(1024 * 1024), b""): - h.update(chunk) - return h.hexdigest() - - def record(name, source, version, paths): - metadata["components"][name] = { - "source": source, - "version": version, - "files": [ - { - "path": str(Path(p).relative_to(ROOT)).replace("\\", "/"), - "sha256": sha256(p), - "size": Path(p).stat().st_size, - } - for p in paths if Path(p).is_file() - ], - } - - # Nampower DLL + settings addon - rel = latest("brues-code/nampower") - a = asset(rel, predicate=lambda n: n.lower().startswith("nampower-") and n.lower().endswith(".zip")) - tmp = extract_zip(get_bytes(a["browser_download_url"])) - try: - dll = find_file(tmp, "nampower.dll") - addon = find_dir(tmp, "NampowerSettings") - write_bytes(PAYLOAD / "nampower.dll", dll.read_bytes()) - replace_dir(addon, PAYLOAD / "Interface" / "Addons" / "nampowersettings") - finally: - shutil.rmtree(tmp, ignore_errors=True) - validate_pe(PAYLOAD / "nampower.dll") - record("Nampower", a["browser_download_url"], rel["tag_name"], [PAYLOAD / "nampower.dll"]) - - # UnitXP SP3 DLL + addon - rel = latest("brues-code/UnitXP_SP3") - a = asset(rel, predicate=lambda n: n.lower().startswith("unitxp_sp3") and n.lower().endswith(".zip")) - tmp = extract_zip(get_bytes(a["browser_download_url"])) - try: - dll = find_file(tmp, "UnitXP_SP3.dll") - addon = find_dir(tmp, "UnitXP_SP3_Addon") - write_bytes(PAYLOAD / "UnitXP_SP3.dll", dll.read_bytes()) - replace_dir(addon, PAYLOAD / "Interface" / "Addons" / "UnitXP_SP3_Addon") - finally: - shutil.rmtree(tmp, ignore_errors=True) - validate_pe(PAYLOAD / "UnitXP_SP3.dll") - record("UnitXP_SP3", a["browser_download_url"], rel["tag_name"], [PAYLOAD / "UnitXP_SP3.dll"]) - - # SuperWoW DLL + current SuperAPI master - rel = latest("balakethelock/SuperWoW") - a = asset(rel, predicate=lambda n: n.lower().startswith("superwow") and n.lower().endswith(".zip")) - tmp = extract_zip(get_bytes(a["browser_download_url"])) - try: - dll = find_file(tmp, "SuperWoWhook.dll") - write_bytes(PAYLOAD / "SuperWoWhook.dll", dll.read_bytes()) - finally: - shutil.rmtree(tmp, ignore_errors=True) - validate_pe(PAYLOAD / "SuperWoWhook.dll") - superapi_url = "https://codeload.github.com/balakethelock/SuperAPI/zip/refs/heads/master" - tmp = extract_zip(get_bytes(superapi_url)) - try: - addon = find_dir(tmp, "SuperAPI-master") - replace_dir(addon, PAYLOAD / "Interface" / "Addons" / "SuperAPI") - finally: - shutil.rmtree(tmp, ignore_errors=True) - record("SuperWoW", a["browser_download_url"], rel["tag_name"], [PAYLOAD / "SuperWoWhook.dll"]) - - # VanillaHelpers - rel = latest("isfir/VanillaHelpers") - a = asset(rel, exact="VanillaHelpers.dll") - write_bytes(PAYLOAD / "VanillaHelpers.dll", get_bytes(a["browser_download_url"])) - validate_pe(PAYLOAD / "VanillaHelpers.dll") - record("VanillaHelpers", a["browser_download_url"], rel["tag_name"], [PAYLOAD / "VanillaHelpers.dll"]) - - # no1600x1200 current RetroCro backup - url = "https://raw.githubusercontent.com/RetroCro/TurtleWoW-Mods/refs/heads/main/Archive/DLL%20BACKUP/no1600x1200.dll" - write_bytes(PAYLOAD / "no1600x1200.dll", get_bytes(url)) - validate_pe(PAYLOAD / "no1600x1200.dll") - record("no1600x1200", url, "RetroCro main", [PAYLOAD / "no1600x1200.dll"]) - - # PerfBoost current RetroCro binary backup (addon remains the existing avitasia bundle). - url = "https://raw.githubusercontent.com/RetroCro/TurtleWoW-Mods/refs/heads/main/Archive/DLL%20BACKUP/perf_boost.dll" - write_bytes(PAYLOAD / "perf_boost.dll", get_bytes(url)) - validate_pe(PAYLOAD / "perf_boost.dll") - record("PerfBoost", url, "RetroCro main", [PAYLOAD / "perf_boost.dll"]) - - # User-selected WeirdPerformance 0.7.3 build - url = "https://codeberg.org/Dusk92/WeirdUtils/releases/download/0.7.3/weirdperformance.dll" - write_bytes(PAYLOAD / "weirdperformance.dll", get_bytes(url)) - validate_pe(PAYLOAD / "weirdperformance.dll") - record("WeirdPerformance", url, "0.7.3", [PAYLOAD / "weirdperformance.dll"]) - - # ClassicAPI fallback - rel = latest("brues-code/ClassicAPI") - a = asset(rel, exact="ClassicAPI.dll") - write_bytes(FALLBACK / "ClassicAPI.dll", get_bytes(a["browser_download_url"])) - validate_pe(FALLBACK / "ClassicAPI.dll") - record("ClassicAPI fallback", a["browser_download_url"], rel["tag_name"], [FALLBACK / "ClassicAPI.dll"]) - - # AuctionQueryThrottle fallback - rel = latest("brues-code/AuctionQueryThrottle") - a = asset(rel, exact="AuctionQueryThrottle.dll") - write_bytes(FALLBACK / "AuctionQueryThrottle.dll", get_bytes(a["browser_download_url"])) - validate_pe(FALLBACK / "AuctionQueryThrottle.dll") - record("AuctionQueryThrottle fallback", a["browser_download_url"], rel["tag_name"], [FALLBACK / "AuctionQueryThrottle.dll"]) - - # VanillaMultiMonitorFix fallback - rel = latest("Mates1500/VanillaMultiMonitorFix") - a = asset(rel, exact="release.zip") - tmp = extract_zip(get_bytes(a["browser_download_url"])) - try: - dll = find_file(tmp, "VanillaMultiMonitorFix.dll") - cfg = find_file(tmp, "VMMFix_preferred_monitor.txt") - out = FALLBACK / "VanillaMultiMonitorFix" - if out.exists(): - shutil.rmtree(out) - out.mkdir(parents=True) - write_bytes(out / "VanillaMultiMonitorFix.dll", dll.read_bytes()) - write_bytes(out / "VMMFix_preferred_monitor.txt", cfg.read_bytes()) - finally: - shutil.rmtree(tmp, ignore_errors=True) - validate_pe(FALLBACK / "VanillaMultiMonitorFix" / "VanillaMultiMonitorFix.dll") - record( - "VanillaMultiMonitorFix fallback", - a["browser_download_url"], - rel["tag_name"], - [ - FALLBACK / "VanillaMultiMonitorFix" / "VanillaMultiMonitorFix.dll", - FALLBACK / "VanillaMultiMonitorFix" / "VMMFix_preferred_monitor.txt", - ], - ) - - # Interact fallback (DLL + addon) - rel = latest("lookino/Interact") - a = asset(rel, exact="Interact.zip") - tmp = extract_zip(get_bytes(a["browser_download_url"])) - try: - dll = find_file(tmp, "Interact.dll") - toc = find_file(tmp, "Interact.toc") - addon = toc.parent - out = FALLBACK / "Interact" - if out.exists(): - shutil.rmtree(out) - out.mkdir(parents=True) - write_bytes(out / "Interact.dll", dll.read_bytes()) - replace_dir(addon, out / "Addon") - finally: - shutil.rmtree(tmp, ignore_errors=True) - validate_pe(FALLBACK / "Interact" / "Interact.dll") - record("Interact fallback", a["browser_download_url"], rel["tag_name"], [FALLBACK / "Interact" / "Interact.dll"]) - - # Tiny sound packs: store complete source trees as offline fallbacks. - sound_specs = [ - ("NoErrorSounds", "Macumbafeh/NoErrorSounds", "main", "Sound", FALLBACK / "Audio" / "NoErrorSounds" / "Sound"), - ("FishPing", "notsureawake/FishPing", "master", "Sound", FALLBACK / "Audio" / "FishPing" / "Sound"), - ("WarlockMutedDemons", "spzilyk/Warlock-Muted-Demons", "main", "Data", FALLBACK / "Audio" / "WarlockMutedDemons" / "Data"), - ] - for name, repo, branch, source_dir_name, dest in sound_specs: - url = f"https://codeload.github.com/{repo}/zip/refs/heads/{branch}" - tmp = extract_zip(get_bytes(url)) - try: - src = find_dir(tmp, source_dir_name) - replace_dir(src, dest) - finally: - shutil.rmtree(tmp, ignore_errors=True) - files = [p for p in dest.rglob("*") if p.is_file()] - record(f"{name} fallback", url, branch, files) - - # Keep a modern tubtubs vanilla-tweaks build offline as well. - rel = latest("tubtubs/vanilla-tweaks") - a = asset( - rel, - predicate=lambda n: n.lower().endswith(".zip") - and "windows" in n.lower() - and not n.lower().endswith(".sha256sum"), - ) - tmp = extract_zip(get_bytes(a["browser_download_url"])) - try: - exe = find_file(tmp, "vanilla-tweaks.exe") - write_bytes(ROOT / "vanilla-tweaks.exe", exe.read_bytes()) - finally: - shutil.rmtree(tmp, ignore_errors=True) - validate_pe(ROOT / "vanilla-tweaks.exe") - record("vanilla-tweaks fallback", a["browser_download_url"], rel["tag_name"], [ROOT / "vanilla-tweaks.exe"]) - - FALLBACK.mkdir(parents=True, exist_ok=True) - (FALLBACK / "versions.json").write_text( - json.dumps(metadata, indent=2, sort_keys=True) + "\n", - encoding="utf-8", - ) - PY - - - name: Commit refreshed bundled fallbacks - shell: bash - run: | - set -euo pipefail - if git diff --quiet; then - echo "Bundled files already match upstream." - exit 0 - fi - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add Payload vanilla-tweaks.exe - git commit -m "payload: refresh bundled known-good fallbacks [skip ci]" - git push origin HEAD:feature/client-tweaks