scripts/release/gen_latest_json.py
Rama master · réplica de lectura del repositorio original.
#!/usr/bin/env python3
"""Generate latest.json for Tauri updater from release assets and .sig files.
Usage:
VERSION=v0.1.0 REPO=nyroway/nyro python3 scripts/gen_latest_json.py \
--assets-dir release-assets --output latest.json
Environment variables:
VERSION Git tag name, e.g. v0.1.0
REPO GitHub owner/repo, e.g. nyroway/nyro
"""
import argparse
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
from urllib.parse import quote
PLATFORM_RULES = [
# (file suffix, arch keywords, platform key, score)
(".app.tar.gz", ("x86_64",), "darwin-x86_64", 100),
(".app.tar.gz", ("aarch64",), "darwin-aarch64", 100),
("-setup.exe", ("arm64", "aarch64"), "windows-aarch64", 100),
("-setup.exe", ("x64", "x86_64"), "windows-x86_64", 100),
("-setup.exe", (), "windows-x86_64", 50),
(".appimage", ("aarch64", "arm64"), "linux-aarch64", 100),
(".appimage", (), "linux-x86_64", 100),
]
def classify(name: str):
lower = name.lower()
for suffix, keywords, platform, score in PLATFORM_RULES:
if not lower.endswith(suffix):
continue
if not keywords or any(k in lower for k in keywords):
return platform, score
return None, -1
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--assets-dir", default="release-assets")
parser.add_argument("--output", default="latest.json")
args = parser.parse_args()
version_tag = os.environ.get("VERSION", "").strip()
repo = os.environ.get("REPO", "").strip()
if not version_tag or not repo:
sys.exit("ERROR: VERSION and REPO environment variables are required.")
version = version_tag.lstrip("v")
release_dir = Path(args.assets_dir)
sig_files = sorted(release_dir.glob("*.sig"))
if not sig_files:
sys.exit(
f"ERROR: No .sig files found in '{release_dir}'. "
"Ensure TAURI_SIGNING_PRIVATE_KEY is configured."
)
base_url = f"https://github.com/{repo}/releases/download/{version_tag}"
preferred: dict = {}
for sig in sig_files:
target_name = sig.name[:-4]
platform, score = classify(target_name)
if platform is None:
continue
target_file = release_dir / target_name
if not target_file.exists():
continue
current = preferred.get(platform)
if current is None or score > current["score"]:
preferred[platform] = {
"file": target_name,
"signature": sig.read_text(encoding="utf-8").strip(),
"score": score,
}
platforms = {
p: {"url": f"{base_url}/{quote(e['file'])}", "signature": e["signature"]}
for p, e in preferred.items()
}
if not platforms:
sys.exit("ERROR: No updater-compatible assets found to build latest.json.")
latest = {
"version": version,
"notes": "See release notes for details.",
"pub_date": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
"platforms": platforms,
}
Path(args.output).write_text(
json.dumps(latest, ensure_ascii=False, indent=2) + "\n", encoding="utf-8"
)
print(f"Generated {args.output} — platforms: {', '.join(platforms)}")
if __name__ == "__main__":
main()