From 7a93f1c0363f0e7cf81ece04ed5ede42c151732f Mon Sep 17 00:00:00 2001 From: yalh76 Date: Mon, 8 Mar 2021 22:47:23 +0100 Subject: [PATCH] implement new ynh_install_nodejs --- scripts/_common.sh | 2 +- scripts/backup | 1 + scripts/change_url | 1 + scripts/install | 5 +- scripts/remove | 1 + scripts/restore | 3 +- scripts/upgrade | 3 +- scripts/ynh_install_nodejs | 277 +++++++++++++++++++++++++++++++++++++ 8 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 scripts/ynh_install_nodejs diff --git a/scripts/_common.sh b/scripts/_common.sh index 9145635..daa6c91 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -7,7 +7,7 @@ # dependencies used by the app pkg_dependencies="postgresql postgresql-contrib" -NODEJS_VERSION=12 +NODEJS_VERSION=12.14.1 #================================================= # PERSONAL HELPERS diff --git a/scripts/backup b/scripts/backup index 9fcc981..e4842b4 100644 --- a/scripts/backup +++ b/scripts/backup @@ -9,6 +9,7 @@ #Keep this path for calling _common.sh inside the execution's context of backup and restore scripts source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers +source ../settings/scripts/ynh_install_nodejs #================================================= # MANAGE SCRIPT FAILURE diff --git a/scripts/change_url b/scripts/change_url index cc7a858..517e313 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -8,6 +8,7 @@ source _common.sh source /usr/share/yunohost/helpers +source ynh_install_nodejs #================================================= # RETRIEVE ARGUMENTS diff --git a/scripts/install b/scripts/install index 45697eb..3cfdbd8 100644 --- a/scripts/install +++ b/scripts/install @@ -9,6 +9,7 @@ source _common.sh source ynh_send_readme_to_admin__2 source /usr/share/yunohost/helpers +source ynh_install_nodejs #================================================= # MANAGE SCRIPT FAILURE @@ -70,9 +71,8 @@ ynh_app_setting_set --app=$app --key=port --value=$port #================================================= ynh_script_progression --message="Installing dependencies..." -ynh_install_nodejs --nodejs_version=$NODEJS_VERSION -ynh_use_nodejs ynh_install_app_dependencies $pkg_dependencies +ynh_install_nodejs --nodejs_version=$NODEJS_VERSION #================================================= # CREATE A POSTGRESQL DATABASE @@ -96,6 +96,7 @@ ynh_script_progression --message="Setting up source files..." ynh_app_setting_set --app=$app --key=final_path --value=$final_path # Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$final_path" +ynh_use_nodejs #================================================= # NGINX CONFIGURATION diff --git a/scripts/remove b/scripts/remove index 9286422..189f677 100644 --- a/scripts/remove +++ b/scripts/remove @@ -8,6 +8,7 @@ source _common.sh source /usr/share/yunohost/helpers +source ynh_install_nodejs #================================================= # LOAD SETTINGS diff --git a/scripts/restore b/scripts/restore index f23531c..cb4d8a6 100644 --- a/scripts/restore +++ b/scripts/restore @@ -9,6 +9,7 @@ #Keep this path for calling _common.sh inside the execution's context of backup and restore scripts source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers +source ../settings/scripts/ynh_install_nodejs #================================================= # MANAGE SCRIPT FAILURE @@ -86,9 +87,9 @@ chown -R "$app":"$app" "$final_path" ynh_script_progression --message="Reinstalling dependencies..." # Define and install dependencies +ynh_install_app_dependencies $pkg_dependencies ynh_install_nodejs --nodejs_version=$NODEJS_VERSION ynh_use_nodejs -ynh_install_app_dependencies $pkg_dependencies #================================================= # RESTORE THE POSTGRESQL DATABASE diff --git a/scripts/upgrade b/scripts/upgrade index 33037ca..b939e60 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -9,6 +9,7 @@ source _common.sh source ynh_send_readme_to_admin__2 source /usr/share/yunohost/helpers +source ynh_install_nodejs #================================================= # LOAD SETTINGS @@ -135,9 +136,9 @@ ynh_add_nginx_config #================================================= ynh_script_progression --message="Upgrading dependencies..." +ynh_install_app_dependencies $pkg_dependencies ynh_install_nodejs --nodejs_version=$NODEJS_VERSION ynh_use_nodejs -ynh_install_app_dependencies $pkg_dependencies #================================================= # CREATE DEDICATED USER diff --git a/scripts/ynh_install_nodejs b/scripts/ynh_install_nodejs new file mode 100644 index 0000000..8906731 --- /dev/null +++ b/scripts/ynh_install_nodejs @@ -0,0 +1,277 @@ +#!/bin/bash + +nodenv_version=1.4.0 +node_build_version=4.9.32 +nodenv_aliases_version=2.0.2 +nodenv_install_dir="/opt/nodenv" +node_version_path="$nodenv_install_dir/versions" +# NODENV_ROOT is the directory of nodenv, it needs to be loaded as a environment variable. +export NODENV_ROOT="$nodenv_install_dir" + +# Install Node.js Version Management +# +# [internal] +# +# usage: ynh_install_nodenv +# +# Requires YunoHost version 2.7.12 or higher. +ynh_install_nodenv () { + ynh_print_info --message="Installation of nodenv - Node.js Version Management - nodenv-${nodenv_version}/node-build-${node_build_version}" + + # Build an app.src for nodenv + mkdir -p "../conf" + echo "SOURCE_URL=https://github.com/nodenv/nodenv/archive/v${nodenv_version}.tar.gz +SOURCE_SUM=33e2f3e467219695ba114f75a7c769f3ee4e29b29c1c97a852aa001327ca9713" > "../conf/nodenv.src" + # Download and extract nodenv + ynh_setup_source --dest_dir="$nodenv_install_dir" --source_id=nodenv + + # Build an app.src for node-build + mkdir -p "../conf" + echo "SOURCE_URL=https://github.com/nodenv/node-build/archive/v${node_build_version}.tar.gz +SOURCE_SUM=e2c98e06f9fb31865d7e23be8d49b8adb5ed1ede1d16ec87b0e06865689ea718" > "../conf/node-build.src" + # Download and extract node-build + ynh_setup_source --dest_dir="$nodenv_install_dir/plugins/node-build" --source_id=node-build + + # Build an app.src for nodenv-aliases + mkdir -p "../conf" + echo "SOURCE_URL=https://github.com/nodenv/nodenv-aliases/archive/v${nodenv_aliases_version}.tar.gz +SOURCE_SUM=632193b462438c986c104edc95f5378c067e02f6f8d1a7be38d5017183ab0149" > "../conf/nodenv-aliases.src" + # Download and extract nodenv-aliases + ynh_setup_source --dest_dir="$nodenv_install_dir/plugins/nodenv-aliases" --source_id=nodenv-aliases + + (cd $nodenv_install_dir + ./src/configure && make -C src) + + # Create shims directory if needed + if [ ! -d $nodenv_install_dir/shims ] ; then + mkdir $nodenv_install_dir/shims + fi +} + +# Load the version of Node.js for an app, and set variables. +# +# ynh_use_nodejs has to be used in any app scripts before using Node.js for the first time. +# This helper will provide alias and variables to use in your scripts. +# +# To use npm or node, use the alias `ynh_npm` and `ynh_node` +# Those alias will use the correct version installed for the app +# For example: use `ynh_npm install` instead of `npm install` +# +# With `sudo` or `ynh_exec_as`, use instead the fallback variables `$ynh_npm` and `$ynh_node` +# And propagate $PATH to sudo with $ynh_node_load_path +# Exemple: `ynh_exec_as $app $ynh_node_load_path $ynh_npm install` +# +# $PATH contains the path of the requested version of Node.js. +# However, $PATH is duplicated into $nodejs_path to outlast any manipulation of $PATH +# You can use the variable `$ynh_node_load_path` to quickly load your Node.js version +# in $PATH for an usage into a separate script. +# Exemple: $ynh_node_load_path $final_path/script_that_use_npm.sh` +# +# +# Finally, to start a Node.js service with the correct version, 2 solutions +# Either the app is dependent of Node.js or npm, but does not called it directly. +# In such situation, you need to load PATH +# `Environment="__YNH_NODE_LOAD_PATH__"` +# `ExecStart=__FINALPATH__/my_app` +# You will replace __YNH_NODE_LOAD_PATH__ with $ynh_node_load_path +# +# Or Node.js start the app directly, then you don't need to load the PATH variable +# `ExecStart=__YNH_NODE__ my_app run` +# You will replace __YNH_NODE__ with $ynh_node +# +# +# one other variable is also available +# - $nodejs_path: The absolute path to Node.js binaries for the chosen version. +# +# usage: ynh_use_nodejs +# +# Requires YunoHost version 2.7.12 or higher. +ynh_use_nodejs () { + nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version) + + # Get the absolute path of this version of Node.js + nodejs_path="$node_version_path/$YNH_APP_INSTANCE_NAME/bin" + + # Allow alias to be used into bash script + shopt -s expand_aliases + + # Create an alias for the specific version of Node.js and a variable as fallback + ynh_node="$nodejs_path/node" + alias ynh_node="$ynh_node" + # And npm + ynh_npm="$nodejs_path/npm" + alias ynh_npm="$ynh_npm" + + # Load the path of this version of Node.js in $PATH + if [[ :$PATH: != *":$nodejs_path"* ]]; then + PATH="$nodejs_path:$PATH" + fi + # Create an alias to easily load the PATH + ynh_node_load_PATH="PATH=$PATH" + ynh_node_load_path="PATH=$PATH" + + # Sets the local application-specific Node.js version + (cd $final_path + nodenv local $nodejs_version) +} + +# Install a specific version of Node.js +# +# ynh_install_nodejs will install the version of Node.js provided as argument by using nodenv. +# +# nodenv (Node.js Version Management) stores the target Node.js version in a .nodejs_version file created in the target folder (using nodenv local ) +# It then uses that information for every Node.js user that uses nodenv provided Node.js command +# +# This helper creates a /etc/profile.d/nodenv.sh that configures PATH environment for nodenv +# for every LOGIN user, hence your user must have a defined shell (as opposed to /usr/sbin/nologin) +# +# Don't forget to execute Node.js-dependent command in a login environment +# (e.g. sudo --login option) +# When not possible (e.g. in systemd service definition), please use direct path +# to nodenv shims (e.g. $NODENV_ROOT/shims/bundle) +# +# usage: ynh_install_nodejs --nodejs_version=nodejs_version +# | arg: -v, --nodejs_version= - Version of Node.js to install. +# +# Requires YunoHost version 2.7.12 or higher. +ynh_install_nodejs () { + # Declare an array to define the options of this helper. + local legacy_args=v + local -A args_array=( [v]=nodejs_version= ) + local nodejs_version + # Manage arguments with getopts + ynh_handle_getopts_args "$@" + + # Store nodejs_version into the config of this app + ynh_app_setting_set --app=$YNH_APP_INSTANCE_NAME --key=nodejs_version --value=$nodejs_version + + # Create $nodenv_install_dir if doesn't exist already + mkdir -p "$nodenv_install_dir/plugins/node-build" + + # Load nodenv path in PATH + local CLEAR_PATH="$nodenv_install_dir/bin:$PATH" + + # Remove /usr/local/bin in PATH in case of Node.js prior installation + PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@') + + # Move an existing Node.js binary, to avoid to block nodenv + test -x /usr/bin/node && mv /usr/bin/node /usr/bin/node_n + test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n + + # If nodenv is not previously setup, install it + if ! type nodenv > /dev/null 2>&1 + then + ynh_install_nodenv + elif dpkg --compare-versions "$($nodenv_install_dir/bin/nodenv --version | cut -d" " -f2)" lt $nodenv_version + then + ynh_install_nodenv + elif dpkg --compare-versions "$($nodenv_install_dir/plugins/node-build/bin/node-build --version | cut -d" " -f2)" lt $node_build_version + then + ynh_install_nodenv + fi + + # Restore /usr/local/bin in PATH + PATH=$CLEAR_PATH + + # And replace the old Node.js binary + test -x /usr/bin/node_n && mv /usr/bin/node_n /usr/bin/node + test -x /usr/bin/npm_n && mv /usr/bin/npm_n /usr/bin/npm + + # Install the requested version of Node.js + ynh_print_info --message="Installation of Node.js-"$nodejs_version + nodenv install --skip-existing $nodejs_version + + # Remove app virtualenv + if `nodenv alias --list | grep --quiet "$YNH_APP_INSTANCE_NAME" 1>/dev/null 2>&1` + then + nodenv alias $YNH_APP_INSTANCE_NAME --remove + fi + + # Create app virtualenv + nodenv alias $YNH_APP_INSTANCE_NAME $nodejs_version + + # Cleanup Node.js versions + ynh_cleanup_nodejs + + # Set environment for Node.js users + echo "#nodenv +export NODENV_ROOT=$nodenv_install_dir +export PATH=\"$nodenv_install_dir/bin:$PATH\" +eval \"\$(nodenv init -)\" + #nodenv" > /etc/profile.d/nodenv.sh + + # Load the environment + eval "$(nodenv init -)" +} + +# Remove the version of Node.js used by the app. +# +# This helper will also cleanup Node.js versions +# +# usage: ynh_remove_nodejs +ynh_remove_nodejs () { + local nodejs_version=$(ynh_app_setting_get --app=$YNH_APP_INSTANCE_NAME --key=nodejs_version) + + # Load nodenv path in PATH + local CLEAR_PATH="$nodenv_install_dir/bin:$PATH" + + # Remove /usr/local/bin in PATH in case of Node.js prior installation + PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@') + + nodenv alias $YNH_APP_INSTANCE_NAME --remove + + # Remove the line for this app + ynh_app_setting_delete --app=$YNH_APP_INSTANCE_NAME --key=nodejs_version + + # Cleanup Node.js versions + ynh_cleanup_nodejs +} + +# Remove no more needed versions of Node.js used by the app. +# +# This helper will check what Node.js version are no more required, +# and uninstall them +# If no app uses Node.js, nodenv will be also removed. +# +# usage: ynh_cleanup_nodejs +ynh_cleanup_nodejs () { + + # List required Node.js version + local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$') + local required_nodejs_versions="" + for installed_app in $installed_apps + do + local installed_app_nodejs_version=$(yunohost app setting $installed_app nodejs_version) + if [[ $installed_app_nodejs_version ]] + then + required_nodejs_versions="${installed_app_nodejs_version}\n${required_nodejs_versions}" + fi + done + + # Remove no more needed Node.js version + local installed_nodejs_versions=$(nodenv versions --bare --skip-aliases | grep -Ev '/') + for installed_nodejs_version in $installed_nodejs_versions + do + if ! `echo ${required_nodejs_versions} | grep "${installed_nodejs_version}" 1>/dev/null 2>&1` + then + ynh_print_info --message="Removing of Node.js-"$installed_nodejs_version + $nodenv_install_dir/bin/nodenv uninstall --force $installed_nodejs_version + fi + done + + # If none Node.js version is required + if [[ ! $required_nodejs_versions ]] + then + # Remove nodenv environment configuration + ynh_print_info --message="Removing of nodenv-"$nodenv_version + ynh_secure_remove --file="$nodenv_install_dir" + rm /etc/profile.d/nodenv.sh + + # Remove previous n Version Management + n_install_dir="/opt/node_n" + ynh_secure_remove --file="$n_install_dir" + ynh_secure_remove --file="/usr/local/n" + sed --in-place "/$n_install_dir/d" /root/.bashrc + rm --force /etc/cron.daily/node_update + fi +}