fix: validate configured OpenCode binary (#1120)

* Validate configured OpenCode binary

* fix: keep WSL OpenCode startup failures retryable

Avoids misclassifying transient WSL resolution failures as invalid binary config
Adds regression coverage for WSL strict-mode handling
Cleans up temporary test directories
Fix for #1119 issue
This commit is contained in:
Bohdan Triapitsyn
2026-05-06 02:06:16 +03:00
committed by GitHub
parent a02f0cd7c7
commit b18886598c
5 changed files with 305 additions and 25 deletions
@@ -170,7 +170,7 @@ describe('OpenCode lifecycle', () => {
await server.close();
});
it('reports the exit signal when managed OpenCode exits before becoming ready', async () => {
it('reports the binary when managed OpenCode exits before becoming ready', async () => {
delete process.env.OPENCODE_BINARY;
const firstChild = createMockChild();
const secondChild = createMockChild();
@@ -189,10 +189,26 @@ describe('OpenCode lifecycle', () => {
const runtime = createRuntime();
await expect(runtime.startOpenCode()).rejects.toThrow('OpenCode exited with signal SIGTERM. No stdout/stderr captured');
await expect(runtime.startOpenCode()).rejects.toThrow('OpenCode process exited before serving with signal SIGTERM. Binary used: opencode. No stdout/stderr captured');
expect(spawnMock).toHaveBeenCalledTimes(2);
});
it('does not retry managed startup when the configured OpenCode binary is invalid', async () => {
delete process.env.OPENCODE_BINARY;
const error = new Error('Configured OpenCode binary not found: /missing/opencode');
error.code = 'OPENCODE_BINARY_INVALID';
const applyOpencodeBinaryFromSettings = vi.fn(async () => {
throw error;
});
const runtime = createRuntime({ applyOpencodeBinaryFromSettings });
await expect(runtime.startOpenCode()).rejects.toThrow('Configured OpenCode binary not found: /missing/opencode');
expect(applyOpencodeBinaryFromSettings).toHaveBeenCalledTimes(1);
expect(applyOpencodeBinaryFromSettings).toHaveBeenCalledWith({ strict: true });
expect(spawnMock).not.toHaveBeenCalled();
});
it('retries managed OpenCode startup once after a pre-ready exit', async () => {
delete process.env.OPENCODE_BINARY;
const firstChild = createMockChild();