mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-20 07:13:05 +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:
@@ -46,10 +46,40 @@ describe('stack_update_status tri-state accessors', () => {
|
||||
expect(db().getStackUpdateDetail(NODE).web.checkStatus).toBe('ok');
|
||||
});
|
||||
|
||||
it('keeps getStackUpdateStatus a boolean map for the fleet contract', () => {
|
||||
it('keeps getStackUpdateStatus a raw boolean map ignoring check_status', () => {
|
||||
db().upsertStackUpdateStatus(NODE, 'web', true, 1000, 'ok', null);
|
||||
db().upsertStackUpdateStatus(NODE, 'api', false, 1000, 'failed', 'boom');
|
||||
expect(db().getStackUpdateStatus(NODE)).toEqual({ web: true, api: false });
|
||||
db().upsertStackUpdateStatus(NODE, 'sticky', true, 1000, 'partial', 'half');
|
||||
expect(db().getStackUpdateStatus(NODE)).toEqual({ web: true, api: false, sticky: true });
|
||||
});
|
||||
|
||||
it('projects confirmed updates only via getConfirmedStackUpdateStatus', () => {
|
||||
db().upsertStackUpdateStatus(NODE, 'web', true, 1000, 'ok', null);
|
||||
db().upsertStackUpdateStatus(NODE, 'sticky', true, 1000, 'partial', 'half');
|
||||
db().upsertStackUpdateStatus(NODE, 'failed', true, 1000, 'failed', 'boom');
|
||||
db().upsertStackUpdateStatus(NODE, 'clean', false, 1000, 'ok', null);
|
||||
expect(db().getConfirmedStackUpdateStatus(NODE)).toEqual({
|
||||
web: true,
|
||||
sticky: false,
|
||||
failed: false,
|
||||
clean: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('clearStackUpdateStatus returns deleted row count and removes services_json', () => {
|
||||
db().upsertStackUpdateStatus(NODE, 'web', true, 1000, 'partial', 'half', [
|
||||
{ service: 'web', image: 'web:1', hasUpdate: true, checkStatus: 'ok', lastError: null },
|
||||
]);
|
||||
expect(db().clearStackUpdateStatus(NODE, 'web')).toBe(1);
|
||||
expect(db().getStackUpdateDetail(NODE).web).toBeUndefined();
|
||||
expect(db().clearStackUpdateStatus(NODE, 'web')).toBe(0);
|
||||
});
|
||||
|
||||
it('getNodeUpdateSummary counts only confirmed updates', () => {
|
||||
db().upsertStackUpdateStatus(NODE, 'web', true, 1000, 'ok', null);
|
||||
db().upsertStackUpdateStatus(NODE, 'sticky', true, 1000, 'partial', 'half');
|
||||
const summary = db().getNodeUpdateSummary().find((r) => r.node_id === NODE);
|
||||
expect(summary?.stacks_with_updates).toBe(1);
|
||||
});
|
||||
|
||||
it('recordStackCheckFailure preserves a prior has_update while marking failed', () => {
|
||||
|
||||
Reference in New Issue
Block a user