diff --git a/.gitea/workflows/nightly.yml b/.gitea/workflows/nightly.yml index 45832ae..41ea65f 100644 --- a/.gitea/workflows/nightly.yml +++ b/.gitea/workflows/nightly.yml @@ -68,6 +68,7 @@ jobs: AUTOPKG_USER: ${{ github.actor }} AUTOPKG_TOKEN: ${{ secrets.PACKAGE_TOKEN || github.token }} AUTOPKG_REPLACE: ${{ github.event.inputs.replace }} + AUTOPKG_SKIP_PGP: "1" # Womp womp PKG: ${{ matrix.pkg }} run: | # -E keeps AUTOPKG_*; force HOME to builder's so cargo/git/etc. can write their caches diff --git a/autopackage.py b/autopackage.py index 4012ee7..34f62de 100644 --- a/autopackage.py +++ b/autopackage.py @@ -25,6 +25,7 @@ import shlex import shutil import subprocess import sys +import time import urllib.error import urllib.request from dataclasses import dataclass, field @@ -257,16 +258,33 @@ def auth_header(cfg: Config) -> str: def http_request(url: str, method: str, cfg: Config, - data: Optional[bytes] = None) -> tuple: - req = urllib.request.Request(url, data=data, method=method) - req.add_header("Authorization", auth_header(cfg)) - if data is not None: - req.add_header("Content-Type", "application/octet-stream") - try: - with urllib.request.urlopen(req) as resp: - return resp.status, resp.read().decode("utf-8", "replace") - except urllib.error.HTTPError as e: - return e.code, e.read().decode("utf-8", "replace") + data: Optional[bytes] = None, retries: int = 4) -> tuple: + last_err: Optional[Exception] = None + for attempt in range(1, retries + 1): + req = urllib.request.Request(url, data=data, method=method) + req.add_header("Authorization", auth_header(cfg)) + if data is not None: + req.add_header("Content-Type", "application/octet-stream") + try: + with urllib.request.urlopen(req, timeout=300) as resp: + return resp.status, resp.read().decode("utf-8", "replace") + except urllib.error.HTTPError as e: + body = e.read().decode("utf-8", "replace") + # Retry transient server errors; return everything else as-is. + if e.code in (500, 502, 503, 504) and attempt < retries: + last_err = e + else: + return e.code, body + except (urllib.error.URLError, ConnectionError, TimeoutError, OSError) as e: + # Network-level failures (e.g. connection reset by peer) -> retry. + last_err = e + if attempt >= retries: + raise + backoff = min(2 ** attempt, 30) + print(f" {method} {url} failed ({last_err}); " + f"retry {attempt}/{retries - 1} in {backoff}s") + time.sleep(backoff) + raise RuntimeError(f"{method} {url} failed after {retries} attempts: {last_err}") def delete_version(filename: str, cfg: Config) -> None: @@ -323,6 +341,8 @@ def build_config(args: argparse.Namespace) -> Config: makepkg_cmd = ["makepkg", "-s", "--noconfirm", "--needed"] if args.cleanbuild: makepkg_cmd.append("--cleanbuild") + if args.skip_pgp: + makepkg_cmd.append("--skippgpcheck") if args.sign: makepkg_cmd.append("--sign") @@ -361,6 +381,11 @@ def main(argv: List[str]) -> int: "(used to build the CI matrix)") ap.add_argument("--cleanbuild", action="store_true", help="Pass --cleanbuild to makepkg") + ap.add_argument("--skip-pgp", action="store_true", + default=env("AUTOPKG_SKIP_PGP", "") not in ("", "0", "false"), + help="Skip source PGP signature checks (sha256sums still " + "verified). Useful when upstream signing keys aren't in " + "the build keyring.") ap.add_argument("--sign", action="store_true", help="Sign packages (makepkg --sign) and upload .sig files") ap.add_argument("--keep-going", action="store_true", diff --git a/ggml-git-latest-commit/.gitkeep b/ggml-git-latest-commit/.gitkeep deleted file mode 100644 index e69de29..0000000