mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-21 23:56:39 +00:00
fix: reconcile sticky update indicators with Anatomy preview (#1698)
* fix: reconcile sticky update indicators with Anatomy preview Sidebar, Updates filter, and Fleet treated retained partial/failed scanner has_update as confirmed. Keep raw state for retention/notifications, project confirmed-only to APIs, show distinct incomplete indicators, and clear sticky rows only after an authoritative-negative preview. Closes #1685 * test: align sidebar truncate E2E with failed-over-retained precedence Purple update indicators are confirmed-only; hasUpdate with a failed check correctly shows the failed trailing icon. * fix: clear confirmed update rows on authoritative-negative preview Address audit SF-1/SF-2/SF-3: observation-watermark clears for older ok+has_update rows (DB + memory gens), Fleet checkability parity with backend not_checkable, and Updates chip confirmed-only regressions. * fix: tombstone equal-generation writers on preview clear Advance the per-stack write generation when clearing at the observation watermark so a scanner reserved before preview cannot recreate the row after an authoritative-negative reconcile. * fix: clear sticky updates with digest and tag preview parity Share detection across scanner and preview, keep GET read-only with POST reconcile, gate Apply to digest and rebuild updates, and invalidate the hub fleet cache on clear. * test: set digestUpdate on auto-update checkImage mocks Scheduler and execute routes now gate Compose on digest drift; fixtures that expect an apply need digestUpdate so they exercise the update path. * fix: clear unused lint errors on sticky update branch Drop unused partial helper and fleet invalidate import; keep the CacheService inflight self-ref as let with an eslint exception so tsc stays green. * fix: use inflight holder for CacheService prefer-const Keep generation-aware ownership without a let self-reference that fights ESLint and tsc.
This commit is contained in:
@@ -149,6 +149,69 @@ components:
|
||||
type: boolean
|
||||
example: true
|
||||
|
||||
UpdatePreviewImage:
|
||||
type: object
|
||||
required:
|
||||
[service, image, current_tag, next_tag, has_update, digest_update, tag_update, semver_bump, check_status]
|
||||
properties:
|
||||
service: { type: string }
|
||||
image: { type: string }
|
||||
current_tag: { type: string }
|
||||
next_tag: { type: ["string", "null"] }
|
||||
has_update: { type: boolean }
|
||||
digest_update:
|
||||
type: boolean
|
||||
description: Same-tag registry content drift; Compose pull can apply without changing the pin.
|
||||
tag_update:
|
||||
type: boolean
|
||||
description: A higher pinned semver exists; advisory until Compose is edited.
|
||||
semver_bump:
|
||||
type: string
|
||||
enum: [none, unknown, patch, minor, major]
|
||||
check_status:
|
||||
type: string
|
||||
enum: [ok, partial, failed, not_checkable]
|
||||
|
||||
UpdatePreviewSummary:
|
||||
type: object
|
||||
required:
|
||||
[has_update, primary_image, current_tag, next_tag, semver_bump, update_kind, blocked, blocked_reason, has_build_services, rebuild_available, check_status]
|
||||
properties:
|
||||
has_update: { type: boolean }
|
||||
primary_image: { type: ["string", "null"] }
|
||||
current_tag: { type: ["string", "null"] }
|
||||
next_tag: { type: ["string", "null"] }
|
||||
semver_bump:
|
||||
type: string
|
||||
enum: [none, unknown, patch, minor, major]
|
||||
update_kind:
|
||||
type: string
|
||||
enum: [tag, digest, none]
|
||||
blocked: { type: boolean }
|
||||
blocked_reason: { type: ["string", "null"] }
|
||||
has_build_services: { type: boolean }
|
||||
rebuild_available: { type: boolean }
|
||||
check_status:
|
||||
type: string
|
||||
enum: [ok, partial, failed]
|
||||
|
||||
UpdatePreview:
|
||||
type: object
|
||||
required: [stack_name, images, build_services, summary, rollback_target, changelog]
|
||||
properties:
|
||||
stack_name: { type: string }
|
||||
images:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/UpdatePreviewImage"
|
||||
build_services:
|
||||
type: array
|
||||
items: { type: string }
|
||||
summary:
|
||||
$ref: "#/components/schemas/UpdatePreviewSummary"
|
||||
rollback_target: { type: ["string", "null"] }
|
||||
changelog: { type: ["string", "null"] }
|
||||
|
||||
LabelSource:
|
||||
type: string
|
||||
description: Provenance of a label. `unknown` when a container or image could not be inspected.
|
||||
@@ -1788,6 +1851,68 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/InternalError"
|
||||
|
||||
/api/stacks/{stackName}/update-preview:
|
||||
get:
|
||||
operationId: getStackUpdatePreview
|
||||
tags: [Stacks]
|
||||
summary: Compute image update preview (read-only)
|
||||
description: |
|
||||
Computes the current registry update preview for the stack without
|
||||
mutating persisted scanner state. Use POST when the client should
|
||||
reconcile sticky update indicators after an authoritative-negative
|
||||
result. Requires `stack:read` permission.
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/stackName"
|
||||
- $ref: "#/components/parameters/nodeId"
|
||||
responses:
|
||||
"200":
|
||||
description: Update preview.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/UpdatePreview"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"500":
|
||||
$ref: "#/components/responses/InternalError"
|
||||
post:
|
||||
operationId: reconcileStackUpdatePreview
|
||||
tags: [Stacks]
|
||||
summary: Compute update preview and reconcile sticky state
|
||||
description: |
|
||||
Computes the same preview as GET. When every image reports
|
||||
`check_status: ok` and `has_update` is false (mixed `ok` +
|
||||
`not_checkable` does not clear), clears sticky confirmed update rows
|
||||
for the stack and sets `reconciled: true`. Requires `stack:read`
|
||||
permission.
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/stackName"
|
||||
- $ref: "#/components/parameters/nodeId"
|
||||
responses:
|
||||
"200":
|
||||
description: Update preview, with reconcile outcome.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/UpdatePreview"
|
||||
- type: object
|
||||
required: [reconciled]
|
||||
properties:
|
||||
reconciled:
|
||||
type: boolean
|
||||
description: |
|
||||
True when sticky update rows were cleared after an
|
||||
authoritative-negative preview.
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"500":
|
||||
$ref: "#/components/responses/InternalError"
|
||||
|
||||
/api/stacks/{stackName}/update-readiness:
|
||||
get:
|
||||
operationId: getStackUpdateReadiness
|
||||
|
||||
Reference in New Issue
Block a user