From f0bba10b127a09829b234edcb5fac5fb0a84f5c0 Mon Sep 17 00:00:00 2001 From: Luke Parker <10430890+Hona@users.noreply.github.com> Date: Fri, 13 Mar 2026 14:08:51 +1000 Subject: [PATCH] fix(e2e): fail fast on config dependency installs (#17280) --- packages/app/script/e2e-local.ts | 1 + packages/opencode/script/seed-e2e.ts | 5 +++++ packages/opencode/src/bun/index.ts | 28 +++++++++++--------------- packages/opencode/src/config/config.ts | 21 +++++++++++++++++++ packages/opencode/src/flag/flag.ts | 1 + 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/packages/app/script/e2e-local.ts b/packages/app/script/e2e-local.ts index 9a83411b1..4841c4f22 100644 --- a/packages/app/script/e2e-local.ts +++ b/packages/app/script/e2e-local.ts @@ -73,6 +73,7 @@ const serverEnv = { OPENCODE_E2E_MESSAGE: "Seeded for UI e2e", OPENCODE_E2E_MODEL: "opencode/gpt-5-nano", OPENCODE_CLIENT: "app", + OPENCODE_STRICT_CONFIG_DEPS: "true", } satisfies Record const runnerEnv = { diff --git a/packages/opencode/script/seed-e2e.ts b/packages/opencode/script/seed-e2e.ts index 01e104420..f34dd051d 100644 --- a/packages/opencode/script/seed-e2e.ts +++ b/packages/opencode/script/seed-e2e.ts @@ -10,15 +10,20 @@ const now = Date.now() const seed = async () => { const { Instance } = await import("../src/project/instance") const { InstanceBootstrap } = await import("../src/project/bootstrap") + const { Config } = await import("../src/config/config") const { Session } = await import("../src/session") const { MessageID, PartID } = await import("../src/session/schema") const { Project } = await import("../src/project/project") const { ModelID, ProviderID } = await import("../src/provider/schema") + const { ToolRegistry } = await import("../src/tool/registry") await Instance.provide({ directory: dir, init: InstanceBootstrap, fn: async () => { + await Config.waitForDependencies() + await ToolRegistry.ids() + const session = await Session.create({ title }) const messageID = MessageID.ascending() const partID = PartID.ascending() diff --git a/packages/opencode/src/bun/index.ts b/packages/opencode/src/bun/index.ts index e3bddcc22..d6c453825 100644 --- a/packages/opencode/src/bun/index.ts +++ b/packages/opencode/src/bun/index.ts @@ -4,7 +4,6 @@ import { Log } from "../util/log" import path from "path" import { Filesystem } from "../util/filesystem" import { NamedError } from "@opencode-ai/util/error" -import { text } from "node:stream/consumers" import { Lock } from "../util/lock" import { PackageRegistry } from "./registry" import { proxied } from "@/util/proxied" @@ -13,32 +12,29 @@ import { Process } from "../util/process" export namespace BunProc { const log = Log.create({ service: "bun" }) - export async function run(cmd: string[], options?: Process.Options) { + export async function run(cmd: string[], options?: Process.RunOptions) { + const full = [which(), ...cmd] log.info("running", { - cmd: [which(), ...cmd], + cmd: full, ...options, }) - const result = Process.spawn([which(), ...cmd], { - ...options, - stdout: "pipe", - stderr: "pipe", + const result = await Process.run(full, { + cwd: options?.cwd, + abort: options?.abort, + kill: options?.kill, + timeout: options?.timeout, + nothrow: options?.nothrow, env: { ...process.env, ...options?.env, BUN_BE_BUN: "1", }, }) - const code = await result.exited - const stdout = result.stdout ? await text(result.stdout) : undefined - const stderr = result.stderr ? await text(result.stderr) : undefined log.info("done", { - code, - stdout, - stderr, + code: result.code, + stdout: result.stdout.toString(), + stderr: result.stderr.toString(), }) - if (code !== 0) { - throw new Error(`Command failed with exit code ${code}`) - } return result } diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 2b8aa9e03..f3d0d0b7a 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -36,6 +36,7 @@ import { iife } from "@/util/iife" import { Account } from "@/account" import { ConfigPaths } from "./paths" import { Filesystem } from "@/util/filesystem" +import { Process } from "@/util/process" export namespace Config { const ModelId = z.string().meta({ $ref: "https://models.dev/model-schema.json#/$defs/Model" }) @@ -296,6 +297,26 @@ export namespace Config { ], { cwd: dir }, ).catch((err) => { + if (err instanceof Process.RunFailedError) { + const detail = { + dir, + cmd: err.cmd, + code: err.code, + stdout: err.stdout.toString(), + stderr: err.stderr.toString(), + } + if (Flag.OPENCODE_STRICT_CONFIG_DEPS) { + log.error("failed to install dependencies", detail) + throw err + } + log.warn("failed to install dependencies", detail) + return + } + + if (Flag.OPENCODE_STRICT_CONFIG_DEPS) { + log.error("failed to install dependencies", { dir, error: err }) + throw err + } log.warn("failed to install dependencies", { dir, error: err }) }) } diff --git a/packages/opencode/src/flag/flag.ts b/packages/opencode/src/flag/flag.ts index 30929bd92..f1688a1b4 100644 --- a/packages/opencode/src/flag/flag.ts +++ b/packages/opencode/src/flag/flag.ts @@ -63,6 +63,7 @@ export namespace Flag { export const OPENCODE_MODELS_PATH = process.env["OPENCODE_MODELS_PATH"] export const OPENCODE_DISABLE_CHANNEL_DB = truthy("OPENCODE_DISABLE_CHANNEL_DB") export const OPENCODE_SKIP_MIGRATIONS = truthy("OPENCODE_SKIP_MIGRATIONS") + export const OPENCODE_STRICT_CONFIG_DEPS = truthy("OPENCODE_STRICT_CONFIG_DEPS") function number(key: string) { const value = process.env[key]