Files
jasp-desktop-bin/scripts/gen-pkgbuild.py
T
agw f0f317ca2f Document binary provenance in the PKGBUILD header
Checked what the AUR actually requires rather than relying on my earlier
assumption. The submission guidelines say only that packages using prebuilt
deliverables must carry the -bin suffix; nothing requires the binary to come
from upstream, so -bin is correct and sufficient here.

There is no formal 'unofficial binary' flag, so disclose it where users look:
an explicit PROVENANCE block in the PKGBUILD comment header naming the tag,
commit, build recipe and release URL, plus '(prebuilt binary)' in pkgdesc.

Corrects the README, which overstated the risk of a maintainer objecting.
2026-09-01 22:30:00 +02:00

104 lines
3.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""Turn build-info.json into a ready-to-publish PKGBUILD.
pkgrel is derived from what is currently on the AUR: same pkgver means this is a
rebuild (against a new R/Qt6), so pkgrel increments; a new pkgver resets it to 1.
"""
import argparse
import json
import re
import sys
import urllib.request
AUR_RPC = "https://aur.archlinux.org/rpc/v5/info?arg[]={}"
def next_minor(version: str) -> str:
"""4.6 -> 4.7, 6.11 -> 6.12 — the upper bound of the compatible range."""
major, minor = version.split(".")[:2]
return f"{major}.{int(minor) + 1}"
def current_aur_version(pkgname: str) -> tuple[str, int] | None:
"""(pkgver, pkgrel) currently published on the AUR, or None if absent."""
try:
with urllib.request.urlopen(AUR_RPC.format(pkgname), timeout=30) as r:
results = json.load(r).get("results", [])
except Exception as exc: # network trouble must not silently reset pkgrel
print(f"warning: could not query AUR: {exc}", file=sys.stderr)
return None
if not results:
return None
full = results[0]["Version"] # e.g. "0.98.1-2"
ver, _, rel = full.rpartition("-")
return ver, int(rel) if rel.isdigit() else 1
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--build-info", required=True)
ap.add_argument("--template", required=True)
ap.add_argument("--out", required=True)
ap.add_argument("--gh-owner", required=True)
ap.add_argument("--gh-repo", default="jasp-desktop-bin")
ap.add_argument("--maintainer", required=True)
ap.add_argument("--pkgname", default="jasp-desktop-bin")
args = ap.parse_args()
info = json.loads(open(args.build_info).read())
jasp_version = info["jasp_version"]
published = current_aur_version(args.pkgname)
if published and published[0] == jasp_version:
pkgrel = published[1] + 1
print(f"rebuild of {jasp_version}: pkgrel {published[1]} -> {pkgrel}")
else:
pkgrel = 1
print(f"new version {jasp_version}: pkgrel 1")
tag = f"v{jasp_version}-{pkgrel}"
download_url = (
f"https://github.com/{args.gh_owner}/{args.gh_repo}"
f"/releases/download/{tag}/{info['tarball']}"
)
qt_minor = info["qt6_minor"]
substitutions = {
"@MAINTAINER@": args.maintainer,
"@JASP_VERSION@": jasp_version,
"@JASP_TAG@": info["jasp_tag"],
"@JASP_COMMIT@": info["jasp_commit"],
"@PKGREL@": str(pkgrel),
"@BUNDLED_R@": info["bundled_r_version"],
"@QT_MINOR@": qt_minor,
"@DOWNLOAD_URL@": download_url,
"@SHA256@": info["sha256"],
}
text = open(args.template).read()
for key, value in substitutions.items():
text = text.replace(key, value)
leftover = re.findall(r"@[A-Z0-9_]+@", text)
if leftover:
print(f"error: unsubstituted placeholders: {sorted(set(leftover))}", file=sys.stderr)
return 1
with open(args.out, "w") as fh:
fh.write(text)
# Consumed by the release + AUR-push steps of the workflow.
with open("release-meta.json", "w") as fh:
json.dump({"tag": tag, "pkgrel": pkgrel, "download_url": download_url, **info}, fh, indent=2)
print(f"wrote {args.out} ({args.pkgname} {jasp_version}-{pkgrel})")
print(f" R bundled at {info['bundled_r_version']}; built against Qt {qt_minor}")
print(" depends are unpinned - everything volatile is bundled")
return 0
if __name__ == "__main__":
sys.exit(main())