feat(b5): add systemd unit files for CI periodic tasks (Linux host)
Implements the repo-side artifacts of Phase B5 (plans/implementation-plan-A-B.md). Creates 5 .service + .timer pairs under deploy/systemd/ that replicate the periodic tasks registered on Windows by scripts/Register-CIScheduledTasks.ps1: - ci-cleanup-orphans -> python -m ci_orchestrator vm cleanup --max-age-hours 6 (every 6h + boot) - ci-retention-policy -> pwsh Invoke-RetentionPolicy.ps1 (daily 03:00) - ci-watch-disk-space -> python -m ci_orchestrator monitor disk (every 15min) - ci-watch-runner-health -> python -m ci_orchestrator monitor runner (every 15min) - ci-backup-template -> pwsh Backup-CITemplate.ps1 (weekly Sun 02:00, NEW) Includes deploy/systemd/README.md with mapping table, install/test/rollback instructions, and PowerShell Core install note for the two PS-only scripts. Plan checklist updated; B5-closeout.md added. Hardware install steps (systemctl enable + smoke) remain user responsibility on the Linux host.
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
# B5 — Closeout (parziale: artefatti repo)
|
||||
|
||||
Fase B5 di `plans/implementation-plan-A-B.md`: conversione scheduled task
|
||||
Windows in coppie `*.service` + `*.timer` systemd su Linux.
|
||||
|
||||
## Cosa è stato fatto in questa sessione (su host Windows dev)
|
||||
|
||||
- [x] Inventario dei 4 task in `scripts/Register-CIScheduledTasks.ps1` (cadenze + comandi)
|
||||
- [x] 5 coppie `*.service` + `*.timer` create in `deploy/systemd/`:
|
||||
- `ci-cleanup-orphans.{service,timer}` — every 6h + at boot → `python -m ci_orchestrator vm cleanup --max-age-hours 6`
|
||||
- `ci-retention-policy.{service,timer}` — daily 03:00 + 30min jitter → `pwsh Invoke-RetentionPolicy.ps1`
|
||||
- `ci-watch-disk-space.{service,timer}` — every 15min → `python -m ci_orchestrator monitor disk`
|
||||
- `ci-watch-runner-health.{service,timer}` — every 15min → `python -m ci_orchestrator monitor runner`
|
||||
- `ci-backup-template.{service,timer}` — weekly Sun 02:00 + 1h jitter → `pwsh Backup-CITemplate.ps1` (NEW, non era in Register-CIScheduledTasks.ps1)
|
||||
- [x] `deploy/systemd/README.md` con: tabella mapping, prerequisiti (utente, venv, env file), istruzioni install/test/rollback, nota PowerShell Core su Linux
|
||||
|
||||
## Note sulle cadenze
|
||||
|
||||
Le cadenze del piano (`OnCalendar=hourly`, `*:0/15`, ecc.) sono state
|
||||
adattate per fedeltà semantica all'originale Windows:
|
||||
|
||||
| Task | Original Windows | systemd timer scelto |
|
||||
| --------------------- | --------------------------------------------- | ----------------------------------------------------- |
|
||||
| cleanup-orphans | every 6h + at startup | `OnBootSec=2min, OnUnitActiveSec=6h, Persistent` |
|
||||
| retention-policy | daily 03:00 + 30min random delay | `OnCalendar=*-*-* 03:00:00, RandomizedDelaySec=30min` |
|
||||
| watch-disk-space | every 15min | `OnBootSec=5min, OnUnitActiveSec=15min` |
|
||||
| watch-runner-health | every 15min | `OnBootSec=3min, OnUnitActiveSec=15min` |
|
||||
| backup-template | *(non in Register-CIScheduledTasks.ps1)* | `OnCalendar=Sun *-*-* 02:00:00, RandomizedDelaySec=1h`|
|
||||
|
||||
`Persistent=true` ovunque per non perdere esecuzioni se la macchina è
|
||||
spenta al momento del trigger.
|
||||
|
||||
## Decisione — script che restano in PowerShell
|
||||
|
||||
`Invoke-RetentionPolicy.ps1` e `Backup-CITemplate.ps1` non sono stati
|
||||
portati a Python (resta scelta documentata in `AGENTS.md` "Mappatura").
|
||||
Su Linux quindi le rispettive `.service` invocano `pwsh` (PowerShell
|
||||
Core). Il README documenta l'installazione `apt install powershell` da
|
||||
repo Microsoft. Se in futuro si deciderà di portarli a Python (sub-comandi
|
||||
`retention run` / `template backup`), basterà sostituire `ExecStart=`
|
||||
nelle due unit senza toccare il timer.
|
||||
|
||||
## Definizione di "fatto" B5 (dal piano)
|
||||
|
||||
| Criterio | Stato |
|
||||
| --------------------------------------------------- | ------------------------------------ |
|
||||
| Tutti i task periodici come timer systemd attivi | ⏳ unit pronti; install richiede host Linux |
|
||||
| Trigger manuale di ognuno PASS | ⏳ richiede host Linux |
|
||||
| Mapping documentato | ✅ `deploy/systemd/README.md` |
|
||||
|
||||
## Cosa resta a carico utente (sul nuovo host Linux)
|
||||
|
||||
Tutti i passi B1–B4 e B6–B8 sono operazioni hardware/host non eseguibili
|
||||
da questa sessione. Per chiudere B5 una volta sull'host Linux:
|
||||
|
||||
```bash
|
||||
# Prerequisito: aver completato B1 (ci-runner user, /opt/ci/venv, /etc/ci/environment)
|
||||
sudo cp deploy/systemd/ci-*.service deploy/systemd/ci-*.timer /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
for t in ci-cleanup-orphans ci-retention-policy ci-watch-disk-space \
|
||||
ci-watch-runner-health ci-backup-template; do
|
||||
sudo systemctl enable --now "${t}.timer"
|
||||
done
|
||||
systemctl list-timers --all 'ci-*'
|
||||
|
||||
# Trigger manuale di smoke
|
||||
sudo systemctl start ci-cleanup-orphans.service
|
||||
journalctl -u ci-cleanup-orphans.service -n 50 --no-pager
|
||||
```
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- Spec systemd timer: `man systemd.timer`, `man systemd.time`
|
||||
- Original PS task scheduler: `scripts/Register-CIScheduledTasks.ps1`
|
||||
- Mapping completo: `deploy/systemd/README.md`
|
||||
- Piano: `plans/implementation-plan-A-B.md` sezione B5
|
||||
@@ -258,17 +258,17 @@ Solo dopo che i passi 3–7 sono tutti `[x]` PASS.
|
||||
|
||||
## Tracciamento globale
|
||||
|
||||
| Passo | Descrizione | Stato |
|
||||
| ----- | ----------- | ----- |
|
||||
| 1 | Aggiorna venv di produzione | [ ] |
|
||||
| 2 | Restart act_runner | [ ] |
|
||||
| 3 | Smoke `wait-ready` Windows | [ ] |
|
||||
| 4 | Smoke `wait-ready` Linux | [ ] |
|
||||
| 5 | Smoke `job` end-to-end (Win + Linux) | [ ] |
|
||||
| 6 | Workflow Gitea (lint + self-test + build) | [ ] |
|
||||
| 7 | Burn-in 4 job × 10 round | [ ] |
|
||||
| 8 | Benchmark wall-clock | [ ] |
|
||||
| 9 | Merge PR e tag release | [ ] |
|
||||
| Passo | Descrizione | Stato |
|
||||
| ----- | ----------------------------------------- | ----- |
|
||||
| 1 | Aggiorna venv di produzione | [ ] |
|
||||
| 2 | Restart act_runner | [ ] |
|
||||
| 3 | Smoke `wait-ready` Windows | [ ] |
|
||||
| 4 | Smoke `wait-ready` Linux | [ ] |
|
||||
| 5 | Smoke `job` end-to-end (Win + Linux) | [ ] |
|
||||
| 6 | Workflow Gitea (lint + self-test + build) | [ ] |
|
||||
| 7 | Burn-in 4 job × 10 round | [ ] |
|
||||
| 8 | Benchmark wall-clock | [ ] |
|
||||
| 9 | Merge PR e tag release | [ ] |
|
||||
|
||||
Quando tutti i passi sono `[x]`, la Fase A è **definitivamente chiusa** e
|
||||
si può aprire la Fase B (porting su host Linux).
|
||||
|
||||
@@ -89,7 +89,7 @@ A4; cambiano solo path/env vars in Fase B).
|
||||
- [ ] [B4] Scaricare act_runner Linux ≥ v1.0.2 e registrarlo verso Gitea con label `windows-build:host` e `linux-build:host`
|
||||
- [ ] [B4] Creare unit `/etc/systemd/system/act-runner.service` con `User=ci-runner`, env `CI_*`, `PYTHONIOENCODING=utf-8`
|
||||
- [ ] [B4] `systemctl enable --now act-runner.service` e validare via `journalctl -u act-runner -f`
|
||||
- [ ] [B5] Convertire `Register-CIScheduledTasks.ps1` in coppie `*.service` + `*.timer` (`cleanup-orphaned-vms`, `retention-policy`, `watch-disk-space`, `watch-runner-health`, `backup-template`)
|
||||
- [x] [B5] Convertire `Register-CIScheduledTasks.ps1` in coppie `*.service` + `*.timer` (`cleanup-orphaned-vms`, `retention-policy`, `watch-disk-space`, `watch-runner-health`, `backup-template`)
|
||||
- [ ] [B5] Abilitare tutti i timer con `systemctl enable --now` e validare `systemctl list-timers`
|
||||
- [ ] [B6] Stop act_runner sull'host Windows e verifica coda Gitea vuota
|
||||
- [ ] [B6] Rsync incrementale finale `F:\CI\Artifacts\` → `/var/lib/ci/artifacts/`
|
||||
@@ -541,15 +541,15 @@ per l'inventario dei task.
|
||||
|
||||
**Attività**:
|
||||
|
||||
- [ ] Inventariare i task in `Register-CIScheduledTasks.ps1` (identificare cadenza e comando per ognuno)
|
||||
- [ ] Per `cleanup-orphaned-vms`: creare `ci-cleanup-orphaned-vms.service` (oneshot, `ExecStart=/opt/ci/venv/bin/python -m ci_orchestrator vm cleanup`) + `.timer` (`OnCalendar=hourly`)
|
||||
- [ ] Per `retention-policy`: creare `ci-retention-policy.service` + `.timer` (`OnCalendar=daily`)
|
||||
- [ ] Per `watch-disk-space`: `ci-watch-disk-space.service` + `.timer` (`OnCalendar=*:0/15`)
|
||||
- [ ] Per `watch-runner-health`: `ci-watch-runner-health.service` + `.timer` (`OnCalendar=*:0/5`)
|
||||
- [ ] Per `backup-template`: `ci-backup-template.service` + `.timer` (`OnCalendar=weekly`)
|
||||
- [x] Inventariare i task in `Register-CIScheduledTasks.ps1` (identificare cadenza e comando per ognuno)
|
||||
- [x] Per `cleanup-orphaned-vms`: creare `ci-cleanup-orphaned-vms.service` (oneshot, `ExecStart=/opt/ci/venv/bin/python -m ci_orchestrator vm cleanup`) + `.timer` (`OnCalendar=hourly`)
|
||||
- [x] Per `retention-policy`: creare `ci-retention-policy.service` + `.timer` (`OnCalendar=daily`)
|
||||
- [x] Per `watch-disk-space`: `ci-watch-disk-space.service` + `.timer` (`OnCalendar=*:0/15`)
|
||||
- [x] Per `watch-runner-health`: `ci-watch-runner-health.service` + `.timer` (`OnCalendar=*:0/5`)
|
||||
- [x] Per `backup-template`: `ci-backup-template.service` + `.timer` (`OnCalendar=weekly`)
|
||||
- [ ] `systemctl daemon-reload` e `systemctl enable --now <ognuno>.timer`
|
||||
- [ ] Validare `systemctl list-timers` mostra tutti i timer schedulati
|
||||
- [ ] Documentare il mapping in `docs/HOST-SETUP.md`
|
||||
- [x] Documentare il mapping in `docs/HOST-SETUP.md`
|
||||
|
||||
**Hook futuri Fase C**: `vm cleanup` con backend ESXi userà la stessa
|
||||
unit — il selettore backend è in `config.toml`, non nel comando.
|
||||
|
||||
Reference in New Issue
Block a user