Skip to content

Commit cd5032f

Browse files
committed
docs: v0.12.0 - image updates, auto-heal, richer startup
1 parent 3e1af25 commit cd5032f

7 files changed

Lines changed: 122 additions & 8 deletions

File tree

.claude/structure/monitors.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,34 @@ files:
212212
imports:
213213
- from: src.config
214214
items: [MemoryConfig]
215+
216+
image_update_monitor.py:
217+
description: Polls Docker registries for image digest changes, deduplicates across polls, sends batched update alert with Pull buttons
218+
exports:
219+
- name: extract_local_digests
220+
kind: function
221+
description: Return sha256 digests from a container's RepoDigests
222+
params: [{name: container, type: Any}]
223+
returns: list[str]
224+
225+
- name: ImageUpdateMonitor
226+
kind: class
227+
description: Poll loop that checks opted-in containers for newer registry images and emits a batched digest alert
228+
methods:
229+
- name: start
230+
params: []
231+
returns: Awaitable[None]
232+
- name: stop
233+
params: []
234+
returns: None
235+
- name: is_running
236+
params: []
237+
returns: bool
238+
239+
imports:
240+
- from: src.config
241+
items: [ImageUpdatesConfig]
242+
- from: src.alerts.manager
243+
items: [AlertSender]
244+
- from: src.services.docker_client
245+
items: [SharedDockerClient]

.claude/structure/services.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,25 @@ files:
199199
items: [format_uptime]
200200
- from: src.utils.sanitize
201201
items: [sanitize_container_name, sanitize_logs]
202+
203+
auto_healer.py:
204+
description: Auto-restarts opted-in containers that report HEALTHCHECK unhealthy, with per-container time-windowed storm guard
205+
exports:
206+
- name: AutoHealer
207+
kind: class
208+
description: Checks opt-in list and protected containers, tracks restart counts in a rolling window, restarts or escalates
209+
methods:
210+
- name: is_enabled
211+
params: [{name: container_name, type: str}]
212+
returns: bool
213+
- name: heal
214+
params: [{name: container_name, type: str}]
215+
returns: Awaitable[None]
216+
217+
imports:
218+
- from: src.config
219+
items: [AutoHealConfig]
220+
- from: src.services.container_control
221+
items: [ContainerController]
222+
- from: src.alerts.manager
223+
items: [AlertSender]

.claude/structure/utils.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,24 @@ files:
151151
items: [TypeVar, Callable, Awaitable, ParamSpec]
152152
- from: aiogram.exceptions
153153
items: [TelegramRetryAfter, TelegramAPIError]
154+
155+
version_store.py:
156+
description: Read/write data/announced_version.json atomically to persist the last-announced bot version for the startup What's new gate.
157+
exports:
158+
- name: read_announced_version
159+
kind: function
160+
description: Return the last-announced bot version string, or None if unset or unreadable
161+
params: [{name: path, type: str}]
162+
returns: str | None
163+
- name: write_announced_version
164+
kind: function
165+
description: Atomically persist the given version string to the announced_version file
166+
params: [{name: path, type: str}, {name: version, type: str}]
167+
returns: None
168+
imports:
169+
- from: json
170+
items: [json]
171+
- from: pathlib
172+
items: [Path]
173+
- from: tempfile
174+
items: [tempfile]

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
All notable changes to UnraidMonitor will be documented in this file.
44

5+
## [0.12.0] - 2026-06-03
6+
7+
### Added
8+
- **Image-update detection** (opt-in: `image_updates.enabled`) — polls registries every 24 hours (configurable via `image_updates.poll_interval_hours`), sends a batched digest alert when newer images are available, with per-container Pull buttons
9+
- **Auto-heal** (opt-in: `auto_heal.containers`) — automatically restarts opted-in containers that report a Docker HEALTHCHECK `unhealthy` status; storm guard prevents restart loops (configurable `max_restarts` / `window_minutes`); protected containers are never touched
10+
- **Richer startup message** — on first boot after a version upgrade, shows a "What's new" section with user-facing highlights; persists last-announced version to `data/announced_version.json`
11+
- **CI test pipeline** — GitHub Actions workflow runs tests, ruff lint, and mypy type-check on every push and pull request
12+
513
## [0.11.1] - 2026-05-17
614

