From 3db7866e698c1b5023a8902dcdc5233a8bc81802 Mon Sep 17 00:00:00 2001 From: JoshuaVlantis Date: Sat, 9 May 2026 17:02:04 +0200 Subject: [PATCH] fix(node-pty): fail loudly on npm install failure; require gcc/make/python3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two complementary changes that close the silent-failure path surfaced during testing for #401. 1. install_node_pty: when `npm install node-pty` fails, abort the build with an explicit error message that names the likely cause (missing C/C++ toolchain or python3) and the per-distro fix command. Previously the function printed a one-line warning and continued, which left pty_src_dir empty, skipped the entire copy block, and shipped the upstream Windows node-pty binaries unchanged — exactly the failure mode in #401. 2. check_dependencies: add gcc, g++, make, python3 to the dependency check so the build environment is auto-provisioned before install_node_pty runs (build-essential on Debian/Ubuntu, gcc / gcc-c++ / make / python3 on Fedora). Skipped when --node-pty-dir is set (Nix and explicit overrides bring their own pre-built node-pty). Together: the dep check makes the failure rare, and the install_node_pty abort makes the rare failure obvious instead of silent. Verified two ways: - Isolated test: forced npm to a fake binary that exits 1, called install_node_pty, confirmed exit code 1, error message contains the Debian/Fedora install hints, and the staging copy block did not run. - Full deb build: ran build.sh in an ubuntu:24.04 container with no pre-installed compilers (only ca-certificates, wget, sudo, nodejs, npm). check_dependencies ran `apt install ... build-essential` automatically; npm install node-pty subsequently compiled cleanly; shipped pty.node is ELF 64-bit LSB shared object, x86-64. --- scripts/patches/cowork.sh | 25 ++++++++++++++++++++----- scripts/setup/dependencies.sh | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/scripts/patches/cowork.sh b/scripts/patches/cowork.sh index 35853c0..3a2685f 100644 --- a/scripts/patches/cowork.sh +++ b/scripts/patches/cowork.sh @@ -807,12 +807,27 @@ install_node_pty() { echo '{"name":"node-pty-build","version":"1.0.0","private":true}' > package.json echo 'Installing node-pty (this compiles native module)...' - if npm install node-pty 2>&1; then - echo 'node-pty installed successfully' - pty_src_dir="$node_pty_build_dir/node_modules/node-pty" - else - echo 'Failed to install node-pty - terminal features may not work' + # Fail loudly on npm install failure rather than warn-and-continue. + # The previous behavior silently dropped pty_src_dir, skipped the + # entire copy block, and shipped the upstream Windows node-pty + # binaries (the #401 failure mode). check_dependencies should now + # install gcc/g++/make/python3 before we get here, so this branch + # is the last line of defense for build-tool gaps that auto-install + # couldn't fix (unknown distro, broken package mirror, etc.). + if ! npm install node-pty 2>&1; then + echo "Error: 'npm install node-pty' failed." >&2 + echo 'node-pty has a native module compiled via node-gyp;' >&2 + echo 'this usually means the build environment lacks a C/C++' >&2 + echo 'compiler, make, or python3.' >&2 + echo '' >&2 + echo 'Install build tools and re-run:' >&2 + echo ' Debian/Ubuntu: sudo apt install build-essential python3' >&2 + echo ' Fedora/RHEL: sudo dnf install gcc gcc-c++ make python3' >&2 + cd "$project_root" || exit 1 + exit 1 fi + echo 'node-pty installed successfully' + pty_src_dir="$node_pty_build_dir/node_modules/node-pty" fi if [[ -n $pty_src_dir && -d $pty_src_dir ]]; then diff --git a/scripts/setup/dependencies.sh b/scripts/setup/dependencies.sh index 659db05..ccdda8e 100644 --- a/scripts/setup/dependencies.sh +++ b/scripts/setup/dependencies.sh @@ -22,16 +22,30 @@ check_dependencies() { rpm) all_deps="$all_deps rpmbuild" ;; esac + # node-pty has a native C++ module compiled via node-gyp during + # `npm install`. Without gcc/g++/make/python3 the install silently + # emits a warning, leaves pty_src_dir empty, and the build ends up + # shipping the upstream Windows binaries (the #401 failure mode). + # Skip when --node-pty-dir is set (Nix and explicit overrides bring + # their own pre-built node-pty). + if [[ -z ${node_pty_dir:-} ]]; then + all_deps="$all_deps gcc g++ make python3" + fi + # Command-to-package mappings per distro family declare -A debian_pkgs=( [p7zip]='p7zip-full' [wget]='wget' [wrestool]='icoutils' [icotool]='icoutils' [convert]='imagemagick' [dpkg-deb]='dpkg-dev' [rpmbuild]='rpm' + [gcc]='build-essential' [g++]='build-essential' + [make]='build-essential' [python3]='python3' ) declare -A rpm_pkgs=( [p7zip]='p7zip p7zip-plugins' [wget]='wget' [wrestool]='icoutils' [icotool]='icoutils' [convert]='ImageMagick' [dpkg-deb]='dpkg' [rpmbuild]='rpm-build' + [gcc]='gcc' [g++]='gcc-c++' + [make]='make' [python3]='python3' ) local cmd