mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-08 09:54:26 +00:00
719180f156
* 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
76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
import type { ImageCheckResult } from '../services/ImageUpdateService';
|
|
|
|
/** Accumulator for auto-update image checks (digest vs tag-only vs error). */
|
|
export interface AutoUpdateDigestGateState {
|
|
hasDigestUpdate: boolean;
|
|
hasTagOnlyUpdate: boolean;
|
|
updatedImages: string[];
|
|
checkErrors: string[];
|
|
}
|
|
|
|
export function createAutoUpdateDigestGateState(): AutoUpdateDigestGateState {
|
|
return {
|
|
hasDigestUpdate: false,
|
|
hasTagOnlyUpdate: false,
|
|
updatedImages: [],
|
|
checkErrors: [],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Record one image check into the digest gate. Only digest drift is Compose-
|
|
* actionable for auto-update; tag bumps stay advisory.
|
|
*/
|
|
export function recordAutoUpdateImageCheck(
|
|
state: AutoUpdateDigestGateState,
|
|
imageRef: string,
|
|
result: ImageCheckResult,
|
|
): void {
|
|
if (result.digestUpdate) {
|
|
state.hasDigestUpdate = true;
|
|
state.updatedImages.push(imageRef);
|
|
return;
|
|
}
|
|
if (result.tagUpdate) {
|
|
state.hasTagOnlyUpdate = true;
|
|
return;
|
|
}
|
|
if (result.error || result.checkStatus === 'failed' || result.checkStatus === 'partial') {
|
|
state.checkErrors.push(result.error ?? 'Update check incomplete');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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,
|
|
state: Pick<AutoUpdateDigestGateState, 'hasTagOnlyUpdate' | 'checkErrors'>,
|
|
imageRefCount: number,
|
|
): string {
|
|
if (state.hasTagOnlyUpdate) {
|
|
const errNote = state.checkErrors.length > 0
|
|
? ` (${state.checkErrors.length} check(s) failed)`
|
|
: '';
|
|
return `Stack "${stackName}": newer tag available but Compose pin unchanged; skipped auto-update${errNote}.`;
|
|
}
|
|
if (state.checkErrors.length > 0 && state.checkErrors.length === imageRefCount) {
|
|
return `Stack "${stackName}": WARNING - all image checks failed (${state.checkErrors.join('; ')}). Unable to determine update status.`;
|
|
}
|
|
if (state.checkErrors.length > 0) {
|
|
return `Stack "${stackName}": all reachable images up to date (${state.checkErrors.length} check(s) failed).`;
|
|
}
|
|
return `Stack "${stackName}": all images up to date.`;
|
|
}
|