fix: add safe frontend rebuild workflow

This commit is contained in:
Codex
2026-05-05 02:45:58 +00:00
parent cce8a78508
commit 5a62af6260
7 changed files with 79 additions and 3 deletions
+48
View File
@@ -18,6 +18,13 @@ export interface ContainerStatus {
ports: string;
}
const rebuildableServices = ["backend-core", "frontend", "provider-gateway"] as const;
export type RebuildableService = typeof rebuildableServices[number];
export function isRebuildableService(value: string | undefined): value is RebuildableService {
return rebuildableServices.some((service) => service === value);
}
export function resolveComposeCommand(config: UniDeskConfig, envFile: string): string[] {
const composeFile = rootPath(config.docker.composeFile);
if (commandOk(["docker", "compose", "version"], repoRoot)) {
@@ -133,6 +140,47 @@ export function stopStack(config: UniDeskConfig): unknown {
return { job, runtimeEnv, command, portsBeforeStop: fixedPorts(config) };
}
export function rebuildService(config: UniDeskConfig, service: RebuildableService): unknown {
const runtimeEnv = writeComposeEnv(config, false);
const compose = resolveComposeCommand(config, runtimeEnv.envFile);
const buildCommand = [...compose, "build", service];
const listServiceContainersCommand = [
"docker",
"ps",
"-aq",
"--filter",
`label=com.docker.compose.project=${config.docker.projectName}`,
"--filter",
`label=com.docker.compose.service=${service}`,
];
const upCommand = [...compose, "up", "-d", "--no-deps", service];
const script = [
"set -euo pipefail",
`echo ${shellJoin(["rebuild_service", service, "build_first_then_replace_container"])}`,
shellJoin(buildCommand),
`ids=$(${shellJoin(listServiceContainersCommand)})`,
`if [ -n "$ids" ]; then echo "remove_existing_compose_service_containers service=${service} ids=$ids"; docker rm -f $ids; else echo "no_existing_compose_service_containers service=${service}"; fi`,
shellJoin(upCommand),
].join("; ");
const command = ["bash", "-lc", script];
const job = startJob("server_rebuild", command, `Rebuild and replace UniDesk ${service} without Docker Compose v1 recreate`);
return {
job,
runtimeEnv,
service,
command,
strategy: {
buildBeforeRemove: true,
removeScope: {
projectLabel: config.docker.projectName,
serviceLabel: service,
},
noDeps: 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) },