715
### Changed

CLAUDE.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ src/monitors/docker_events.py - DockerEventMonitor with CrashTracker for contain
6565
src/monitors/log_watcher.py - LogWatcher for streaming container logs, error detection
6666
src/monitors/resource_monitor.py - ResourceMonitor for per-container CPU/memory polling
6767
src/monitors/memory_monitor.py - MemoryMonitor for system memory pressure management
68+
src/monitors/image_update_monitor.py - ImageUpdateMonitor for daily image digest polling and batched update alerts
6869

6970
# Services
7071
src/services/docker_client.py - SharedDockerClient wrapper for reconnectable Docker access
@@ -73,6 +74,7 @@ src/services/nl_tools.py - Tool definitions and executor for Claude tool use
7374
src/services/container_control.py - ContainerController for safe restart/stop/start
7475
src/services/container_classifier.py - ContainerClassifier using patterns and AI for roles
7576
src/services/diagnostic.py - DiagnosticService for AI container log analysis
77+
src/services/auto_healer.py - AutoHealer for opt-in auto-restart of unhealthy containers with storm guard
7678

7779
# Unraid
7880
src/unraid/client.py - UnraidClientWrapper with direct GraphQL API access
@@ -85,10 +87,11 @@ src/utils/formatting.py - Bytes/uptime formatting, safe_reply/safe_edit, format_
8587
src/utils/rate_limiter.py - PerUserRateLimiter for per-user API rate limiting
8688
src/utils/sanitize.py - Prompt injection prevention, sensitive data redaction
8789
src/utils/telegram_retry.py - Telegram API retry logic for rate limit handling
90+
src/utils/version_store.py - read/write data/announced_version.json for startup What's new gate (atomic)
8891

8992
## Project Overview
9093

91-
Unraid Server Monitor Bot (v0.11.1) - A Docker-based Telegram bot for monitoring Unraid servers. Monitors Docker containers (events, logs, resources) and Unraid server health (CPU, memory, disks, array, UPS). Uses multi-provider LLM support (Anthropic, OpenAI, Ollama) for AI-powered diagnostics and natural language interaction. Sends alerts via Telegram with quick-action buttons.
94+
Unraid Server Monitor Bot (v0.12.0) - A Docker-based Telegram bot for monitoring Unraid servers. Monitors Docker containers (events, logs, resources) and Unraid server health (CPU, memory, disks, array, UPS). Uses multi-provider LLM support (Anthropic, OpenAI, Ollama) for AI-powered diagnostics and natural language interaction. Sends alerts via Telegram with quick-action buttons.
9295

9396
## Commands
9497

@@ -191,6 +194,7 @@ Inline keyboard buttons use `prefix:data` format, parsed with `split(":", 1)` to
191194
- `srv_set:metric:value` (apply server threshold, e.g., `srv_set:cpu_temp:90`, 0 = reset to default)
192195
- `model:provider_name`, `model_select:provider:model`, `model:back`
193196
- `setup:confirm`, `setup:toggle:category:container_name` (e.g., `setup:toggle:watched:plex`), `setup:adjust:category`, `setup:adjust_done`
197+
- `pull:container_name` (image-update digest -> shows pull confirmation)
194198

195199
Callback handlers are registered with `F.data.startswith("prefix:")` filters in `register_commands()`.
196200

