diff --git a/core/src/util/ext-tools.ts b/core/src/util/ext-tools.ts index 71bd016c33..26911ce5fe 100644 --- a/core/src/util/ext-tools.ts +++ b/core/src/util/ext-tools.ts @@ -24,9 +24,9 @@ import AsyncLock from "async-lock" import type { PluginContext } from "../plugin-context.js" import { LogLevel } from "../logger/logger.js" import { uuidv4 } from "./random.js" -import { streamLogs, waitForProcess } from "./process.js" import { pipeline } from "node:stream/promises" import type { MaybeSecret } from "./secrets.js" +import split2 from "split2" const { pathExists, createWriteStream, ensureDir, chmod, remove, move, createReadStream } = fsExtra @@ -122,7 +122,7 @@ export abstract class CliWrapper { } /** - * Helper for using spawn with live log streaming. Waits for the command to finish before returning. + * Helper for using exec with live log streaming. Waits for the command to finish before returning. * * If an error occurs and no output has been written to stderr, we use stdout for the error message instead. * @@ -134,20 +134,19 @@ export abstract class CliWrapper { env, log, ctx, - errorPrefix, }: SpawnParams & { errorPrefix: string; ctx: PluginContext; statusLine?: Log }) { - const proc = await this.spawn({ args, cwd, env, log }) + const logEventContext = { + origin: this.name, + level: "verbose" as const, + } - streamLogs({ - proc, - name: this.name, - ctx, + const logStream = split2() + logStream.on("data", (line: Buffer) => { + const logLine = line.toString() + ctx.events.emit("log", { timestamp: new Date().toISOString(), msg: logLine, ...logEventContext }) }) - await waitForProcess({ - proc, - errorPrefix, - }) + return await this.spawnAndWait({ args, cwd, env, log, stdout: logStream, stderr: logStream }) } /** diff --git a/core/src/util/process.ts b/core/src/util/process.ts index 8cf013a6bf..1c6df6168d 100644 --- a/core/src/util/process.ts +++ b/core/src/util/process.ts @@ -8,7 +8,6 @@ import type { ChildProcess } from "child_process" import split2 from "split2" -import { RuntimeError } from "../exceptions.js" import type { PluginContext } from "../plugin-context.js" import type { StringLogLevel } from "../logger/logger.js" @@ -57,45 +56,6 @@ export function waitForProcessExit({ proc }: { proc: ChildProcess }): Promise { - const logStream = split2() - - let stdout = "" - let stderr = "" - - if (proc.stderr) { - proc.stderr.pipe(logStream) - proc.stderr.on("data", (data) => { - stderr += data - }) - } - - if (proc.stdout) { - proc.stdout.pipe(logStream) - proc.stdout.on("data", (data) => { - stdout += data - }) - } - - return new Promise((resolve, reject) => { - proc.on("error", reject) - proc.on("close", (code) => { - if (code === 0) { - resolve() - } else { - // Some commands (e.g. the pulumi CLI) don't log anything to stderr when an error occurs. To handle that, - // we use `stdout` for the error output instead (in case information relevant to the user is included there). - const errOutput = stderr.length > 0 ? stderr : stdout - reject( - new RuntimeError({ - message: `${errorPrefix}:\n${errOutput}\n\nExit code: ${code}`, - }) - ) - } - }) - }) -} - export class LogLineTimeoutError extends Error { private stdout: string private stderr: string