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 '
|
archlinux:base-devel bash -lc '
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
pacman -Syu --noconfirm git jq python libarchive neovim tmux
|
pacman -Syu --noconfirm git jq python libarchive neovim tmux
|
||||||
|
python tests/owe-package-restart.py
|
||||||
python tests/oma-service-removal.py
|
python tests/oma-service-removal.py
|
||||||
python tests/upstream-watch.py
|
python tests/upstream-watch.py
|
||||||
bash tests/ipu7-install.sh
|
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
|
# Maintainer: owe contributors
|
||||||
pkgname=owe
|
pkgname=owe
|
||||||
pkgver=0.2.10
|
pkgver=0.2.10
|
||||||
pkgrel=3
|
pkgrel=4
|
||||||
pkgdesc="High-performance wallpaper engine for Omarchy (mp4, gif, stills)"
|
pkgdesc="High-performance wallpaper engine for Omarchy (mp4, gif, stills)"
|
||||||
arch=('x86_64' 'aarch64')
|
arch=('x86_64' 'aarch64')
|
||||||
url="https://github.com/omacom/owe"
|
url="https://github.com/omacom/owe"
|
||||||
@@ -12,9 +12,13 @@ checkdepends=('python')
|
|||||||
optdepends=('intel-media-driver: VAAPI hardware decode on Intel GPUs'
|
optdepends=('intel-media-driver: VAAPI hardware decode on Intel GPUs'
|
||||||
'libva-mesa-driver: VAAPI hardware decode on AMD 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"
|
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'
|
sha256sums=('b171397c24c0ffd6096781b3f744f674055a57f660a74db07a3b71a111a6980b'
|
||||||
'3ebf413093922b0917bca60c42720c6424c77b1695317364bf73f9fd745376d8')
|
'3ebf413093922b0917bca60c42720c6424c77b1695317364bf73f9fd745376d8'
|
||||||
|
'aee4a08132f0528575d3b7364defc070b8af1648cc48559238ba089c09504b62'
|
||||||
|
'ef1fc780425343623c4a4ddd36cc58cd89ba8a71c528641f4b421db834a349cd')
|
||||||
|
|
||||||
prepare() {
|
prepare() {
|
||||||
cd "$srcdir/owe-$pkgver"
|
cd "$srcdir/owe-$pkgver"
|
||||||
@@ -43,6 +47,8 @@ check() {
|
|||||||
|
|
||||||
package() {
|
package() {
|
||||||
DESTDIR="$pkgdir" ninja -C build install
|
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"
|
install -d "$pkgdir/usr/lib/systemd/user"
|
||||||
sed 's|%h/.local/bin/owed|/usr/bin/owed|' "$srcdir/owe-$pkgver/systemd/owed.service" \
|
sed 's|%h/.local/bin/owed|/usr/bin/owed|' "$srcdir/owe-$pkgver/systemd/owed.service" \
|
||||||
>"$pkgdir/usr/lib/systemd/user/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