fix: restore node resource status sync

This commit is contained in:
Codex
2026-06-12 14:18:55 +00:00
parent 17b54c685a
commit b41847853a
11 changed files with 347 additions and 109 deletions
+78
View File
@@ -100,6 +100,17 @@ export function unsupportedRebuildService(value: string | undefined): Record<str
};
}
export function unsupportedRestartService(value: string | undefined): Record<string, unknown> {
const base = unsupportedRebuildService(value);
return {
...base,
error: "unsupported-server-restart",
reason: typeof base.reason === "string" ? base.reason.replace(/server rebuild/g, "server restart") : base.reason,
replacement: typeof base.replacement === "string" ? base.replacement.replace(/server rebuild/g, "server restart") : base.replacement,
policy: "server restart is a no-build maintenance entrypoint and must not silently mutate upstream images, D601 services, database, or unknown objects",
};
}
export function resolveComposeCommand(config: UniDeskConfig, envFile: string): string[] {
const composeFile = rootPath(config.docker.composeFile);
if (commandOk(["docker", "compose", "version"], repoRoot)) {
@@ -431,6 +442,73 @@ export function rebuildService(config: UniDeskConfig, service: RebuildableServic
};
}
export function restartService(config: UniDeskConfig, service: RebuildableService): unknown {
const runtimeEnv = writeComposeEnv(config, false);
const compose = resolveComposeCommand(config, runtimeEnv.envFile);
const listServiceContainersCommand = [
"docker",
"ps",
"-q",
"--filter",
`label=com.docker.compose.project=${config.docker.projectName}`,
"--filter",
`label=com.docker.compose.service=${service}`,
"--filter",
"label=com.docker.compose.oneoff=False",
];
const upCommand = [...compose, "up", "-d", "--no-build", "--no-deps", "--force-recreate", service];
const listAllServiceContainersCommand = [...listServiceContainersCommand];
listAllServiceContainersCommand[2] = "-a";
const validateScript = [
"ready=0",
"for attempt in $(seq 1 60); do",
`cid=$(${shellJoin(listServiceContainersCommand)} || true)`,
"if [ -n \"$cid\" ]; then",
"health=$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' $cid 2>/dev/null | head -1 || true)",
`echo "service_container_probe service=${service} attempt=$attempt cid=$cid health=$health"`,
"if [ \"$health\" = \"healthy\" ] || [ \"$health\" = \"running\" ]; then ready=1; break; fi",
"else",
`echo "service_container_probe service=${service} attempt=$attempt cid=missing"`,
"fi",
"sleep 1",
"done",
"if [ \"$ready\" != \"1\" ]; then",
`echo "service_container_not_ready service=${service}" >&2`,
`${shellJoin(listAllServiceContainersCommand)} --format '{{.ID}} {{.Names}} {{.Status}}' >&2 || true`,
"exit 1",
"fi",
].join("\n");
const script = [
"set -euo pipefail",
`echo ${shellJoin(["restart_service", service, "no_build_force_recreate_with_validation"])}`,
restrictedHostAccessScript(config),
shellJoin(upCommand),
validateScript,
].join("\n");
const command = ["bash", "-lc", composeLockedScript(script)];
const job = startJob("server_restart", command, `Restart and validate UniDesk ${service} without building images`);
return {
job,
runtimeEnv,
service,
command,
strategy: {
buildBeforeReplace: false,
noBuild: true,
replaceScope: {
projectLabel: config.docker.projectName,
serviceLabel: service,
},
noDeps: true,
forceRecreate: true,
composeMutationLock: rootPath(".state", "locks", "server-compose.lock"),
jobRunner: "local",
postUpValidation: true,
namedVolumesPreserved: true,
},
};
}
function fixedPorts(config: UniDeskConfig): Array<{ name: string; port: number; listening: boolean }> {
return [
{ name: "frontend", port: config.network.frontend.port, listening: isPortListening(config.network.frontend.port) },