Restart active OWE user services after upgrades (#888)
This commit is contained in:
1 parent
3e4cb2308e
commit
f3e71f8a13
5 files changed
+134
-3
No files matched your search
@@ -48,6 +48,7 @@ jobs:
|
||||
archlinux:base-devel bash -lc '
|
||||
set -euo pipefail
|
||||
pacman -Syu --noconfirm git jq python libarchive neovim tmux
|
||||
python tests/owe-package-restart.py
|
||||
python tests/oma-service-removal.py
|
||||
python tests/upstream-watch.py
|
||||
bash tests/ipu7-install.sh
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
[Trigger]
|
||||
Operation = Upgrade
|
||||
Type = Package
|
||||
Target = owe
|
||||
|
||||
[Action]
|
||||
Description = Restarting active OWE user services...
|
||||
When = PostTransaction
|
||||
Exec = /usr/lib/owe/package-restart
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: owe contributors
|
||||
pkgname=owe
|
||||
pkgver=0.2.10
|
||||
pkgrel=3
|
||||
pkgrel=4
|
||||
pkgdesc="High-performance wallpaper engine for Omarchy (mp4, gif, stills)"
|
||||
arch=('x86_64' 'aarch64')
|
||||
url="https://github.com/omacom/owe"
|
||||
@@ -12,9 +12,13 @@ checkdepends=('python')
|
||||
optdepends=('intel-media-driver: VAAPI hardware decode on Intel GPUs'
|
||||
'libva-mesa-driver: VAAPI hardware decode on AMD GPUs')
|
||||
source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz"
|
||||
'lock-policy-timestamp.patch')
|
||||
'lock-policy-timestamp.patch'
|
||||
'90-owe-restart.hook'
|
||||
'package-restart')
|
||||
sha256sums=('b171397c24c0ffd6096781b3f744f674055a57f660a74db07a3b71a111a6980b'
|
||||
'3ebf413093922b0917bca60c42720c6424c77b1695317364bf73f9fd745376d8')
|
||||
'3ebf413093922b0917bca60c42720c6424c77b1695317364bf73f9fd745376d8'
|
||||
'aee4a08132f0528575d3b7364defc070b8af1648cc48559238ba089c09504b62'
|
||||
'ef1fc780425343623c4a4ddd36cc58cd89ba8a71c528641f4b421db834a349cd')
|
||||
|
||||
prepare() {
|
||||
cd "$srcdir/owe-$pkgver"
|
||||
@@ -43,6 +47,8 @@ check() {
|
||||
|
||||
package() {
|
||||
DESTDIR="$pkgdir" ninja -C build install
|
||||
install -Dm644 "$srcdir/90-owe-restart.hook" "$pkgdir/usr/share/libalpm/hooks/90-owe-restart.hook"
|
||||
install -Dm755 "$srcdir/package-restart" "$pkgdir/usr/lib/owe/package-restart"
|
||||
install -d "$pkgdir/usr/lib/systemd/user"
|
||||
sed 's|%h/.local/bin/owed|/usr/bin/owed|' "$srcdir/owe-$pkgver/systemd/owed.service" \
|
||||
>"$pkgdir/usr/lib/systemd/user/owed.service"
|
||||
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Run after systemd's 30-systemd-daemon-reload-user.hook. Image builds and
|
||||
# offline installations have no running managers and must remain untouched.
|
||||
if systemd-detect-virt --chroot || ! systemd-notify --booted; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
managers=$(systemctl list-units 'user@*.service' --state=running --no-legend --plain) || exit 1
|
||||
result=0
|
||||
while read -r unit _; do
|
||||
[[ $unit =~ ^user@([0-9]+)\.service$ ]] || continue
|
||||
user_id=${BASH_REMATCH[1]}
|
||||
# Use the user's manager rather than pacman's root session. try-restart
|
||||
# never starts a stopped service or changes its enablement.
|
||||
if ! systemctl --user --machine="$user_id@.host" try-restart owed.service; then
|
||||
echo ":: Could not restart OWE for user $user_id; restart owed.service in that user session." >&2
|
||||
result=1
|
||||
fi
|
||||
done <<< "$managers"
|
||||
exit "$result"
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Package restart fixtures; no real systemd managers are contacted."""
|
||||
import hashlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PACKAGE = ROOT / "pkgbuilds/owe"
|
||||
|
||||
|
||||
class Restart(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp = tempfile.TemporaryDirectory(prefix="owe-restart-")
|
||||
self.addCleanup(self.temp.cleanup)
|
||||
self.root = Path(self.temp.name)
|
||||
self.log = self.root / "calls"
|
||||
self.env = dict(os.environ, PATH=f"{self.root}:{os.environ['PATH']}", CALLS=str(self.log))
|
||||
self.command("systemd-detect-virt", 'exit "${CHROOT:-1}"')
|
||||
self.command("systemd-notify", 'exit "${BOOTED:-0}"')
|
||||
self.command("systemctl", '''
|
||||
printf '%s\\n' "$*" >> "$CALLS"
|
||||
case "$1" in
|
||||
list-units)
|
||||
printf '%s\\n' "${MANAGERS:-}"
|
||||
exit "${LIST_FAILED:-0}"
|
||||
;;
|
||||
esac
|
||||
[[ $* != *"--machine=${FAIL_USER:-none}@.host"* ]]
|
||||
''')
|
||||
|
||||
def command(self, name, body):
|
||||
path = self.root / name
|
||||
path.write_text("#!/bin/bash\n" + body + "\n")
|
||||
path.chmod(0o755)
|
||||
|
||||
def run_hook(self, **values):
|
||||
return subprocess.run(["bash", str(PACKAGE / "package-restart")],
|
||||
env=self.env | values, capture_output=True, text=True)
|
||||
|
||||
def calls(self):
|
||||
return self.log.read_text().splitlines() if self.log.exists() else []
|
||||
|
||||
def test_offline_and_chroot_skip_managers(self):
|
||||
for values in ({"CHROOT": "0"}, {"BOOTED": "1"}):
|
||||
with self.subTest(values=values):
|
||||
self.assertEqual(self.run_hook(**values).returncode, 0)
|
||||
self.assertEqual(self.calls(), [])
|
||||
|
||||
def test_no_running_managers(self):
|
||||
self.assertEqual(self.run_hook().returncode, 0)
|
||||
self.assertEqual(len(self.calls()), 1)
|
||||
|
||||
def test_all_running_managers_use_conditional_restart(self):
|
||||
result = self.run_hook(MANAGERS="user@1000.service loaded active running User Manager\nuser@1001.service loaded active running User Manager")
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(self.calls(), [
|
||||
"list-units user@*.service --state=running --no-legend --plain",
|
||||
"--user --machine=1000@.host try-restart owed.service",
|
||||
"--user --machine=1001@.host try-restart owed.service",
|
||||
])
|
||||
|
||||
def test_failure_reports_user_and_continues(self):
|
||||
result = self.run_hook(MANAGERS="user@1000.service loaded active running\nuser@1001.service loaded active running", FAIL_USER="1000")
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("Could not restart OWE for user 1000", result.stderr)
|
||||
self.assertIn("--user --machine=1001@.host try-restart owed.service", self.calls())
|
||||
|
||||
def test_list_failure_is_not_silently_successful(self):
|
||||
self.assertNotEqual(self.run_hook(LIST_FAILED="1").returncode, 0)
|
||||
self.assertEqual(len(self.calls()), 1)
|
||||
|
||||
def test_only_user_manager_units_are_accepted(self):
|
||||
self.assertEqual(self.run_hook(MANAGERS="invalid.service loaded active running\nuser@oops.service loaded active running").returncode, 0)
|
||||
self.assertEqual(len(self.calls()), 1)
|
||||
|
||||
def test_packaged_hook_and_sources(self):
|
||||
hook = (PACKAGE / "90-owe-restart.hook").read_text()
|
||||
self.assertIn("Operation = Upgrade\n", hook)
|
||||
self.assertNotIn("Operation = Install", hook)
|
||||
self.assertNotIn("Operation = Remove", hook)
|
||||
self.assertIn("When = PostTransaction\n", hook)
|
||||
self.assertIn("Exec = /usr/lib/owe/package-restart\n", hook)
|
||||
recipe = (PACKAGE / "PKGBUILD").read_text()
|
||||
for source in ("90-owe-restart.hook", "package-restart"):
|
||||
self.assertIn(hashlib.sha256((PACKAGE / source).read_bytes()).hexdigest(), recipe)
|
||||
self.assertIn('"$pkgdir/usr/share/libalpm/hooks/90-owe-restart.hook"', recipe)
|
||||
self.assertIn('"$pkgdir/usr/lib/owe/package-restart"', recipe)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user