From 1229a01767b861e9a09c6889021f3e7c69ebdb0f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 24 Nov 2025 12:02:57 +0100 Subject: [PATCH] Timeout tailscale funnel in verbose runs and surface command output --- src/index.ts | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/index.ts b/src/index.ts index 8c4e22754..3c423f811 100644 --- a/src/index.ts +++ b/src/index.ts @@ -81,20 +81,34 @@ const execFileAsync = promisify(execFile); type ExecResult = { stdout: string; stderr: string }; -async function runExec(command: string, args: string[], maxBuffer = 2_000_000): Promise { +type ExecOptions = { maxBuffer?: number; timeoutMs?: number }; + +async function runExec( + command: string, + args: string[], + { maxBuffer = 2_000_000, timeoutMs }: ExecOptions = {} +): Promise { // Thin wrapper around execFile with utf8 output. if (globalVerbose) { console.log(`$ ${command} ${args.join(' ')}`); } - const { stdout, stderr } = await execFileAsync(command, args, { - maxBuffer, - encoding: 'utf8' - }); - if (globalVerbose) { - if (stdout.trim()) console.log(stdout.trim()); - if (stderr.trim()) console.error(stderr.trim()); + try { + const { stdout, stderr } = await execFileAsync(command, args, { + maxBuffer, + encoding: 'utf8', + timeout: timeoutMs + }); + if (globalVerbose) { + if (stdout.trim()) console.log(stdout.trim()); + if (stderr.trim()) console.error(stderr.trim()); + } + return { stdout, stderr }; + } catch (err) { + if (globalVerbose) { + console.error(danger(`Command failed: ${command} ${args.join(' ')}`)); + } + throw err; } - return { stdout, stderr }; } async function ensureBinary(name: string): Promise { @@ -391,7 +405,10 @@ async function ensureFunnel(port: number) { } logVerbose(`Enabling funnel on port ${port}…`); - const { stdout } = await runExec('tailscale', ['funnel', '--yes', '--bg', `${port}`], 200_000); + const { stdout } = await runExec('tailscale', ['funnel', '--yes', '--bg', `${port}`], { + maxBuffer: 200_000, + timeoutMs: 15_000 + }); if (stdout.trim()) console.log(stdout.trim()); } catch (err) { console.error('Failed to enable Tailscale Funnel. Is it allowed on your tailnet?', err);