Skip to content

Commit

Permalink
app/helpers/resources: simplify helpers and implement resources for n…
Browse files Browse the repository at this point in the history
…odejs/ruby/go/composer
  • Loading branch information
alexAubin committed Feb 9, 2025
1 parent 9c2ccba commit 86e9ce4
Show file tree
Hide file tree
Showing 8 changed files with 464 additions and 378 deletions.
64 changes: 15 additions & 49 deletions helpers/helpers.v1.d/nodejs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@

n_install_dir="/opt/node_n"
node_version_path="$n_install_dir/n/versions/node"
# N_PREFIX is the directory of n, it needs to be loaded as a environment variable.
export N_PREFIX="$n_install_dir"

# Load the version of node for an app, and set variables.
#
Expand Down Expand Up @@ -122,48 +120,13 @@ ynh_install_nodejs() {
# Create $n_install_dir
mkdir --parents "$n_install_dir"

# Load n path in PATH
CLEAR_PATH="$n_install_dir/bin:$PATH"
# Remove /usr/local/bin in PATH in case of node prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')

# Move an existing node binary, to avoid to block n.
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

# Install (or update if YunoHost vendor/ folder updated since last install) n
mkdir -p $n_install_dir/bin/
cp "$YNH_HELPERS_DIR/vendor/n/n" $n_install_dir/bin/n
# Tweak for n to understand it's installed in $N_PREFIX
ynh_replace_string --match_string="^N_PREFIX=\${N_PREFIX-.*}$" --replace_string="N_PREFIX=\${N_PREFIX-$N_PREFIX}" --target_file="$n_install_dir/bin/n"

# Restore /usr/local/bin in PATH
PATH=$CLEAR_PATH

# And replace the old node 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 nodejs
uname=$(uname --machine)
if [[ $uname =~ aarch64 || $uname =~ arm64 ]]; then
n $nodejs_version --arch=arm64
if [[ $YNH_ARCH == "arm64" ]]; then
N_PREFIX=$N_INSTALL_DIR "$YNH_HELPERS_DIR/vendor/n/n" $nodejs_version --arch=arm64
else
n $nodejs_version
N_PREFIX=$N_INSTALL_DIR "$YNH_HELPERS_DIR/vendor/n/n" $nodejs_version
fi

# Find the last "real" version for this major version of node.
real_nodejs_version=$(find $node_version_path/$nodejs_version* -maxdepth 0 | sort --version-sort | tail --lines=1)
real_nodejs_version=$(basename $real_nodejs_version)

# Create a symbolic link for this major version if the file doesn't already exist
if [ ! -e "$node_version_path/$nodejs_version" ]; then
ln --symbolic --force --no-target-directory $node_version_path/$real_nodejs_version $node_version_path/$nodejs_version
fi

# Store the ID of this app and the version of node requested for it
echo "$app:$nodejs_version" | tee --append "$n_install_dir/ynh_app_version"

# Store nodejs_version into the config of this app
ynh_app_setting_set --app=$app --key=nodejs_version --value=$nodejs_version

Expand All @@ -182,18 +145,21 @@ ynh_install_nodejs() {
ynh_remove_nodejs() {
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)

# Remove the line for this app
sed --in-place "/$app:$nodejs_version/d" "$n_install_dir/ynh_app_version"
ynh_app_setting_delete --app=$app --key=nodejs_version

# If no other app uses this version of nodejs, remove it.
if ! grep --quiet "$nodejs_version" "$n_install_dir/ynh_app_version"; then
$n_install_dir/bin/n rm $nodejs_version
fi
# Garbage-collect unused versions
local installed_versions="$(N_PREFIX=/opt/node_n "$YNH_HELPERS_DIR/vendor/n/n" ls | awk -F/ '{print $2}')"
for version in $installed_versions
do
if ! grep -qr "^nodejs_version: '$nodejs_version'" /etc/yunohost/apps/*/settings.yml
then
N_PREFIX=$N_INSTALL_DIR "$YNH_HELPERS_DIR/vendor/n/n" rm $nodejs_version
fi
done

# If no other app uses n, remove n
if [ ! -s "$n_install_dir/ynh_app_version" ]; then
ynh_secure_remove --file="$n_install_dir"
ynh_secure_remove --file="/usr/local/n"
if ! grep -qr "^nodejs_version:" /etc/yunohost/apps/*/settings.yml; then
ynh_safe_rm "$N_INSTALL_DIR"
sed --in-place "/N_PREFIX/d" /root/.bashrc
fi
}
17 changes: 4 additions & 13 deletions helpers/helpers.v1.d/ruby
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ ynh_install_ruby() {
if git remote -v 2> /dev/null | grep "https://github.com/rbenv/rbenv.git"; then
ynh_print_info --message="Updating rbenv..."
git pull -q --tags origin master
ynh_ruby_try_bash_extension
else
ynh_print_info --message="Reinstalling rbenv..."
cd ..
Expand All @@ -148,7 +147,6 @@ ynh_install_ruby() {
git init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master
ynh_ruby_try_bash_extension
rbenv=$rbenv_install_dir/bin/rbenv
fi
popd
Expand All @@ -158,7 +156,6 @@ ynh_install_ruby() {
git init -q
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
git checkout -q -b master origin/master
ynh_ruby_try_bash_extension
rbenv=$rbenv_install_dir/bin/rbenv
popd
fi
Expand Down Expand Up @@ -222,7 +219,9 @@ ynh_install_ruby() {
final_ruby_version=$ruby_version
fi
ynh_print_info --message="Installing Ruby $final_ruby_version"
RUBY_CONFIGURE_OPTS="--disable-install-doc --with-jemalloc" MAKE_OPTS="-j2" rbenv install --skip-existing $final_ruby_version > /dev/null 2>&1
RUBY_CONFIGURE_OPTS="--disable-install-doc --with-jemalloc" \
MAKE_OPTS="-j2" \
rbenv install --skip-existing $final_ruby_version > /dev/null 2>&1

# Store ruby_version into the config of this app
ynh_app_setting_set --app=$app --key=ruby_version --value=$final_ruby_version
Expand Down Expand Up @@ -307,12 +306,4 @@ ynh_cleanup_ruby() {
ynh_secure_remove --file="$rbenv_install_dir"
ynh_secure_remove --file="/etc/profile.d/rbenv.sh"
fi
}

ynh_ruby_try_bash_extension() {
if [ -x src/configure ]; then
src/configure && make -C src || {
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
}
fi
}
}
26 changes: 26 additions & 0 deletions helpers/helpers.v1.d/utils
Original file line number Diff line number Diff line change
Expand Up @@ -462,3 +462,29 @@ ynh_user_get_info() {
ynh_user_list() {
yunohost user list --output-as json --quiet | jq -r ".users | keys[]"
}

# Setup/update a git clone, meant to be used internally to fetch technical tools like goenv, rbenv
#
# [internal]
#
function _ynh_git_clone()
{
local url_and_branch="$1"
local dest_dir="$2"
local url="$(cut -f1 -d: <<< "$url_and_branch")"
local branch="$(cut -f2 -d: <<< "$url_and_branch")"
branch=${branch:-master}

mkdir -p "$dest_dir"
pushd "$dest_dir" || return 1
if ! [ -d "$dest_dir/.git" ]
then
git init -q
git remote add origin "$url"
else
git remote set-url origin "$url"
fi
git fetch -q --tags --prune origin "$branch"
git reset --hard origin/"$branch"
popd || return 1
}
126 changes: 21 additions & 105 deletions helpers/helpers.v2.1.d/go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

readonly GOENV_INSTALL_DIR="/opt/goenv"
# goenv_ROOT is the directory of goenv, it needs to be loaded as a environment variable.
export GOENV_ROOT="$GOENV_INSTALL_DIR"
readonly export GOENV_ROOT="/opt/goenv"

_ynh_load_go_in_path_and_other_tweaks() {

# Get the absolute path of this version of go
go_dir="$GOENV_INSTALL_DIR/versions/$app/bin"
go_dir="$GOENV_ROOT/versions/$go_version/bin"

# Load the path of this version of go in $PATH
if [[ :$PATH: != *":$go_dir"* ]]; then
Expand All @@ -41,7 +39,7 @@ _ynh_load_go_in_path_and_other_tweaks() {

# Sets the local application-specific go version
pushd ${install_dir}
$GOENV_INSTALL_DIR/bin/goenv local $go_version
$GOENV_ROOT/bin/goenv local $go_version
popd
}

Expand All @@ -61,81 +59,25 @@ ynh_go_install() {

[[ -n "${go_version:-}" ]] || ynh_die "\$go_version should be defined prior to calling ynh_go_install"

# Load goenv path in PATH
local CLEAR_PATH="$GOENV_INSTALL_DIR/bin:$PATH"

# Remove /usr/local/bin in PATH in case of Go prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')

# Move an existing Go binary, to avoid to block goenv
test -x /usr/bin/go && mv /usr/bin/go /usr/bin/go_goenv

# Install or update goenv
mkdir -p $GOENV_INSTALL_DIR
pushd "$GOENV_INSTALL_DIR"
if ! [ -x "$GOENV_INSTALL_DIR/bin/goenv" ]; then
ynh_print_info "Downloading goenv..."
git init -q
git remote add origin https://github.com/syndbg/goenv.git
else
ynh_print_info "Updating goenv..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
_ynh_go_try_bash_extension
goenv=$GOENV_INSTALL_DIR/bin/goenv
popd

# Install or update xxenv-latest
mkdir -p "$GOENV_INSTALL_DIR/plugins/xxenv-latest"
pushd "$GOENV_INSTALL_DIR/plugins/xxenv-latest"
if ! [ -x "$GOENV_INSTALL_DIR/plugins/xxenv-latest/bin/goenv-latest" ]; then
ynh_print_info "Downloading xxenv-latest..."
git init -q
git remote add origin https://github.com/momo-lab/xxenv-latest.git
else
ynh_print_info "Updating xxenv-latest..."
fi
git fetch -q --tags --prune origin
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git checkout -q "$git_latest_tag"
popd
_ynh_git_clone "https://github.com/syndbg/goenv" "$GOENV_ROOT"
_ynh_git_clone "https://github.com/momo-lab/xxenv-latest" "$GOENV_ROOT/plugins/xxenv-latest"

# Enable caching
mkdir -p "${GOENV_INSTALL_DIR}/cache"

mkdir -p "${GOENV_ROOT}/cache"
# Create shims directory if needed
mkdir -p "${GOENV_INSTALL_DIR}/shims"

# Restore /usr/local/bin in PATH
PATH=$CLEAR_PATH

# And replace the old Go binary
test -x /usr/bin/go_goenv && mv /usr/bin/go_goenv /usr/bin/go
mkdir -p "${GOENV_ROOT}/shims"

# Install the requested version of Go
local final_go_version=$("$GOENV_INSTALL_DIR/plugins/xxenv-latest/bin/goenv-latest" --print "$go_version")
ynh_print_info "Installation of Go-$final_go_version"
goenv install --quiet --skip-existing "$final_go_version" 2>&1

# Store go_version into the config of this app
ynh_app_setting_set --app="$app" --key="go_version" --value="$final_go_version"
local final_go_version=$("$GOENV_ROOT/plugins/xxenv-latest/bin/goenv-latest" --print "$go_version")
go_version=$final_go_version
ynh_app_setting_set --app="$app" --key="go_version" --value="$go_version"

ynh_print_info "Installation Go $go_version"
$GOENV_ROOT/bin/goenv install --quiet --skip-existing "$go_version" 2>&1

# Cleanup Go versions
_ynh_go_cleanup

# Set environment for Go users
echo "#goenv
export GOENV_ROOT=$GOENV_INSTALL_DIR
export PATH=\"$GOENV_INSTALL_DIR/bin:$PATH\"
eval \"\$(goenv init -)\"
#goenv" > /etc/profile.d/goenv.sh

# Load the environment
HOME=$install_dir eval "$(goenv init -)"

_ynh_load_go_in_path_and_other_tweaks
}

Expand All @@ -145,14 +87,6 @@ eval \"\$(goenv init -)\"
#
# usage: ynh_go_remove
ynh_go_remove() {
local go_version=$(ynh_app_setting_get --key="go_version")

# Load goenv path in PATH
local CLEAR_PATH="$GOENV_INSTALL_DIR/bin:$PATH"

# Remove /usr/local/bin in PATH in case of Go prior installation
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')

# Remove the line for this app
ynh_app_setting_delete --key="go_version"

Expand All @@ -171,38 +105,20 @@ ynh_go_remove() {
# usage: _ynh_go_cleanup
_ynh_go_cleanup() {

# List required Go versions
local installed_apps=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
local required_go_versions=""
for installed_app in $installed_apps; do
local installed_app_go_version=$(ynh_app_setting_get --app=$installed_app --key="go_version")
if [[ $installed_app_go_version ]]; then
required_go_versions="${installed_app_go_version}\n${required_go_versions}"
fi
done

# Remove no more needed Go versions
local installed_go_versions=$(goenv versions --bare --skip-aliases | grep -Ev '/')
local installed_go_versions=$($GOENV_ROOT/bin/goenv versions --bare --skip-aliases | grep -Ev '/')
for installed_go_version in $installed_go_versions; do
if ! $(echo ${required_go_versions} | grep "${installed_go_version}" 1> /dev/null 2>&1); then
ynh_print_info "Removing of Go-$installed_go_version"
$GOENV_INSTALL_DIR/bin/goenv uninstall --force "$installed_go_version"
if ! grep -qE "^go_version: '?$installed_go_version'?" /etc/yunohost/apps/*/settings.yml
ynh_print_info "Removing Go-$installed_go_version"
$GOENV_ROOT/bin/goenv uninstall --force "$installed_go_version"
fi
done

# If none Go version is required
if [[ ! $required_go_versions ]]; then
# If no app uses Go anymore
if ! grep -q "^go_version:" /etc/yunohost/apps/*/settings.yml; then
# Remove goenv environment configuration
ynh_print_info "Removing of goenv"
ynh_safe_rm "$GOENV_INSTALL_DIR"
ynh_print_info "Removing goenv"
ynh_safe_rm "$GOENV_ROOT"
ynh_safe_rm "/etc/profile.d/goenv.sh"
fi
}

_ynh_go_try_bash_extension() {
if [ -x src/configure ]; then
src/configure && make -C src || {
ynh_print_info "Optional bash extension failed to build, but things will still work normally."
}
fi
}
}
Loading

0 comments on commit 86e9ce4

Please sign in to comment.