Skip to content

fix(workflows): bundle via esbuild CLI, not the Node service or a global env - #70

Merged
obogoni merged 1 commit into
mainfrom
fix/esbuild-service-epipe
Jul 7, 2026
Merged

fix(workflows): bundle via esbuild CLI, not the Node service or a global env#70
obogoni merged 1 commit into
mainfrom
fix/esbuild-service-epipe

Conversation

@obogoni

@obogoni obogoni commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Segue o PR #69 (que corrigiu só o ENOENT). No app empacotado, com o caminho do binário já correto, apareceu:

The service is no longer running: write EPIPE

Causa (dois bugs empilhados)

  1. EPIPE: loadWorkflow usava a API assíncrona esbuild.build(), que mantém uma service persistente spawnada com stdio[2]: 'inherit'. Num app Electron GUI empacotado no Windows (sem stderr válido no pai) essa service morre logo após subir → a próxima escrita no stdin dá write EPIPE → todo workflow fica broken. (buildSync evita a service, mas spawna um worker thread frágil — quebra até a service esbuild do vitest.)
  2. Vazamento de env: o fix(workflows): esbuild binary path in packaged app (ENOENT) #69 setava process.env.ESBUILD_BINARY_PATH global. Isso vaza para todo processo filho que o app spawna (agents/CLIs), forçando o esbuild deles (outra versão) sobre este binário 0.25.12 → Host version X does not match binary version 0.25.12. Observado ao vivo: quebrou o vitest de uma sessão Claude Code spawnada pelo app (esbuild 0.27.7).

Correção

  • Bundle spawnando o binário do esbuild direto, one-shot, via execFileSync com stdio piped (não inherited): sem service persistente, sem worker thread, sem stderr herdado. Idêntico em dev e empacotado; o stderr real do esbuild aparece em {error} no lugar do EPIPE opaco.
  • Binário resolvido uma vez no main (empacotado → app.asar.unpacked; dev → node_modules) e passado explicitamente ao loader. Sem ESBUILD_BINARY_PATH global → sem vazamento.

Verificação

  • npm test → 489 verdes (novo teste de regressão: binário inválido ⇒ {error}).
  • typecheck + lint limpos.
  • build:win, depois um execFileSync one-shot do binário unpacked bundleando o revisar-pr real (238 bytes) — o caminho exato do código empacotado.

⚠️ O nightly atual (com o #69) tem a versão incompleta/vazante. Precisa de merge + novo nightly para validação final de runtime.

Closes #68

🤖 Generated with Claude Code

…bal env

The ESBUILD_BINARY_PATH fix stopped the ENOENT but the packaged app then hit
"The service is no longer running: write EPIPE" — esbuild's async build()
keeps a long-lived service child spawned with stdio[2]:'inherit', which in a
packaged Windows Electron GUI app (no valid parent stderr) dies right after
launch, so every workflow lists as broken. buildSync avoids the service but
spins a worker thread that is fragile in a host already running esbuild (it
crashes vitest's own esbuild).

Bundle by spawning the esbuild binary one-shot via execFileSync with piped
(not inherited) stdio: no persistent service, no worker thread, no inherited
stderr — identical in dev and packaged, and esbuild's real stderr surfaces in
{error} instead of the opaque EPIPE.

Also drop the process.env.ESBUILD_BINARY_PATH mutation from the previous
commit: a global env leaks into every child the app spawns (agents/CLIs),
forcing their own differently-versioned esbuild onto this 0.25.12 binary and
breaking them with a host/binary version mismatch (observed: it broke a
spawned Claude Code session's vitest, whose esbuild is 0.27.7). Resolve the
binary once in main (packaged → app.asar.unpacked; dev → node_modules) and
pass it explicitly into the loader.

Verified: full suite 488→489 green (new invalid-binary regression test);
build:win, then a one-shot execFileSync of the unpacked binary bundles the
real revisar-pr workflow.ts (238 bytes) — the exact packaged code path.

Closes #68

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@obogoni

obogoni commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

Validado em runtime no app empacotado. Rodei o dist/win-unpacked/playground.exe (build com a correção completa, app.isPackaged === true, asar + app.asar.unpacked reais) e o revisar-pr carrega normalmente na aba Workflows — não fica mais "broken".

@obogoni
obogoni merged commit 37822ff into main Jul 7, 2026
3 checks passed
@obogoni
obogoni deleted the fix/esbuild-service-epipe branch July 7, 2026 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Workflows: esbuild ENOENT no app empacotado (revisar-pr fica "broken")

1 participant