Add systemd timer and desktop notifications #3

Merged
schaefera merged 6 commits from worktree-add-systemd-timer into master 2026-09-20 08:02:07 +00:00
Owner

Why

pkgwatch had no scheduler: it only ran when invoked by hand, so new upstream releases (e.g. Claude Code 2.1.278) sat unnoticed. This adds a user-level systemd timer and desktop notifications so a new release surfaces on its own.

What

  • Timer (systemd/pkgwatch.timer, pkgwatch.service): user-level units that run a check 10s after login, then hourly. Non-persistent, per the spec. The service sets WorkingDirectory=~/dev/pkgwatch because packages.d/, state/ and work/ resolve relative to cwd. There is no RandomizedDelaySec: it applies to every trigger, including the login one, and a single machine has no herd to spread out.
  • Notifications (src/notifier.rs): notify-send when a tier 4-6 release is newly queued for review, or a tier 1-3 release is published. Best-effort: a missing notify-send or session bus only prints a warning and never fails a run. review --approve deliberately doesn't notify, since the operator is already at the terminal.
  • Failures (pkgwatch-failure.service): triggered via OnFailure=, sends a critical notification on any non-zero exit (verification, build or network failure).
  • Test fix (src/test_support.rs): write_executable_script was flaky (~5% of runs) with Text file busy, because a fork on another test thread could hold a copy of the script's write fd during exec. It now probe-execs the script and retries until it is runnable. 150 consecutive runs passed with no failures. This also fixes the existing publisher tests, not just the new notifier one.
  • Docs (docs/SPEC.md): scheduling and notifications are documented with install commands. Per-package check_interval stays listed as unimplemented, since the timer is a fixed tick.

Design notes

  • Why a user unit, not a system one: pkgwatch never needs root (makepkg refuses it, the repo is under ~/.local/share, and install remains a manual sudo pacman -Syu), and desktop notifications need the user's session bus.
  • Tier 4 packages such as claude-code still require pkgwatch review <name> --approve. The notification is what makes that visible.

Testing

cargo fmt --check, cargo clippy --all-targets -- -D warnings and the complexity lint are clean. 91 tests pass, 4 of them new (notifier message wording, stub-binary invocation, missing binary). systemd-analyze verify --user is clean on all three units. Not yet verified: a live notification or a real timer run, since the timer isn't installed.

After merging

From the main checkout:

cargo build --release && mkdir -p ~/.config/systemd/user &&
  cp systemd/* ~/.config/systemd/user/ && systemctl --user daemon-reload &&
  systemctl --user enable --now pkgwatch.timer

Rebuild with cargo build --release after code changes; the service runs target/release/pkgwatch.

🤖 Generated with Claude Code

## Why pkgwatch had no scheduler: it only ran when invoked by hand, so new upstream releases (e.g. Claude Code 2.1.278) sat unnoticed. This adds a user-level systemd timer and desktop notifications so a new release surfaces on its own. ## What - **Timer** (`systemd/pkgwatch.timer`, `pkgwatch.service`): user-level units that run a check 10s after login, then hourly. Non-persistent, per the spec. The service sets `WorkingDirectory=~/dev/pkgwatch` because `packages.d/`, `state/` and `work/` resolve relative to cwd. There is no `RandomizedDelaySec`: it applies to every trigger, including the login one, and a single machine has no herd to spread out. - **Notifications** (`src/notifier.rs`): `notify-send` when a tier 4-6 release is newly queued for review, or a tier 1-3 release is published. Best-effort: a missing `notify-send` or session bus only prints a warning and never fails a run. `review --approve` deliberately doesn't notify, since the operator is already at the terminal. - **Failures** (`pkgwatch-failure.service`): triggered via `OnFailure=`, sends a critical notification on any non-zero exit (verification, build or network failure). - **Test fix** (`src/test_support.rs`): `write_executable_script` was flaky (~5% of runs) with `Text file busy`, because a fork on another test thread could hold a copy of the script's write fd during exec. It now probe-execs the script and retries until it is runnable. 150 consecutive runs passed with no failures. This also fixes the existing `publisher` tests, not just the new notifier one. - **Docs** (`docs/SPEC.md`): scheduling and notifications are documented with install commands. Per-package `check_interval` stays listed as unimplemented, since the timer is a fixed tick. ## Design notes - Why a user unit, not a system one: pkgwatch never needs root (`makepkg` refuses it, the repo is under `~/.local/share`, and install remains a manual `sudo pacman -Syu`), and desktop notifications need the user's session bus. - Tier 4 packages such as claude-code still require `pkgwatch review <name> --approve`. The notification is what makes that visible. ## Testing `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings` and the complexity lint are clean. 91 tests pass, 4 of them new (notifier message wording, stub-binary invocation, missing binary). `systemd-analyze verify --user` is clean on all three units. Not yet verified: a live notification or a real timer run, since the timer isn't installed. ## After merging From the main checkout: ```sh cargo build --release && mkdir -p ~/.config/systemd/user && cp systemd/* ~/.config/systemd/user/ && systemctl --user daemon-reload && systemctl --user enable --now pkgwatch.timer ``` Rebuild with `cargo build --release` after code changes; the service runs `target/release/pkgwatch`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
schaefera added 5 commits 2026-09-20 07:52:53 +00:00
Hourly user-level pkgwatch.timer/.service, an OnFailure= notifier, and a
notifier module that sends notify-send alerts when a tier 4-6 release is
queued for review or a tier 1-3 release is published.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Apply review feedback: docs, doc comment, lifetimes
Some checks failed
CI / build (pull_request) Successful in 39s
CI / audit (pull_request) Has been cancelled
CI / coverage (pull_request) Has been cancelled
CI / test (pull_request) Has been cancelled
38a32a0c60
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
schaefera added 1 commit 2026-09-20 07:54:18 +00:00
Fix ETXTBSY flake in stub-script tests
All checks were successful
CI / build (pull_request) Successful in 37s
CI / test (pull_request) Successful in 2m34s
CI / audit (pull_request) Successful in 11s
CI / coverage (pull_request) Successful in 5m6s
dd42bcbe75
write_executable_script now probe-execs the script and retries on Text
file busy, so it returns only once the script is actually runnable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
claude-bot changed title from worktree-add-systemd-timer to Add systemd timer and desktop notifications 2026-09-20 07:55:02 +00:00
schaefera merged commit b78c5ad9d9 into master 2026-09-20 08:02:07 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: schaefera/pkgwatch#3
No description provided.