fix(fleet): verify update status before removing readiness cards (#1697)

* fix(fleet): verify update status before removing readiness cards

Full-stack Apply now rechecks persisted status after the health gate starts, reloads the live preview before dropping a card, and invalidates the hub fleet aggregation so cleared updates cannot resurrect from a stale cache.

Closes #1686

* fix(fleet): align persisted update status with preview semver detection

Share digest-plus-tag detection so post-Apply sidebar status matches Fleet and Anatomy.

* fix(fleet): keep tag-only updates advisory for Compose automation

Expose digestUpdate vs tagUpdate from checkImage so scheduled and API auto-update only apply same-tag digest drift Compose can pull.

* docs: clarify scheduled auto-update applies digest drift only

Document that higher pinned tags stay advisory until Compose is changed, matching schedule and Run Now behavior.

* docs: require Compose pin edits for higher-tag advisories

Stop recommending Apply now or Update as remedies that cannot rewrite a pinned image tag.

* docs: clarify Apply now pulls pinned tags only

Align the detection-cadence bullet with digest-rebuild vs higher-tag guidance.

* fix(fleet): keep tag advisories after apply and scheduled updates

Tag-only previews were treated as cleared on Fleet reload, and scheduled/
Run Now paths wiped status without rechecking. Align post-update verification
with the manual Apply path (health gate first, recheck, no blind clear) and
block digest apply when sibling image checks failed.

* fix(fleet): clear eslint unused-arg and containers assignment
This commit is contained in:
Anso
2026-07-26 03:09:21 -04:00
committed by GitHub
parent bb7c76ba46
commit 719180f156
16 changed files with 1320 additions and 74 deletions
@@ -40,6 +40,19 @@ export function recordAutoUpdateImageCheck(
}
}
/**
* Operator message when a sibling image check failed and a full-stack Compose
* update must not run (it would pull/recreate the unverified image as
* collateral). Null when digest apply may proceed.
*/
export function messageWhenDigestApplyBlockedByCheckErrors(
stackName: string,
state: Pick<AutoUpdateDigestGateState, 'hasDigestUpdate' | 'checkErrors'>,
): string | null {
if (!state.hasDigestUpdate || state.checkErrors.length === 0) return null;
return `Stack "${stackName}": WARNING - digest update available but ${state.checkErrors.length} image check(s) failed; skipped auto-update (${state.checkErrors.join('; ')}).`;
}
/** Operator message when no digest-actionable update was found. */
export function messageWhenNoDigestUpdate(
stackName: string,