feat: real release notes, restart button, reliable .run installer (0.0.10)
release / release (push) Successful in 14s

- feat(ci): set each Gitea release body from the matching CHANGELOG section
  (was hardcoded "Automated release for…")
- feat(updater): show "What's new" — release notes dialog before applying (GUI)
  and in `rigdoctor update` (CLI); fetch_latest/update_state now return notes
- feat(gui): "Restart now" button relaunches the app after an update is applied
- fix(packaging): build the self-extracting .run with a pure-Python extractor
  (packaging/make_run.py) instead of makeself, so it attaches to every release
  (it was silently skipped before)
- chore: adopt Conventional Commits + git-cliff (cliff.toml, packaging/
  changelog.sh) for changelog generation going forward (D20)
- chore(gui): drop internal module refs (M4, M5, …) from Setup descriptions

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-21 18:31:28 +02:00
parent ca4bc4c64f
commit f3021c4ddb
15 changed files with 240 additions and 68 deletions
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env sh
# Regenerate CHANGELOG.md from Conventional Commits using git-cliff (D20).
# Install once: pip install git-cliff (ships prebuilt binaries)
# Usage: packaging/changelog.sh [--tag vX.Y.Z]
set -eu
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
cd "$ROOT"
command -v git-cliff >/dev/null 2>&1 || {
echo "git-cliff not found. Install it: pip install git-cliff"
exit 1
}
if [ "${1:-}" = "--tag" ] && [ -n "${2:-}" ]; then
git-cliff --tag "$2" -o CHANGELOG.md
else
git-cliff -o CHANGELOG.md
fi
echo "Wrote CHANGELOG.md"
+2 -32
View File
@@ -1,33 +1,3 @@
#!/usr/bin/env sh
# Build a self-extracting .run installer: bundles the wheel + install.sh so a user
# can download one file, run it, and get a no-root user-local install.
#
# Requires `makeself` (apt install makeself). Run from the repo root.
set -eu
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
cd "$ROOT"
command -v makeself >/dev/null 2>&1 || {
echo "makeself not found. Install it: sudo apt install makeself"
exit 1
}
VERSION=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
mkdir -p dist
# Build the wheel if it isn't already in dist/.
if ! ls dist/rigdoctor-"$VERSION"-py3-none-any.whl >/dev/null 2>&1; then
python3 -m build --wheel
fi
STAGE=$(mktemp -d)
cp dist/rigdoctor-"$VERSION"-py3-none-any.whl "$STAGE"/
cp install.sh "$STAGE"/install.sh
chmod +x "$STAGE/install.sh"
OUT="dist/rigdoctor-$VERSION-installer.run"
makeself --notemp-suffix "$STAGE" "$OUT" "RigDoctor $VERSION installer" ./install.sh
rm -rf "$STAGE"
echo "Built $OUT"
echo "Run it with: chmod +x $OUT && ./$OUT"
# Build the self-extracting .run installer (delegates to make_run.py — no makeself).
exec python3 "$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)/make_run.py" "$@"
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""Build a dependency-free self-extracting .run installer (no makeself).
Produces dist/rigdoctor-<version>-installer.run: a POSIX shell stub with an appended
tar.gz of the wheel + install.sh. Running it extracts to a temp dir and runs install.sh.
"""
from __future__ import annotations
import io
import os
import subprocess
import sys
import tarfile
import tomllib
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
MARKER = "__RIGDOCTOR_ARCHIVE__"
STUB = f"""#!/bin/sh
# RigDoctor self-extracting installer. Extracts the embedded archive and runs install.sh.
set -eu
SKIP=$(awk '/^{MARKER}$/ {{ print NR + 1; exit 0 }}' "$0")
TMP=$(mktemp -d)
tail -n +"$SKIP" "$0" | tar -xz -C "$TMP"
sh "$TMP/install.sh" "$@"
RET=$?
rm -rf "$TMP"
exit $RET
{MARKER}
"""
def main() -> int:
version = tomllib.loads((ROOT / "pyproject.toml").read_text())["project"]["version"]
dist = ROOT / "dist"
dist.mkdir(exist_ok=True)
wheel = dist / f"rigdoctor-{version}-py3-none-any.whl"
if not wheel.exists():
subprocess.run([sys.executable, "-m", "build", "--wheel"], cwd=ROOT, check=True)
if not wheel.exists():
print(f"wheel not found: {wheel}", file=sys.stderr)
return 1
buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode="w:gz") as tar:
tar.add(wheel, arcname=wheel.name)
tar.add(ROOT / "install.sh", arcname="install.sh")
out = dist / f"rigdoctor-{version}-installer.run"
with open(out, "wb") as f:
f.write(STUB.encode())
f.write(buf.getvalue())
os.chmod(out, 0o755)
print(f"Built {out}")
return 0
if __name__ == "__main__":
raise SystemExit(main())