78cd417d0b
packaging/make_deb.py builds rigdoctor_<ver>_all.deb (Architecture: all) via dpkg-deb, no debhelper: Depends python3; Recommends python3-pyside6/pyte (GUI by default, --no-install-recommends = CLI only). Installs the package, both launchers, desktop entry + icon; postinst refreshes the desktop database. release.yml builds it as a release asset and optionally pushes to the Gitea apt registry (REGISTRY_TOKEN). Verified locally: valid .deb, packaged launcher runs 'rigdoctor --version'. Docs/README/ROADMAP/MODULES updated; M9 complete. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
"""Build a `.deb` for RigDoctor (M9 / D8) — dependency-light, no debhelper.
|
|
|
|
Pure-Python app, so it's `Architecture: all`: we stage the package into dist-packages, drop the
|
|
two launchers in /usr/bin, install the desktop entry + icon, write a DEBIAN/control, and call
|
|
`dpkg-deb`. The core is stdlib (`Depends: python3`); the GUI/tray deps are **Recommends**
|
|
(`python3-pyside6`, `python3-pyte`) so `apt install rigdoctor` gives the full app by default,
|
|
while `--no-install-recommends` yields a CLI-only install.
|
|
|
|
Run: `python packaging/make_deb.py` → `dist/rigdoctor_<version>_all.deb`.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
DIST = ROOT / "dist"
|
|
MAINTAINER = "Jessey van Offeren <jjvanofferen@gmail.com>"
|
|
HOMEPAGE = "https://git.jesseyvanofferen.com/jessey/rigdoctor"
|
|
|
|
|
|
def _version() -> str:
|
|
text = (ROOT / "src" / "rigdoctor" / "__init__.py").read_text(encoding="utf-8")
|
|
for line in text.splitlines():
|
|
if line.startswith("__version__"):
|
|
return line.split('"')[1]
|
|
raise SystemExit("could not read __version__")
|
|
|
|
|
|
_LAUNCHER = """\
|
|
#!/usr/bin/python3
|
|
import sys
|
|
from {module} import main
|
|
sys.exit(main())
|
|
"""
|
|
|
|
_DESKTOP = """\
|
|
[Desktop Entry]
|
|
Type=Application
|
|
Name=RigDoctor
|
|
Comment=Hardware monitoring & crash diagnostics for Linux gamers
|
|
Exec=rigdoctor-gui
|
|
Icon=rigdoctor
|
|
Terminal=false
|
|
Categories=System;Monitor;Utility;
|
|
StartupWMClass=rigdoctor
|
|
"""
|
|
|
|
_CONTROL = """\
|
|
Package: rigdoctor
|
|
Version: {version}
|
|
Architecture: all
|
|
Maintainer: {maintainer}
|
|
Section: utils
|
|
Priority: optional
|
|
Depends: python3 (>= 3.11)
|
|
Recommends: python3-pyside6, python3-pyte
|
|
Homepage: {homepage}
|
|
Description: Hardware monitoring & crash diagnostics for Linux gamers
|
|
RigDoctor monitors GPU/CPU temperatures, load, and sensors, captures crash
|
|
diagnostics while gaming, scans logs (Xid/SMART/kernel) for problems, and can
|
|
explain them in plain language. The CLI and background daemon are pure Python
|
|
(stdlib only); the optional desktop GUI and system-tray applet use PySide6,
|
|
pulled in via Recommends. Install with --no-install-recommends for CLI only.
|
|
"""
|
|
|
|
|
|
def _write(path: Path, text: str, mode: int = 0o644) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(text, encoding="utf-8")
|
|
path.chmod(mode)
|
|
|
|
|
|
def build() -> Path:
|
|
version = _version()
|
|
DIST.mkdir(exist_ok=True)
|
|
stage = DIST / f"rigdoctor_{version}_all"
|
|
if stage.exists():
|
|
shutil.rmtree(stage)
|
|
|
|
# Python package → dist-packages (importable system-wide), minus bytecode.
|
|
pkg_dst = stage / "usr/lib/python3/dist-packages/rigdoctor"
|
|
shutil.copytree(ROOT / "src" / "rigdoctor", pkg_dst,
|
|
ignore=shutil.ignore_patterns("__pycache__", "*.pyc"))
|
|
|
|
# Launchers.
|
|
_write(stage / "usr/bin/rigdoctor", _LAUNCHER.format(module="rigdoctor.cli"), 0o755)
|
|
_write(stage / "usr/bin/rigdoctor-gui", _LAUNCHER.format(module="rigdoctor.gui.app"), 0o755)
|
|
|
|
# Desktop entry + icon.
|
|
_write(stage / "usr/share/applications/rigdoctor.desktop", _DESKTOP)
|
|
icon = ROOT / "src" / "rigdoctor" / "gui" / "assets" / "rigdoctor.svg"
|
|
_write(stage / "usr/share/icons/hicolor/scalable/apps/rigdoctor.svg",
|
|
icon.read_text(encoding="utf-8"))
|
|
|
|
# Refresh the desktop database on install/remove (best-effort).
|
|
_write(stage / "DEBIAN/postinst",
|
|
"#!/bin/sh\nset -e\nupdate-desktop-database -q 2>/dev/null || true\n", 0o755)
|
|
_write(stage / "DEBIAN/postrm",
|
|
"#!/bin/sh\nset -e\nupdate-desktop-database -q 2>/dev/null || true\n", 0o755)
|
|
_write(stage / "DEBIAN/control",
|
|
_CONTROL.format(version=version, maintainer=MAINTAINER, homepage=HOMEPAGE))
|
|
|
|
out = DIST / f"rigdoctor_{version}_all.deb"
|
|
subprocess.run(["dpkg-deb", "--root-owner-group", "--build", str(stage), str(out)], check=True)
|
|
shutil.rmtree(stage)
|
|
return out
|
|
|
|
|
|
if __name__ == "__main__":
|
|
path = build()
|
|
print(f"built {path}")
|
|
sys.exit(0)
|