fix: stream artifact download progress to jobs
This commit is contained in:
@@ -17,6 +17,7 @@ assertCondition(source.includes("runRemoteScriptBackground(options, remoteScript
|
||||
assertCondition(source.includes('runRemoteScriptBackground(options, deployScript, Math.max(options.timeoutMs, 420_000), "d601-k3s-deploy")'), "D601 k3s deploy must use background polling");
|
||||
assertCondition(source.includes('"ssh",\n options.providerId,\n "download"'), "download helper must route through UniDesk ssh download");
|
||||
assertCondition(downloadRemoteFileSource.includes('"--chunk-bytes",\n "64000"'), "artifact ssh download must use a mid-size bounded chunk, not the largest chunk");
|
||||
assertCondition(downloadRemoteFileSource.includes("teeStderrFile: process.env.UNIDESK_JOB_STDERR_FILE"), "artifact ssh download must stream progress stderr into async job logs");
|
||||
assertCondition(source.includes("UNIDESK_SSH_CLIENT_TOKEN") && source.includes("UNIDESK_SSH_CLIENT_ROUTE_ALLOWLIST"), "dev frontend artifact deploy must sync scoped ssh runtime keys");
|
||||
|
||||
console.log(JSON.stringify({
|
||||
@@ -27,6 +28,7 @@ console.log(JSON.stringify({
|
||||
"compose artifact uses verified ssh download",
|
||||
"remote docker save and k3s deploy use background polling",
|
||||
"artifact downloads use a mid-size bounded ssh chunk",
|
||||
"artifact download progress is visible in async job stderr",
|
||||
"dev frontend artifact deploy syncs scoped ssh runtime keys"
|
||||
]
|
||||
}, null, 2));
|
||||
|
||||
@@ -1671,7 +1671,7 @@ function combineCommandResults(command: string[], parts: CommandResult[]): Comma
|
||||
}
|
||||
|
||||
function downloadRemoteFile(options: ArtifactRegistryOptions, remotePath: string, localPath: string, timeoutMs = options.timeoutMs): CommandResult {
|
||||
return runCommand([
|
||||
const result = runCommand([
|
||||
process.execPath,
|
||||
"scripts/cli.ts",
|
||||
"ssh",
|
||||
@@ -1681,7 +1681,12 @@ function downloadRemoteFile(options: ArtifactRegistryOptions, remotePath: string
|
||||
"64000",
|
||||
remotePath,
|
||||
localPath,
|
||||
], repoRoot, { timeoutMs });
|
||||
], repoRoot, {
|
||||
timeoutMs,
|
||||
teeStdoutFile: process.env.UNIDESK_JOB_STDOUT_FILE,
|
||||
teeStderrFile: process.env.UNIDESK_JOB_STDERR_FILE,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
async function runRemoteScriptBackground(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
import { closeSync, createWriteStream, existsSync, openSync, readSync, statSync } from "node:fs";
|
||||
import { appendFileSync, closeSync, createWriteStream, existsSync, openSync, readSync, statSync } from "node:fs";
|
||||
|
||||
export interface CommandResult {
|
||||
command: string[];
|
||||
@@ -11,7 +11,7 @@ export interface CommandResult {
|
||||
timedOut: boolean;
|
||||
}
|
||||
|
||||
export function runCommand(command: string[], cwd: string, options: { timeoutMs?: number; env?: NodeJS.ProcessEnv } = {}): CommandResult {
|
||||
export function runCommand(command: string[], cwd: string, options: { timeoutMs?: number; env?: NodeJS.ProcessEnv; teeStdoutFile?: string; teeStderrFile?: string } = {}): CommandResult {
|
||||
const result = spawnSync(command[0], command.slice(1), {
|
||||
cwd,
|
||||
encoding: "utf8",
|
||||
@@ -20,12 +20,15 @@ export function runCommand(command: string[], cwd: string, options: { timeoutMs?
|
||||
timeout: options.timeoutMs,
|
||||
});
|
||||
const error = result.error as (Error & { code?: string }) | undefined;
|
||||
if (options.teeStdoutFile !== undefined && result.stdout !== undefined && result.stdout.length > 0) appendFileSync(options.teeStdoutFile, result.stdout, "utf8");
|
||||
const stderr = result.stderr ?? error?.message ?? "";
|
||||
if (options.teeStderrFile !== undefined && stderr.length > 0) appendFileSync(options.teeStderrFile, stderr, "utf8");
|
||||
return {
|
||||
command,
|
||||
cwd,
|
||||
exitCode: result.status,
|
||||
stdout: result.stdout ?? "",
|
||||
stderr: result.stderr ?? error?.message ?? "",
|
||||
stderr,
|
||||
signal: result.signal,
|
||||
timedOut: error?.code === "ETIMEDOUT",
|
||||
};
|
||||
@@ -39,7 +42,7 @@ export async function runCommandToFiles(command: string[], cwd: string, stdoutFi
|
||||
const stdout = createWriteStream(stdoutFile, { flags: "a" });
|
||||
const stderr = createWriteStream(stderrFile, { flags: "a" });
|
||||
stdout.write(`$ ${command.map((part) => JSON.stringify(part)).join(" ")}\n`);
|
||||
const child = spawn(command[0], command.slice(1), { cwd, env: process.env });
|
||||
const child = spawn(command[0], command.slice(1), { cwd, env: { ...process.env, UNIDESK_JOB_STDOUT_FILE: stdoutFile, UNIDESK_JOB_STDERR_FILE: stderrFile } });
|
||||
child.stdout.pipe(stdout, { end: false });
|
||||
child.stderr.pipe(stderr, { end: false });
|
||||
const exitCode = await new Promise<number | null>((resolve) => {
|
||||
|
||||
Reference in New Issue
Block a user