From 198f58e2522251161c8502a058366530c1c96811 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sat, 19 Sep 2026 23:44:30 +0800 Subject: [PATCH] Add version normalization and payload count check Added a function to normalize version tags by stripping project-name prefixes. Implemented checks to prevent publishing if payload count drops significantly. --- update_payloads.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/update_payloads.py b/update_payloads.py index 1b55068..e55bf7d 100644 --- a/update_payloads.py +++ b/update_payloads.py @@ -25,6 +25,7 @@ Design rules: import json import re import subprocess +import sys import urllib.request from datetime import datetime, timedelta, timezone from pathlib import Path @@ -166,6 +167,17 @@ def get_checksum(asset: dict) -> str: return digest.split(":", 1)[1] if digest.startswith("sha256:") else "" +def normalize_version(tag: str, repo_url: str) -> str: + """Strip a leading project-name prefix from the tag (e.g. 'file-explorer-v0.2.1' → 'v0.2.1'). + + Only strips when the prefix is followed by 'v.', i.e. '-v1.2.3'. + Bare-digit tags ('1.2.3', 'beta-1.2', 'nightly-20250901') and already-clean + 'v…' tags pass through untouched. The client treats `version` as display-only. + """ + m = re.match(r"^[a-z][a-z0-9-]*-(?=v\d+\.)", tag, re.IGNORECASE) + return tag[m.end():] if m else tag + + # ─── Category derivation ───────────────────────────────────────────── # 分类顺序 = 特异性优先:越靠前的规则越特殊,避免被后面的通用词覆盖。 # 维度统一为“用户用它做什么”,粗颗粒度,每类 ≥3 个,无 Misc 兜底(默认 Tools)。 @@ -366,7 +378,7 @@ def build_item(repo_url: str, override: dict, asset_hint: str) -> tuple[dict, st "filename": selected["name"], "url": selected["browser_download_url"], "description": description, - "version": release.get("tag_name", ""), + "version": normalize_version(release.get("tag_name", ""), repo_url), "category": category, "checksum": get_checksum(selected), "last_update": format_last_update(release.get("published_at") or ""), @@ -492,7 +504,30 @@ def main() -> None: final_items.sort(key=lambda p: p.get("name", "").lower()) + # 护栏:条目数较上一次骤降 >20% 视为上游大面积失效,拒绝写盘并退出非零, + # 防止残缺目录被 Action 自动 commit 部署。 + try: + with open(OUTPUT_FILE, encoding="utf-8") as f: + prev_count = len(json.load(f).get("payloads", [])) + except (OSError, json.JSONDecodeError): + prev_count = 0 + if prev_count and len(final_items) < prev_count * 0.8: + print( + f"error: payload count dropped from {prev_count} to {len(final_items)} " + f"(>20% drop); aborting to avoid publishing a broken catalogue", + file=sys.stderr, + ) + sys.exit(1) + document = {"name": CATALOGUE_NAME, "payloads": final_items} + # skipped 区块:让"投了 sources.json 但没产出"的源在输出里可见。 + # 注意:skipped 条目只含 url/reason,绝不能含 name+filename+url 三件套—— + # ps5-payload-manager 的解析器会把任何带三件套的 {…} 对象误收进可安装列表。 + if skipped: + document["skipped"] = [ + {"url": u, "reason": "no release with .elf/.bin asset, or repo unreachable"} + for u in sorted(skipped) + ] with open(OUTPUT_FILE, "w", encoding="utf-8") as f: json.dump(document, f, indent=2, ensure_ascii=False) f.write("\n")