fix: upload long deploy scripts before remote launch
This commit is contained in:
+46
-1
@@ -55,6 +55,13 @@ interface BackgroundPoll {
|
||||
raw: unknown;
|
||||
}
|
||||
|
||||
interface RemoteScriptUpload {
|
||||
ok: boolean;
|
||||
path: string;
|
||||
error: string;
|
||||
raw: unknown[];
|
||||
}
|
||||
|
||||
interface ServiceRuntimeState {
|
||||
serviceId: string;
|
||||
ok: boolean;
|
||||
@@ -964,6 +971,37 @@ async function runTargetCommand(config: UniDeskConfig, service: UniDeskMicroserv
|
||||
return await dispatchSsh(config, service.providerId, command, cwd, waitMs, remoteTimeoutMs);
|
||||
}
|
||||
|
||||
function splitFixed(value: string, size: number): string[] {
|
||||
const chunks: string[] = [];
|
||||
for (let index = 0; index < value.length; index += size) chunks.push(value.slice(index, index + size));
|
||||
return chunks;
|
||||
}
|
||||
|
||||
async function uploadRemoteShellScript(
|
||||
config: UniDeskConfig,
|
||||
service: UniDeskMicroserviceConfig,
|
||||
script: string,
|
||||
cwd: string,
|
||||
name: string,
|
||||
): Promise<RemoteScriptUpload> {
|
||||
const remotePath = `/tmp/unidesk-deploy-${safeId(service.id)}-${safeId(name)}-${Date.now().toString(36)}-${Math.random().toString(16).slice(2, 8)}.sh`;
|
||||
const b64Path = `${remotePath}.b64`;
|
||||
const raw: unknown[] = [];
|
||||
const init = await runTargetCommand(config, service, `umask 077; rm -f ${shellQuote(remotePath)} ${shellQuote(b64Path)}; : > ${shellQuote(b64Path)}`, cwd, shortDispatchWaitMs, shortRemoteTimeoutMs);
|
||||
raw.push(init.raw);
|
||||
if (!init.ok) return { ok: false, path: remotePath, error: init.stderr || init.stdout || "failed to initialize remote script upload", raw };
|
||||
const encoded = Buffer.from(script, "utf8").toString("base64");
|
||||
for (const chunk of splitFixed(encoded, 2400)) {
|
||||
const append = await runTargetCommand(config, service, `printf %s ${shellQuote(chunk)} >> ${shellQuote(b64Path)}`, cwd, shortDispatchWaitMs, shortRemoteTimeoutMs);
|
||||
raw.push(append.raw);
|
||||
if (!append.ok) return { ok: false, path: remotePath, error: append.stderr || append.stdout || "failed to append remote script chunk", raw };
|
||||
}
|
||||
const finalize = await runTargetCommand(config, service, `base64 -d ${shellQuote(b64Path)} > ${shellQuote(remotePath)}; chmod 700 ${shellQuote(remotePath)}; rm -f ${shellQuote(b64Path)}; wc -c ${shellQuote(remotePath)}`, cwd, shortDispatchWaitMs, shortRemoteTimeoutMs);
|
||||
raw.push(finalize.raw);
|
||||
if (!finalize.ok) return { ok: false, path: remotePath, error: finalize.stderr || finalize.stdout || "failed to finalize remote script upload", raw };
|
||||
return { ok: true, path: remotePath, error: "", raw };
|
||||
}
|
||||
|
||||
async function launchRemoteBackground(
|
||||
config: UniDeskConfig,
|
||||
service: UniDeskMicroserviceConfig,
|
||||
@@ -1029,7 +1067,14 @@ async function step(
|
||||
const runId = `${Date.now().toString(36)}-${Math.random().toString(16).slice(2, 8)}`;
|
||||
const logFile = `/tmp/unidesk-deploy-${safeId(service.id)}-${name}-${runId}.log`;
|
||||
const sentinelFile = `/tmp/unidesk-deploy-${safeId(service.id)}-${name}-${runId}.done`;
|
||||
const launch = await launchRemoteBackground(config, service, command, cwd ?? "/home/ubuntu", logFile, sentinelFile);
|
||||
let launchCommand = command;
|
||||
if (launchCommand.length > 1800) {
|
||||
const upload = await uploadRemoteShellScript(config, service, command, cwd ?? "/home/ubuntu", name);
|
||||
if (!upload.ok) return { step: name, ok: false, detail: upload.error, startedAt, finishedAt: nowIso(), raw: upload.raw };
|
||||
launchCommand = `bash ${shellQuote(upload.path)}`;
|
||||
progressLine(name, "remote script uploaded", { serviceId: service.id, path: upload.path, bytes: command.length });
|
||||
}
|
||||
const launch = await launchRemoteBackground(config, service, launchCommand, cwd ?? "/home/ubuntu", logFile, sentinelFile);
|
||||
if (!launch.ok) return { step: name, ok: false, detail: launch.error, startedAt, finishedAt: nowIso(), raw: launch.raw };
|
||||
progressLine(name, "remote background started", { serviceId: service.id, pid: launch.pid, logFile });
|
||||
const deadline = Date.now() + timeoutMs;
|
||||
|
||||
Reference in New Issue
Block a user