chore(common): use nvm to select version of node for builds

Used by default only on build agents. See docs/build/node.md and
resources/build/_builder_nvm.sh for documentation of this change.

Fixes: #11376
This commit is contained in:
Marc Durdin 2024-08-01 05:09:08 +07:00
parent 87f5560b14
commit fc4df037bb
3 changed files with 118 additions and 22 deletions

51
resources/build/_builder_nvm.sh Executable file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env bash
# See also /docs/build/node.md
set -e
set -u
if [[ $# -lt 1 ]]; then
echo "This script is called by shellHelperFunctions.sh, _select_node_version_with_nvm()"
echo "during build.sh configure steps. It is not intended to be called directly, as it"
echo "is a wrapper for nvm."
exit 99
fi
REQUIRED_NODE_VERSION="$1"
if [[ -z "${NVM_DIR+x}" ]]; then
export NVM_DIR="$HOME/.nvm"
fi
#
# nvm on macos and linux is a shell function. `source`ing it into our scripts is
# fragile because it uses some of the same variable names that we do. We have
# marked our most precious variables as `readonly`, which breaks nvm re-use of
# them also! Safest way to work around this is to load nvm in a child process
# and run it there. Downside is then of course we don't get the `PATH` changes
# that nvm does for us, so we have to do it ourselves back in the caller,
# `_select_node_version_with_nvm()`.
#
# Note: the readonly attribute for variables is not inherited by child
# processes.
#
# See also https://github.com/nvm-sh/nvm/issues/3257 (among others)
#
type -t nvm >/dev/null || {
source "$NVM_DIR/nvm.sh"
type -t nvm >/dev/null || {
echo "Failed to find nvm"
exit 1
}
}
nvm install "$REQUIRED_NODE_VERSION"
nvm use "$REQUIRED_NODE_VERSION"
# Beware the hardcoded path below -- it should already be in the system PATH
mkdir -p "$HOME/.keyman"
rm -f "$HOME/.keyman/node"
ln -s "$NVM_BIN" "$HOME/.keyman/node"

View file

@ -6,27 +6,29 @@
# Linux/macOS: jq
#
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
JQ_THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
# . "${THIS_SCRIPT%/*}/build-utils.sh"
## END STANDARD BUILD SCRIPT INCLUDE
if [[ -z "${JQ+x}" ]]; then
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
JQ_THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
# . "${THIS_SCRIPT%/*}/build-utils.sh"
## END STANDARD BUILD SCRIPT INCLUDE
case "${OSTYPE}" in
"cygwin")
JQ=$(dirname "$JQ_THIS_SCRIPT")/jq-win64.exe
;;
"msys")
JQ=$(dirname "$JQ_THIS_SCRIPT")/jq-win64.exe
;;
*)
JQ=jq
;;
esac
case "${OSTYPE}" in
"cygwin")
JQ=$(dirname "$JQ_THIS_SCRIPT")/jq-win64.exe
;;
"msys")
JQ=$(dirname "$JQ_THIS_SCRIPT")/jq-win64.exe
;;
*)
JQ=jq
;;
esac
readonly JQ
readonly JQ
# JQ with inplace file replacement
function jqi() {
cat <<< "$($JQ -c "$1" < "$2")" > "$2"
}
# JQ with inplace file replacement
function jqi() {
cat <<< "$($JQ -c "$1" < "$2")" > "$2"
}
fi

View file

@ -1,5 +1,16 @@
#!/usr/bin/env bash
# We only import JQ if not already defined; jq is used by
# _select_node_version_with_nvm()
if [[ -z "${JQ+x}" ]]; then
if [[ "$BUILDER_OS" == win ]]; then
. "$KEYMAN_ROOT/resources/build/jq.inc.sh"
else
JQ=jq
fi
fi
# Allows for a quick macOS check for those scripts requiring a macOS environment.
verify_on_mac() {
if [[ "${OSTYPE}" != "darwin"* ]]; then
@ -243,6 +254,13 @@ verify_npm_setup() {
fi
builder_set_module_has_been_built /external/npm-ci
# If we are on CI environment, automatically select a node version with nvm
# Also, a developer can set KEYMAN_USE_NVM variable to get this behaviour
# automatically too (see /docs/build/node.md)
if [[ "$VERSION_ENVIRONMENT" != local || ! -z "${KEYMAN_USE_NVM+x}" ]]; then
_select_node_version_with_nvm
fi
# Check if Node.JS/npm is installed.
type npm >/dev/null ||\
builder_die "Build environment setup error detected! Please ensure Node.js is installed!"
@ -252,4 +270,29 @@ verify_npm_setup() {
try_multiple_times npm ci
popd > /dev/null
}
}
# Use nvm to select a node version according to package.json
# see /docs/build/node.md
_select_node_version_with_nvm() {
local REQUIRED_NODE_VERSION="$("$JQ" -r '.engines.node' "$KEYMAN_ROOT/package.json")"
if [[ $BUILDER_OS != win ]]; then
# launch nvm in a sub process, see _builder_nvm.sh for details
"$KEYMAN_ROOT/resources/build/_builder_nvm.sh" "$REQUIRED_NODE_VERSION"
else
nvm install "$REQUIRED_NODE_VERSION"
nvm use "$REQUIRED_NODE_VERSION"
fi
# Now, check that the node version is correct, on all systems
# Note: On windows, `nvm use` and `nvm install` always return success.
# https://github.com/coreybutler/nvm-windows/issues/738
# note the 'v' prefix that node emits (and npm doesn't!)
local CURRENT_NODE_VERSION="$(node --version)"
if [[ "$CURRENT_NODE_VERSION" != "v$REQUIRED_NODE_VERSION" ]]; then
builder_die "Attempted to select node.js version $REQUIRED_NODE_VERSION but found $CURRENT_NODE_VERSION instead"
fi
}