fix(config-manager): support silent bun install execution
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { existsSync } from "node:fs"
|
||||
|
||||
import { getOpenCodeCacheDir } from "../../shared/data-path"
|
||||
import { log } from "../../shared/logger"
|
||||
import { spawnWithWindowsHide } from "../../shared/spawn-with-windows-hide"
|
||||
@@ -6,6 +7,26 @@ import { spawnWithWindowsHide } from "../../shared/spawn-with-windows-hide"
|
||||
const BUN_INSTALL_TIMEOUT_SECONDS = 60
|
||||
const BUN_INSTALL_TIMEOUT_MS = BUN_INSTALL_TIMEOUT_SECONDS * 1000
|
||||
|
||||
type BunInstallOutputMode = "inherit" | "pipe"
|
||||
|
||||
interface RunBunInstallOptions {
|
||||
outputMode?: BunInstallOutputMode
|
||||
}
|
||||
|
||||
interface BunInstallOutput {
|
||||
stdout: string
|
||||
stderr: string
|
||||
}
|
||||
|
||||
declare function setTimeout(callback: () => void, delay?: number): number
|
||||
declare function clearTimeout(timeout: number): void
|
||||
|
||||
type ProcessOutputStream = ReturnType<typeof spawnWithWindowsHide>["stdout"]
|
||||
|
||||
declare const Bun: {
|
||||
readableStreamToText(stream: NonNullable<ProcessOutputStream>): Promise<string>
|
||||
}
|
||||
|
||||
export interface BunInstallResult {
|
||||
success: boolean
|
||||
timedOut?: boolean
|
||||
@@ -17,7 +38,33 @@ export async function runBunInstall(): Promise<boolean> {
|
||||
return result.success
|
||||
}
|
||||
|
||||
export async function runBunInstallWithDetails(): Promise<BunInstallResult> {
|
||||
function readProcessOutput(stream: ProcessOutputStream): Promise<string> {
|
||||
if (!stream) {
|
||||
return Promise.resolve("")
|
||||
}
|
||||
|
||||
return Bun.readableStreamToText(stream)
|
||||
}
|
||||
|
||||
function logCapturedOutputOnFailure(outputMode: BunInstallOutputMode, output: BunInstallOutput): void {
|
||||
if (outputMode !== "pipe") {
|
||||
return
|
||||
}
|
||||
|
||||
const stdout = output.stdout.trim()
|
||||
const stderr = output.stderr.trim()
|
||||
if (!stdout && !stderr) {
|
||||
return
|
||||
}
|
||||
|
||||
log("[bun-install] Captured output from failed bun install", {
|
||||
stdout,
|
||||
stderr,
|
||||
})
|
||||
}
|
||||
|
||||
export async function runBunInstallWithDetails(options?: RunBunInstallOptions): Promise<BunInstallResult> {
|
||||
const outputMode = options?.outputMode ?? "inherit"
|
||||
const cacheDir = getOpenCodeCacheDir()
|
||||
const packageJsonPath = `${cacheDir}/package.json`
|
||||
|
||||
@@ -31,17 +78,23 @@ export async function runBunInstallWithDetails(): Promise<BunInstallResult> {
|
||||
try {
|
||||
const proc = spawnWithWindowsHide(["bun", "install"], {
|
||||
cwd: cacheDir,
|
||||
stdout: "inherit",
|
||||
stderr: "inherit",
|
||||
stdout: outputMode,
|
||||
stderr: outputMode,
|
||||
})
|
||||
|
||||
let timeoutId: ReturnType<typeof setTimeout>
|
||||
const outputPromise = Promise.all([readProcessOutput(proc.stdout), readProcessOutput(proc.stderr)]).then(
|
||||
([stdout, stderr]) => ({ stdout, stderr })
|
||||
)
|
||||
|
||||
let timeoutId: ReturnType<typeof setTimeout> | undefined
|
||||
const timeoutPromise = new Promise<"timeout">((resolve) => {
|
||||
timeoutId = setTimeout(() => resolve("timeout"), BUN_INSTALL_TIMEOUT_MS)
|
||||
})
|
||||
const exitPromise = proc.exited.then(() => "completed" as const)
|
||||
const result = await Promise.race([exitPromise, timeoutPromise])
|
||||
clearTimeout(timeoutId!)
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId)
|
||||
}
|
||||
|
||||
if (result === "timeout") {
|
||||
try {
|
||||
@@ -49,6 +102,10 @@ export async function runBunInstallWithDetails(): Promise<BunInstallResult> {
|
||||
} catch (err) {
|
||||
log("[cli/install] Failed to kill timed out bun install process:", err)
|
||||
}
|
||||
|
||||
await proc.exited
|
||||
logCapturedOutputOnFailure(outputMode, await outputPromise)
|
||||
|
||||
return {
|
||||
success: false,
|
||||
timedOut: true,
|
||||
@@ -56,7 +113,11 @@ export async function runBunInstallWithDetails(): Promise<BunInstallResult> {
|
||||
}
|
||||
}
|
||||
|
||||
const output = await outputPromise
|
||||
|
||||
if (proc.exitCode !== 0) {
|
||||
logCapturedOutputOnFailure(outputMode, output)
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: `bun install failed with exit code ${proc.exitCode}`,
|
||||
|
||||
Reference in New Issue
Block a user