Skip to content

Commit 9d0f2fc

Browse files
authored
fix(ssh): surface a failed remote t3 install instead of a silent 0-byte server.log (#5132)
1 parent e9e4697 commit 9d0f2fc

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

packages/ssh/src/tunnel.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ describe("ssh tunnel scripts", () => {
108108
assert.include(script, "exec npx --yes 't3@latest' \"$@\"");
109109
assert.include(script, "exec npm exec --yes 't3@latest' -- \"$@\"");
110110
assert.include(script, "could not install 't3@latest'");
111+
assert.include(script, "require_installed_t3_cli npx --yes --package 't3@latest'");
112+
assert.include(script, "require_installed_t3_cli npm exec --yes --package 't3@latest'");
113+
assert.include(script, "npm produced no t3 executable");
111114
assert.include(script, 'prepend_path_if_dir "$HOME/.local/bin"');
112115
assert.include(script, `T3_NODE_ENGINE_RANGE='${TEST_NODE_ENGINE_RANGE}'`);
113116
assert.include(script, "remote_node_satisfies_engine()");
@@ -140,6 +143,10 @@ describe("ssh tunnel scripts", () => {
140143

141144
assert.include(script, "exec npx --yes 't3@nightly; touch /tmp/t3-owned' \"$@\"");
142145
assert.include(script, "exec npm exec --yes 't3@nightly; touch /tmp/t3-owned' -- \"$@\"");
146+
assert.include(
147+
script,
148+
"require_installed_t3_cli npx --yes --package 't3@nightly; touch /tmp/t3-owned'",
149+
);
143150
assert.notInclude(script, "exec npx --yes t3@nightly; touch /tmp/t3-owned");
144151
});
145152

@@ -185,6 +192,8 @@ describe("ssh tunnel scripts", () => {
185192
assert.notInclude(buildRemoteLaunchScript(), "server-home");
186193
assert.include(buildRemoteLaunchScript(), "Remote T3 server did not become ready");
187194
assert.include(buildRemoteLaunchScript(), 'wait_ready "60000"');
195+
assert.include(buildRemoteLaunchScript(), 'if [ -s "$LOG_FILE" ]; then');
196+
assert.include(buildRemoteLaunchScript(), "It wrote nothing to %s");
188197
assert.include(buildRemoteLaunchScript({ packageSpec: "t3@nightly" }), "t3@nightly");
189198
assert.include(
190199
buildRemotePairingScript(target),

packages/ssh/src/tunnel.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,26 @@ fi
426426
if command -v t3 >/dev/null 2>&1; then
427427
exec t3 "$@"
428428
fi
429+
# npm extracts a package before it runs the native builds of its dependencies,
430+
# so a failed build (t3 depends on node-pty, which needs a C toolchain) leaves
431+
# the npx cache without a t3 executable. \`npx --yes\` then exits 0 without
432+
# running anything at all, which the caller only ever sees as a server that
433+
# never becomes ready. Resolve the CLI once up front so that install failure is
434+
# reported here, with npm's own output on stderr.
435+
require_installed_t3_cli() {
436+
T3_CLI_PATH="$("$@" -- sh -c 'command -v t3' || true)"
437+
if [ -n "$T3_CLI_PATH" ]; then
438+
return 0
439+
fi
440+
printf 'Remote host installed %s but npm produced no t3 executable, which usually means a native dependency (node-pty) failed to build. Install a C toolchain on the remote host (Debian/Ubuntu: build-essential, Fedora/RHEL: gcc-c++ make, macOS: xcode-select --install) and try again.\\n' @@T3_PACKAGE_SPEC@@ >&2
441+
return 1
442+
}
429443
if command -v npx >/dev/null 2>&1; then
444+
require_installed_t3_cli npx --yes --package @@T3_PACKAGE_SPEC@@ || exit 1
430445
exec npx --yes @@T3_PACKAGE_SPEC@@ "$@"
431446
fi
432447
if command -v npm >/dev/null 2>&1; then
448+
require_installed_t3_cli npm exec --yes --package @@T3_PACKAGE_SPEC@@ || exit 1
433449
exec npm exec --yes @@T3_PACKAGE_SPEC@@ -- "$@"
434450
fi
435451
printf 'Remote host is missing the t3 CLI and could not install @@T3_PACKAGE_SPEC@@ because node/npm/npx are unavailable on PATH. Install Node or configure a supported version manager for non-interactive shells.\\n' >&2
@@ -581,7 +597,11 @@ if [ -z "$REMOTE_PORT" ]; then
581597
printf 'managed\\n' >"$MANAGED_FILE"
582598
if ! wait_ready "@@T3_READY_TIMEOUT_MS@@"; then
583599
printf 'Remote T3 server did not become ready on 127.0.0.1:%s.\\n' "$REMOTE_PORT" >&2
584-
tail -n 80 "$LOG_FILE" >&2 2>/dev/null || true
600+
if [ -s "$LOG_FILE" ]; then
601+
tail -n 80 "$LOG_FILE" >&2 2>/dev/null || true
602+
else
603+
printf 'It wrote nothing to %s, so it exited before producing any output.\\n' "$LOG_FILE" >&2
604+
fi
585605
kill "$REMOTE_PID" 2>/dev/null || true
586606
wait_for_pid_exit "$REMOTE_PID"
587607
rm -f "$PID_FILE" "$PORT_FILE" "$MANAGED_FILE"

0 commit comments

Comments
 (0)