scripts(backup-notifications): unify push + email format across VDS/RUVDS/windows-host
3 host-pipelines (VDS bash, RUVDS+windows-host ps1) had drifted formats: ntfy title `VDS backup OK $D` vs `RUVDS backup OK ($D)`, tags `white_check_mark` vs `green_circle`, email subject `[VDS] backup OK` vs `RUVDS backup -- SUCCESS`. Phone-side фильтрация и desktop reading ломались за счёт inconsistency. Unified to: - ntfy push: title `<HOST> backup OK <date>`, body `<duration_human>, size=<>, snapshots=<>, dest=kreknin:<>`, tags `green_circle` (OK) / `red_circle` (FAILED). - email: subject `[<HOST>] backup <STATUS> <date>` (STATUS=OK|FAILED), body — structured Date/Duration/Size/Snapshots/Source/Dest/Components/Log. Failure body extends with `Tail (last 40 lines)`. Also imports VDS `run.sh` into repo as `scripts/vds-backup-rsync-kreknin/` — closes drift из общего `scripts/<slug>/` pattern (RUVDS+windows-host уже жили там; VDS жил только на /opt/stacks/backup/scripts/). Deploy status: - VDS: deployed via scp + sudo install, sha256=27b09ca272bb, smoke ntfy+email ✓ - RUVDS: deployed via scp + Move-Item, sha256=f3bb57a86af5, smoke ntfy+email ✓ - windows-host: deploy.ps1 + smoke-notify.ps1 готовы в scripts/, **pending elevated PS у user'а** (ACL=SYSTEM+Administrators, не пишется без UAC). Spec + decisions + completed: .tasks/unify-backup-notifications.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
127
.tasks/unify-backup-notifications.md
Normal file
127
.tasks/unify-backup-notifications.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# unify-backup-notifications
|
||||
|
||||
## Goal
|
||||
|
||||
Привести notification-формат всех 3 backup-pipelines (VDS, RUVDS, windows-host) к единому виду: **один формат для ntfy push** + **один формат для email**. Сейчас у каждого хоста свой стиль — subject `[VDS] backup OK` vs `RUVDS backup -- SUCCESS` vs `windows-host backup -- SUCCESS`, тэги `white_check_mark` vs `green_circle`, body — то 1 строка с MSG, то структурированный block. На phone-side фильтрация и desktop-side чтение должны быть predictable.
|
||||
|
||||
Параллельно — закрыть drift VDS-скрипта от общего pattern'а: RUVDS+windows-host лежат в `scripts/<task-slug>/run.ps1` локально, VDS жил только на remote (`/opt/stacks/backup/scripts/run.sh`). Импортирую как `scripts/vds-backup-rsync-kreknin/run.sh` (canonical source), правлю локально, deploy.
|
||||
|
||||
## Scope (что меняем — TOLKO notification block, backup-logic не трогаем)
|
||||
|
||||
### Push (ntfy) — единый формат, 1 строка
|
||||
|
||||
**Топик:** `vds-backup` (уже общий для 3 хостов).
|
||||
**Tags:** `green_circle` (OK) / `red_circle` (FAILED).
|
||||
**Priority:** `default` / `high`.
|
||||
|
||||
```
|
||||
Title: <HOST> backup OK <date>
|
||||
Body: <duration_human>, size=<size>, snapshots=<count>, dest=kreknin:<path>
|
||||
|
||||
Title: <HOST> backup FAILED <date>
|
||||
Body: After <duration_human>: <error>. See <logpath>
|
||||
```
|
||||
|
||||
Где `<HOST>` ∈ {`VDS`, `RUVDS`, `windows-host`}.
|
||||
`<duration_human>` = `Xm YYs` (e.g. `21m07s`, `0m45s`).
|
||||
|
||||
### Email — единый формат, structured multi-line
|
||||
|
||||
**Subject:** `[<HOST>] backup <STATUS> <date>` где `STATUS` ∈ {`OK`, `FAILED`}.
|
||||
|
||||
**Body (success):**
|
||||
|
||||
```
|
||||
<HOST> daily backup completed successfully.
|
||||
|
||||
Date: <date>
|
||||
Duration: <duration_human>
|
||||
Size: <size>
|
||||
Snapshots: <count>
|
||||
Source: <hostname> (<ip>)
|
||||
Dest: kreknin:<path>
|
||||
|
||||
Components:
|
||||
- <component 1>
|
||||
- <component 2>
|
||||
...
|
||||
|
||||
Log: <log-path>
|
||||
```
|
||||
|
||||
**Body (failure):**
|
||||
|
||||
```
|
||||
<HOST> daily backup FAILED.
|
||||
|
||||
Date: <date>
|
||||
Duration: <duration_human>
|
||||
Error: <error>
|
||||
Source: <hostname> (<ip>)
|
||||
Log: <log-path>
|
||||
|
||||
Tail (last 40 lines):
|
||||
<tail>
|
||||
```
|
||||
|
||||
## Key files
|
||||
|
||||
- `scripts/vds-backup-rsync-kreknin/run.sh` — bash, deployed to VDS `/opt/stacks/backup/scripts/run.sh`. Functions: `notify()` (ntfy), `email_send()` (msmtp). Callers — line 122-123 (success) + 49-53 (failure).
|
||||
- `scripts/ruvds-backup-daily-kreknin/run.ps1` — PS1, deployed to RUVDS `C:\ProgramData\backup\run.ps1`. Functions: `Notify-Ntfy` + `Notify-Email`. Callers — line 140-161 (success) + 169-170 (failure).
|
||||
- `scripts/windows-host-fallback-backup-daily/run.ps1` — PS1, deployed to windows-host `C:\ProgramData\backup\run.ps1`. Same function names. Callers — line 169-189 (success) + 197-198 (failure).
|
||||
|
||||
## Implementation steps
|
||||
|
||||
1. Edit VDS `run.sh`: добавить `[<HOST>] backup <STATUS> <date>` email-subject, structured body для success+failure, ntfy tags на `green_circle`/`red_circle`.
|
||||
2. Edit RUVDS `run.ps1`: переписать success+failure ntfy+email callers под унифицированный format. Поменять subject на `[RUVDS] backup OK <date>` etc.
|
||||
3. Edit windows-host `run.ps1`: same.
|
||||
4. Deploy:
|
||||
- windows-host: `Copy-Item scripts/windows-host-.../run.ps1 → C:\ProgramData\backup\run.ps1` (elevated; user может потребоваться UAC).
|
||||
- RUVDS: `scp` to `C:\ProgramData\backup\run.ps1` через ssh-key.
|
||||
- VDS: `scp` + `sudo install` to `/opt/stacks/backup/scripts/run.sh`.
|
||||
5. Smoke: вызвать `notify` + `email_send` (или их PS-аналог) с mock success-data на каждом хосте — не запускать полный backup (21-80 min), только проверить, что новые format-strings проходят через каналы.
|
||||
6. Verify user-side: phone ntfy app получил, gmail получил, форматы единые.
|
||||
7. Commit + push.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- [x] 3 scripts в `scripts/` имеют идентичный notification-block (modulo language: bash vs ps1).
|
||||
- [x] ntfy push для всех 3: title = `<HOST> backup OK <date>`, body = `<duration>, size=<>, snapshots=<>, dest=kreknin:<>`, tags `green_circle`.
|
||||
- [x] Email subject для всех 3: `[<HOST>] backup OK <date>`. Body — единый template.
|
||||
- [x] Failure path: title `<HOST> backup FAILED <date>`, subject `[<HOST>] backup FAILED <date>`, tags `red_circle`, body — единый.
|
||||
- [x] Smoke от VDS + RUVDS через notify-channels: push приходит, email приходит. (2026-05-25, см. completed steps)
|
||||
- [ ] Smoke от windows-host — **deferred** (user-decision 2026-05-25: пропустить smoke, доверяем parser-проверке).
|
||||
- [ ] **Deploy на windows-host pending** — user сделает elevated PS позже. До deploy'а windows-host остаётся на pre-unify формате.
|
||||
- [ ] User-verify: phone ntfy уведомления — TEST из VDS + RUVDS пришли, format читается?
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [x] **2026-05-25:** spec написана + STATUS.md обновлён, task 🔴 active.
|
||||
- [x] **2026-05-25:** VDS `run.sh` импортирован из `vds.kzntsv.site:/opt/stacks/backup/scripts/run.sh` в `scripts/vds-backup-rsync-kreknin/run.sh` — closes drift из общего `scripts/<slug>/` pattern.
|
||||
- [x] **2026-05-25:** 3 scripts edited: VDS bash + RUVDS ps1 + WHOST ps1. Notify helpers (`notify`/`Notify-Ntfy`/`Notify-Email`) сохранены, callers переписаны под unified format. Parser-check ✓ всех 3 (bash -n / `[Parser]::ParseFile`).
|
||||
- [x] **2026-05-25:** VDS deployed: `scp /tmp/run.sh.new` + `sudo install -m 755 -o root -g root` → `/opt/stacks/backup/scripts/run.sh`. SHA256=`27b09ca272bb` match. Backup pre-unify в `.bak-pre-unify`.
|
||||
- [x] **2026-05-25:** RUVDS deployed: `scp` → `C:\ProgramData\backup\run.ps1.new` → `Move-Item -Force`. SHA256=`f3bb57a86af5` match. Backup в `.bak-pre-unify`.
|
||||
- [x] **2026-05-25:** VDS smoke notify ✓: ntfy + email sent с TEST-prefix через `bash -c "source .env; ..."` snippet.
|
||||
- [x] **2026-05-25:** RUVDS smoke notify ✓: SCP + run `smoke-notify.ps1` → `ntfy_ok` + `email_ok`.
|
||||
- [x] **2026-05-25:** windows-host `smoke-notify.ps1` + `deploy.ps1` подготовлены в `scripts/windows-host-fallback-backup-daily/`. **Pending elevated execution user'ом.**
|
||||
|
||||
## Decisions log
|
||||
|
||||
- **2026-05-25** (task creation): выбран `green_circle`/`red_circle` поверх `white_check_mark`/`warning` (VDS-default). Reason: visually distinct на phone, RUVDS+windows-host уже используют circle-style.
|
||||
- **2026-05-25**: `OK` вместо `SUCCESS` в subject — shorter, у VDS уже было `OK`.
|
||||
- **2026-05-25**: square brackets в subject ([HOST]) — у VDS уже было, читается лучше при filter'е в gmail.
|
||||
- **2026-05-25**: Failure body — sequential для всех 3 (Date / Duration / Error / Source / Log / Tail). У VDS уже был tail-of-log; экстендим на RUVDS+WHOST.
|
||||
- **2026-05-25**: VDS `run.sh` импортирован в repo как `scripts/vds-backup-rsync-kreknin/run.sh` — closes drift из общего pattern (`scripts/<slug>/`). Deploy = scp + sudo install обратно на VDS.
|
||||
|
||||
## Open questions
|
||||
|
||||
- [ ] **Snapshots count для RUVDS/WHOST.** VDS делает `ls -1d $DEST_BASE/20*-*-* | wc -l` через SSH. RUVDS/WHOST используют rclone — нужен `rclone lsd | wc -l` или повторное использование `$existing` из retention-prune step. Включим в edit.
|
||||
- [ ] **Size**: VDS = `du -sh dest_path` (post-rsync, accurate), RUVDS/WHOST = source bytes Get-ChildItem. Standardize? Слишком expensive делать `rclone size` на dest (extra round-trip). **Решение:** keep source bytes для RUVDS/WHOST, dest du для VDS — оба отображают «size of dataset» одинаково adequately. В email можно подписать как `Size: <X> GB`, не различая источник.
|
||||
- [ ] **Source IP/hostname**: hardcode (VDS=`89.253.255.94`, RUVDS=`80.64.31.36`, windows-host=`94.19.247.14`) vs `$(hostname -I)` / `$env:COMPUTERNAME`. Hardcode — short-term, проще; для prod-grade нужен detect.
|
||||
|
||||
## Notes
|
||||
|
||||
- **Связано:** `vds-backup-rsync-kreknin` 🟢, `ruvds-backup-daily-kreknin` 🟢, `windows-host-fallback-backup-daily` 🟢 — все 3 продакшн уже работают. Эта таска — cosmetic + observability unification, не функциональная.
|
||||
- **Атомарный revert:** `git revert HEAD` + redeploy 3-х previous scripts. Pre-edit content закоммичен.
|
||||
|
||||
<!-- created-by: vitya / 2026-05-25 / trigger: user-decision — unify push+email across VDS/RUVDS/windows-host -->
|
||||
Reference in New Issue
Block a user