#!/usr/bin/env python3 """Build the pacman package and publish a Gitea release for the current version. Usage: GITEA_TOKEN=... packaging/release.py Requires a clean working tree and the tag v already pushed. The release notes are taken from CHANGELOG.md and contain the package's SHA-256, which the built-in updater uses to verify downloads. """ import hashlib import json import os import re import subprocess import sys import urllib.request ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) API = "https://git.mrblake.cc/api/v1/repos/MrBlake/Cachy-Predator-Keyboard" def api(method, path, data=None, ctype="application/json"): headers = {"Authorization": "token " + os.environ["GITEA_TOKEN"]} if data is not None: headers["Content-Type"] = ctype req = urllib.request.Request(API + path, data=data, method=method, headers=headers) return json.load(urllib.request.urlopen(req)) def main(): if "GITEA_TOKEN" not in os.environ: sys.exit("set GITEA_TOKEN") version = re.search(r'__version__ = "([^"]+)"', open(os.path.join(ROOT, "predator_control/__init__.py")).read())[1] pkgbuild = open(os.path.join(ROOT, "packaging/arch/PKGBUILD")).read() if "pkgver=%s\n" % version not in pkgbuild: sys.exit("PKGBUILD pkgver does not match version %s" % version) pkgrel = re.search(r"^pkgrel=(\d+)", pkgbuild, re.M)[1] arch_dir = os.path.join(ROOT, "packaging/arch") subprocess.run(["makepkg", "-f", "--cleanbuild"], cwd=arch_dir, check=True) pkg = "predator-control-%s-%s-any.pkg.tar.zst" % (version, pkgrel) data = open(os.path.join(arch_dir, pkg), "rb").read() sha = hashlib.sha256(data).hexdigest() changelog = open(os.path.join(ROOT, "CHANGELOG.md")).read() notes = changelog.split("## %s" % version, 1)[1].split("\n## ", 1)[0].split("\n", 1)[1].strip() body = notes + f""" ### Install (Arch / CachyOS / Manjaro) ```bash sudo pacman -S --needed linux-cachyos-headers clang lld llvm # stock Arch kernel: linux-headers sudo pacman -U {pkg} ``` Already installed via pacman? Use the built-in updater (System page, panel widget or `predatorctl update`). SHA-256 `{pkg}`: `{sha}` Not affiliated with Acer Inc.""" rel = api("POST", "/releases", json.dumps({ "tag_name": "v" + version, "name": "Predator Control " + version, "body": body, "draft": False, "prerelease": False}).encode()) boundary = "----predator" + sha[:16] mp = (f'--{boundary}\r\nContent-Disposition: form-data; name="attachment"; filename="{pkg}"\r\n' f"Content-Type: application/octet-stream\r\n\r\n").encode() + data + f"\r\n--{boundary}--\r\n".encode() api("POST", "/releases/%d/assets?name=%s" % (rel["id"], pkg), mp, "multipart/form-data; boundary=" + boundary) print("Released", rel["html_url"]) print("SHA-256", sha) if __name__ == "__main__": main()