mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-09-04 14:45:41 +00:00
feat: add service-scoped Compose update and restore (#1648)
* feat: add service-scoped Compose update and restore Allow updating or rebuilding one declared Compose service on multi-service stacks without recreating siblings, with recovery snapshots, health-gate observation, and prune holds for rollback images. Full-stack update paths and single-service UX stay unchanged. * fix: sanitize service-scoped update log messages for CodeQL * fix: address service-scoped update audit findings B-01 through B-07 * fix: complete service-scoped update audit metadata and surfaces * test: wrap Updates readiness tests for deploy-feedback context * fix: keep service recovery reachable without Deploy Progress Make failed service-gate recovery discoverable when Deploy Progress is disabled or dismissed, suppress stale image-scan notification side effects, normalize ComposeService line endings, and add focused regression coverage. * fix: resurface ContainersHealth density and expand on multi-service stacks Service grouping hid the summary strip and Compact/Detailed/Expand controls that still applied to multi-container stacks.
This commit is contained in:
@@ -7,7 +7,7 @@ import { NodeRegistry } from '../services/NodeRegistry';
|
||||
import { CacheService } from '../services/CacheService';
|
||||
import { ImageUpdateService } from '../services/ImageUpdateService';
|
||||
import { FileSystemService } from '../services/FileSystemService';
|
||||
import { ComposeService } from '../services/ComposeService';
|
||||
import { StackUpdateOrchestrator } from '../services/StackUpdateOrchestrator';
|
||||
import { StackOpLockService, stackOpSkipMessage } from '../services/StackOpLockService';
|
||||
import { NotificationService } from '../services/NotificationService';
|
||||
import { enforcePolicyPreDeploy } from '../services/PolicyEnforcement';
|
||||
@@ -342,7 +342,6 @@ autoUpdateRouter.post('/execute', authMiddleware, async (req: Request, res: Resp
|
||||
|
||||
const docker = DockerController.getInstance(req.nodeId);
|
||||
const imageUpdateService = ImageUpdateService.getInstance();
|
||||
const compose = ComposeService.getInstance(req.nodeId);
|
||||
const db = DatabaseService.getInstance();
|
||||
const atomic = true;
|
||||
const results: string[] = [];
|
||||
@@ -417,14 +416,17 @@ autoUpdateRouter.post('/execute', authMiddleware, async (req: Request, res: Resp
|
||||
|
||||
const lock = await StackOpLockService.getInstance().runExclusive(
|
||||
req.nodeId, stackName, 'update', 'system',
|
||||
() => compose.updateStack(stackName, undefined, atomic),
|
||||
() => StackUpdateOrchestrator.getInstance().execute(
|
||||
{ nodeId: req.nodeId, stackName, target: { scope: 'stack' }, trigger: 'automatic', actor: `auto-update:${req.user?.username ?? 'scheduler'}` },
|
||||
{ atomic, terminalWs: null },
|
||||
),
|
||||
);
|
||||
if (!lock.ran) {
|
||||
results.push(stackOpSkipMessage(stackName, lock.existing.action));
|
||||
continue;
|
||||
}
|
||||
db.clearStackUpdateStatus(req.nodeId, stackName);
|
||||
HealthGateService.getInstance().begin(req.nodeId, stackName, 'update', `auto-update:${req.user?.username ?? 'scheduler'}`);
|
||||
HealthGateService.getInstance().beginStack(req.nodeId, stackName, 'update', `auto-update:${req.user?.username ?? 'scheduler'}`);
|
||||
|
||||
NotificationService.getInstance().broadcastEvent({
|
||||
type: 'state-invalidate',
|
||||
|
||||
Reference in New Issue
Block a user