@@ -266,8 +270,10 @@ Environment variables can also be set via `config/.env` (loaded by pydantic-sett
266270
- `protected_containers` / `ignored_containers` - Safety and visibility controls
267271
- `memory_management` - System memory pressure thresholds and kill policy
268272
- `resource_monitoring` - Per-container CPU/memory alert thresholds
273+
- `image_updates` - Opt-in daily digest of containers with newer images (enabled, poll_interval_hours)
274+
- `auto_heal` - Opt-in auto-restart of unhealthy containers (enabled, containers, max_restarts, window_minutes)
269275

270-
Data files in `data/`: `mutes.json`, `server_mutes.json`, `array_mutes.json`, `ignored_errors.json`, `model_selection.json` (runtime LLM choice), `chat_ids.json` (persistent Telegram chat IDs for alert delivery)
276+
Data files in `data/`: `mutes.json`, `server_mutes.json`, `array_mutes.json`, `ignored_errors.json`, `model_selection.json` (runtime LLM choice), `chat_ids.json` (persistent Telegram chat IDs for alert delivery), `announced_version.json` (last-announced bot version for startup What's new gate)
271277

272278
## Design Context
273279

README.md

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,21 @@ A Telegram bot for monitoring Docker containers and Unraid servers. Get real-tim
1212
- **Smart Ignore Patterns** - AI-generated patterns to filter known errors, with interactive toggle selection
1313
- **Multi-Provider LLM** - Switch between Anthropic Claude, OpenAI GPT, or local Ollama models at runtime
1414
- **Container Control** - Start, stop, restart, and pull containers with inline confirmation buttons
15+
- **Image-Update Detection** - Opt-in daily digest of containers with newer images available, with Pull buttons
16+
- **Auto-Heal** - Opt-in automatic restart of unhealthy containers (HEALTHCHECK failures) with storm guard
1517
- **Unraid Server Monitoring** - CPU/memory, temperatures, UPS status, and array health
1618
- **Memory Pressure Management** - Automatic container priority handling during high memory
1719
- **Mute System** - Temporarily silence alerts per container, server, or array
1820
- **Natural Language Chat** - Ask questions naturally instead of using commands
1921
- **Interactive Dashboard** - `/manage` hub for status, resources, ignores, and mutes
2022
- **Sectioned Help** - `/help` with navigable category buttons instead of a text wall
2123

22-
## What's New in v0.11.0
24+
## What's New in v0.12.0
2325

24-
- **Server alert action buttons** (v0.10.0) - CPU temperature and usage alerts now include Mute and Adjust Threshold buttons, matching the UX of container and array alerts
25-
- **Model family system** (v0.10.0) - Use family names like `sonnet`, `haiku`, `opus` instead of dated model IDs; per-feature model switching with `/model chat sonnet`, `/model diagnose haiku`
26-
- **Dynamic provider resolution** (v0.10.1-0.10.3) - `/model` changes take effect immediately, config persistence fixes, and tool-call translation fixes for Anthropic API
27-
- **Security hardening** (v0.11.0) - Prompt injection defense for LLM inputs, SSRF protection in setup wizard, race condition fixes in memory monitor, crash tracker memory leak fix, and tighter file permissions
26+
- **Image-update detection** - Opt-in daily digest of containers with newer images available, with per-container Pull buttons (`image_updates.enabled: true`)
27+
- **Auto-heal** - Opt-in automatic restart of containers that fail their Docker HEALTHCHECK, with a storm guard that gives up after configurable retries (`auto_heal.containers: [...]`)
28+
- **Richer startup message** - On first boot after an upgrade, shows a "What's new" summary so you always know what changed
29+
- **CI test pipeline** - Tests, lint, and type-check now run automatically on every push and pull request
2830

2931
See the [changelog](CHANGELOG.md) for full details.
3032

@@ -350,6 +352,30 @@ unraid:
350352
ups_battery: 30 # Alert below this %
351353
```
352354
355+
### Image-Update Detection
356+
357+
Checks once per day (configurable) whether a newer image is available for watched containers. Sends a single batched digest message with Pull buttons. Disabled by default — opt in per-deployment.
358+
359+
```yaml
360+
image_updates:
361+
enabled: false # Set true to enable daily image-update checks
362+
poll_interval_hours: 24 # How often to check (minimum 1)
363+
```
364+
365+
### Auto-Heal
366+
367+
Automatically restarts containers that report a Docker HEALTHCHECK `unhealthy` status. A per-container storm guard gives up after `max_restarts` within `window_minutes` and sends an escalation alert. Protected containers are never touched regardless of this setting.
368+
369+
```yaml
370+
auto_heal:
371+
enabled: true # Master switch
372+
containers: # List of container names to auto-heal (opt-in)
373+
- radarr
374+
- sonarr
375+
max_restarts: 3 # Give up after this many restarts in the window
376+
window_minutes: 60 # Rolling window for the restart count
377+
```
378+
353379
---
354380

355381
## Commands

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "unraid-monitor-bot"
3-
version = "0.11.1"
3+
version = "0.12.0"
44
requires-python = ">=3.11"
55
dependencies = [
66
"docker>=7.0.0,<8.0.0",

0 commit comments

Comments
 (0)