mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-26 11:49:16 +00:00
feat: add cron scheduling mode for image update checks (#1460)
* feat: add cron scheduling mode for image update checks Adds a cron scheduling mode alongside the existing fixed-interval dropdown in Settings > Automation > Image update checks. Users can now set a 5-field cron expression (e.g. "0 3 * * 1") for precise time-of-day scheduling of registry polls. - Backend: ImageUpdateService gains mode/cronExpression fields and cron-based nextDelayMs() using the existing cron-parser dependency. PUT /api/image-updates/interval extended with transactional writes and server-authoritative cron validation matching the Scheduled Operations contract. Nicknames like @daily are supported. - Frontend: UpdatesSection gains a SegmentedControl toggle and cron text input with cronstrue-powered live description. The frontend does advisory validation only; backend 400s are surfaced inline. SettingsPrimaryButton used for explicit "Save schedule" action. - No cron jitter (the user chose a specific time). Interval mode keeps existing ±10% jitter. - Tests: 15 new backend tests covering valid cron, invalid cron, 6-field rejection, nickname support, backward compat, runtime fallback, and transactional writes. - Docs: auto-update-policies.mdx, alerts-notifications.mdx, and openapi.yaml updated with new scheduling mode. * fix: add mode and cronExpression to UpdatesSection test fixtures The existing tests failed because the mock status object was missing the new required fields (mode, cronExpression) added with cron scheduling support. Without them, status.mode was undefined, causing uiMode to never match 'interval' and the Select combobox to not render. * fix: prevent SegmentedControl from stretching full-width in SettingsField The flex-col container defaults items to align-self: stretch, making the Interval/Cron toggle bar span the full card width. Add self-start so it sizes to its content.
This commit is contained in:
@@ -384,7 +384,7 @@ The **Host Alerts** panel also carries the **Host thresholds** rows (CPU limit,
|
||||
| Crash, OOM, and healthcheck events | Real-time over the Docker event stream |
|
||||
| Host CPU / RAM / disk threshold checks | 30 seconds |
|
||||
| Per-stack alert rule evaluation | 30 seconds |
|
||||
| Image update poll | 6 hours, with a 2-minute startup delay and a 2-minute cooldown on manual refresh |
|
||||
| Image update poll | Configurable (default every 2 hours), with a 2-minute startup delay and a 2-minute cooldown on manual refresh |
|
||||
| Sencho version check | 6 hours |
|
||||
| Notification fanout to channels | Single shot per dispatch, 10-second timeout, no retries |
|
||||
| Bell live updates | Pushed live over the notifications WebSocket per node |
|
||||
|
||||
@@ -33,7 +33,7 @@ When nothing is pending, the board renders a single Shield-icon panel with the h
|
||||
|
||||
## Detection cadence
|
||||
|
||||
Sencho polls your registries on a set interval to detect available image updates and raise notifications. This detection cadence is configurable under **Settings > Automation > Image update checks**: choose anything from every 15 minutes to once a day. The default is every 2 hours, and changing it takes effect immediately, with no restart.
|
||||
Sencho polls your registries on a configurable schedule to detect available image updates and raise notifications. This detection cadence is configurable under **Settings > Automation > Image update checks**: choose a fixed interval (every 15 minutes to once a day) or set a cron expression for precise scheduling (e.g. "every Monday at 03:00"). The default is every 2 hours on an interval schedule, and changing it takes effect immediately, with no restart.
|
||||
|
||||
Detection is separate from applying updates:
|
||||
|
||||
|
||||
+73
-9
@@ -516,6 +516,35 @@ components:
|
||||
type: ["integer", "null"]
|
||||
description: Unix timestamp of the last check.
|
||||
|
||||
ImageUpdateCheckStatus:
|
||||
type: object
|
||||
properties:
|
||||
checking:
|
||||
type: boolean
|
||||
description: "`true` if a scan is currently running."
|
||||
intervalMinutes:
|
||||
type: integer
|
||||
description: Configured fallback interval in minutes (15-1440).
|
||||
lastCheckedAt:
|
||||
type: ["integer", "null"]
|
||||
description: Unix epoch-ms of the last check start, or null if never checked.
|
||||
nextCheckAt:
|
||||
type: ["integer", "null"]
|
||||
description: Unix epoch-ms of the next scheduled check, or null when not scheduled.
|
||||
manualCooldownMinutes:
|
||||
type: integer
|
||||
description: Fixed cooldown ceiling in minutes for manual refresh.
|
||||
manualCooldownRemainingMs:
|
||||
type: integer
|
||||
description: Live remaining cooldown in milliseconds (0 when refresh is allowed).
|
||||
mode:
|
||||
type: string
|
||||
enum: [interval, cron]
|
||||
description: Active scheduling mode.
|
||||
cronExpression:
|
||||
type: ["string", "null"]
|
||||
description: 5-field cron expression when mode is 'cron', null otherwise.
|
||||
|
||||
responses:
|
||||
Unauthorized:
|
||||
description: Authentication required. Provide a valid Bearer token.
|
||||
@@ -3118,19 +3147,54 @@ paths:
|
||||
get:
|
||||
operationId: getImageUpdateCheckStatus
|
||||
tags: [Image Updates]
|
||||
summary: Check if update scan is running
|
||||
description: Returns whether an image update check is currently in progress.
|
||||
summary: Get scanner cadence status
|
||||
description: Returns the scanner's current status including scheduling mode and next check time.
|
||||
responses:
|
||||
"200":
|
||||
description: Check status.
|
||||
description: Scanner status.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [checking]
|
||||
properties:
|
||||
checking:
|
||||
type: boolean
|
||||
description: "`true` if a scan is currently running."
|
||||
$ref: "#/components/schemas/ImageUpdateCheckStatus"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
|
||||
/api/image-updates/interval:
|
||||
put:
|
||||
operationId: setImageUpdateCheckSchedule
|
||||
tags: [Image Updates]
|
||||
summary: Set the detection schedule
|
||||
description: Configure the image-update check cadence. In interval mode only `minutes` is required. In cron mode also send `mode` and `cron`.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [minutes]
|
||||
properties:
|
||||
minutes:
|
||||
type: integer
|
||||
minimum: 15
|
||||
maximum: 1440
|
||||
description: Fallback interval in minutes (used in interval mode, or as fallback when cron is unset).
|
||||
mode:
|
||||
type: string
|
||||
enum: [interval, cron]
|
||||
description: Scheduling mode. Omit to leave unchanged.
|
||||
cron:
|
||||
type: string
|
||||
description: 5-field cron expression (required when mode is 'cron'). Nicknames like @daily are accepted.
|
||||
responses:
|
||||
"200":
|
||||
description: Schedule updated.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ImageUpdateCheckStatus"
|
||||
"400":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
description: Non-admin users cannot change the schedule.
|
||||
|
||||
Reference in New Issue
Block a user