Add daemon mode for background checks with systemd support

- Added daemon command with --interval, --pid-file, --since flags
- Configurable check interval (s/m/h/d format)
- PID file for status checking
- Graceful shutdown on SIGTERM/SIGINT
- Structured logging to stderr for systemd journal
- Updated README with daemon docs and systemd service template
- Added daemon tests (parse_interval, PID file, help)
This commit is contained in:
2026-07-28 12:05:07 +02:00
parent 2a5f11bd9b
commit 959d068474
3 changed files with 248 additions and 0 deletions
+55
View File
@@ -75,6 +75,61 @@ class TestCliList:
assert "No repositories" in result.stdout
class TestParseInterval:
def test_seconds(self):
from src.cli import parse_interval
assert parse_interval("60s") == 60
def test_minutes(self):
from src.cli import parse_interval
assert parse_interval("30m") == 1800
def test_hours(self):
from src.cli import parse_interval
assert parse_interval("2h") == 7200
def test_days(self):
from src.cli import parse_interval
assert parse_interval("1d") == 86400
def test_invalid_format(self):
from src.cli import parse_interval
with pytest.raises(SystemExit):
parse_interval("invalid")
class TestCliDaemon:
def test_daemon_help(self):
result = subprocess.run(
[sys.executable, "-m", "src.cli", "daemon", "--help"],
capture_output=True, text=True
)
assert result.returncode == 0
assert "interval" in result.stdout.lower()
assert "pid-file" in result.stdout.lower()
def test_daemon_pid_file_write(self, tmp_path):
"""Test that daemon PID file writing works correctly."""
import os
from pathlib import Path
pid_file = Path(tmp_path / "daemon.pid")
pid_file.parent.mkdir(parents=True, exist_ok=True)
# Test PID file writing logic directly
pid_file.write_text(str(os.getpid()))
assert pid_file.exists()
assert pid_file.read_text() == str(os.getpid())
pid_file.unlink()
assert not pid_file.exists()
def test_cmd_check_for_daemon_empty(self, tmp_path):
"""Test daemon check with no repos (no error raised)."""
db_path = str(tmp_path / "test.db")
from src.cli import cmd_check_for_daemon
cmd_check_for_daemon(db_path) # Should not raise
class TestCliAddRemove:
def test_add_invalid_format(self, tmp_path):
db_path = str(tmp_path / "test.db")