From 98822509a8deffd599ce9b1ad25e3951f75b223b Mon Sep 17 00:00:00 2001 From: jiarung Date: Fri, 13 Mar 2026 14:17:36 +0000 Subject: [PATCH] fix(git-hooks): pick newest nvm Node with version-aware sort The previous loop used Bash glob expansion (lexicographic order) and stopped at the first match, so environments with multiple Node installs could select an older runtime (e.g. v18 before v22). Extract the nvm resolution into a shared scripts/pre-commit/resolve-node.sh that pipes `ls` output through `sort -V | tail -1` to select the semantically newest version. Both pre-commit and run-node-tool.sh now source the shared script, eliminating the duplicated logic. --- git-hooks/pre-commit | 17 ++++++----------- scripts/pre-commit/resolve-node.sh | 18 ++++++++++++++++++ scripts/pre-commit/run-node-tool.sh | 13 ++++--------- 3 files changed, 28 insertions(+), 20 deletions(-) create mode 100644 scripts/pre-commit/resolve-node.sh diff --git a/git-hooks/pre-commit b/git-hooks/pre-commit index 9650fe936eb..696f9b7b20e 100755 --- a/git-hooks/pre-commit +++ b/git-hooks/pre-commit @@ -2,18 +2,13 @@ set -euo pipefail -# Resolve node when not in PATH (e.g. nvm environments where shell profile -# hasn't been sourced by the git hook). Picks the highest nvm version found. -if ! command -v node >/dev/null 2>&1; then - for _nvm_node in "$HOME/.nvm/versions/node"/*/bin/node; do - if [[ -x "$_nvm_node" ]]; then - export PATH="$(dirname "$_nvm_node"):$PATH" - break - fi - done -fi - ROOT_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" + +# Resolve node when not in PATH (e.g. nvm environments where the shell +# profile hasn't been sourced by the git hook). Picks the newest installed +# nvm version using version-aware sort so that v22 is preferred over v18. +# shellcheck source=scripts/pre-commit/resolve-node.sh +source "$ROOT_DIR/scripts/pre-commit/resolve-node.sh" RUN_NODE_TOOL="$ROOT_DIR/scripts/pre-commit/run-node-tool.sh" FILTER_FILES="$ROOT_DIR/scripts/pre-commit/filter-staged-files.mjs" diff --git a/scripts/pre-commit/resolve-node.sh b/scripts/pre-commit/resolve-node.sh new file mode 100644 index 00000000000..a3f484c7029 --- /dev/null +++ b/scripts/pre-commit/resolve-node.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Resolve the newest nvm-managed Node when it is not already in PATH. +# Source this file; do not execute it directly. +# +# Uses `sort -V` (version-aware sort) so that semantic version order is +# respected — e.g. v22.x is chosen over v18.x even though "v1" sorts +# before "v2" lexicographically. +if ! command -v node >/dev/null 2>&1; then + _nvm_node=$( + ls -d "$HOME/.nvm/versions/node"/*/bin/node 2>/dev/null \ + | sort -V \ + | tail -1 + ) + if [[ -x "$_nvm_node" ]]; then + export PATH="$(dirname "$_nvm_node"):$PATH" + fi + unset _nvm_node +fi diff --git a/scripts/pre-commit/run-node-tool.sh b/scripts/pre-commit/run-node-tool.sh index 69a26f45e0e..4fda9e4ba0b 100755 --- a/scripts/pre-commit/run-node-tool.sh +++ b/scripts/pre-commit/run-node-tool.sh @@ -3,15 +3,10 @@ set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -# Resolve node when not in PATH (nvm environments). -if ! command -v node >/dev/null 2>&1; then - for _nvm_node in "$HOME/.nvm/versions/node"/*/bin/node; do - if [[ -x "$_nvm_node" ]]; then - export PATH="$(dirname "$_nvm_node"):$PATH" - break - fi - done -fi +# Resolve node when not in PATH (e.g. nvm environments). Picks the newest +# installed nvm version using version-aware sort. +# shellcheck source=resolve-node.sh +source "$ROOT_DIR/scripts/pre-commit/resolve-node.sh" if [[ $# -lt 1 ]]; then echo "usage: run-node-tool.sh [args...]" >&2