#!/usr/bin/env python3 """上传 release 资产到 gitcode(两步:取签名 URL → PUT 到 OBS)。 用法: upload_assets.py [file...] 不传 file 时上传该版本目录下所有 tar.gz/zip 与 SHA256SUMS。 """ import json import os import sys import urllib.request import urllib.parse REPO = "JianFeeeee/webui4frpc" API = "https://gitcode.com/api/v5/repos" def get_upload_url(version: str, token: str, filename: str) -> tuple[str, dict]: q = urllib.parse.urlencode({"file_name": filename}) url = f"{API}/{REPO}/releases/v{version}/upload_url?{q}" req = urllib.request.Request(url, headers={"private-token": token}) with urllib.request.urlopen(req, timeout=20) as r: data = json.loads(r.read()) return data["url"], data.get("headers", {}) def put_file(url: str, headers: dict, path: str) -> tuple[int, str]: size = os.path.getsize(path) with open(path, "rb") as f: body = f.read() req = urllib.request.Request(url, data=body, method="PUT") for k, v in headers.items(): req.add_header(k, v) req.add_header("Content-Length", str(size)) try: with urllib.request.urlopen(req, timeout=300) as r: return r.status, r.read().decode("utf-8", "replace")[:300] except urllib.error.HTTPError as e: return e.code, e.read().decode("utf-8", "replace")[:300] def main() -> int: if len(sys.argv) < 3: print(__doc__) return 2 version, token = sys.argv[1], sys.argv[2] outdir = os.path.join( os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "dist", "artifacts", version, ) files = sys.argv[3:] or sorted( f for f in os.listdir(outdir) if f.endswith((".tar.gz", ".zip")) or f == "SHA256SUMS" ) failed = 0 for name in files: path = os.path.join(outdir, name) if not os.path.isfile(path): print(f"skip (missing): {name}") continue print(f"==> {name} ({os.path.getsize(path)/1048576:.1f} MiB)") try: url, headers = get_upload_url(version, token, name) except Exception as e: # noqa: BLE001 print(f" upload_url FAILED: {e}") failed += 1 continue status, body = put_file(url, headers, path) ok = 200 <= status < 300 print(f" PUT -> {status} {'OK' if ok else body}") if not ok: failed += 1 print(f"\n{'ALL OK' if failed == 0 else f'{failed} FAILED'}") return 1 if failed else 0 if __name__ == "__main__": sys.exit(main())