Files
MrBlakeandClaude Opus 5.5 cc4fdb9cd0 Add built-in updater, bump to 1.2.0
- predatord checks the Gitea releases every 6 hours, downloads the
  newest pacman package, verifies its SHA-256 from the release notes
  and installs it with `pacman -U` in a separate systemd unit
- Update notice and install button on the System page, in the sidebar
  and in the panel widget; `predatorctl update [--check] [--yes]`
- Optional API token for private repositories
- packaging/release.py builds and publishes releases in the format
  the updater expects

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 17:42:02 +02:00

73 lines
2.8 KiB
Python
Executable File

#!/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<version> 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()