aboutsummaryrefslogtreecommitdiff
path: root/scripts/ynh_install_ruby__2
blob: b3e3922743b033db7d1ecc2197cecc9c6b042b57 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#!/bin/bash

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

rbenv_install_dir="/opt/rbenv"
ruby_version_path="$rbenv_install_dir/versions"
# RBENV_ROOT is the directory of rbenv, it needs to be loaded as a environment variable.
export RBENV_ROOT="$rbenv_install_dir"

# Load the version of Ruby for an app, and set variables.
#
# ynh_use_ruby has to be used in any app scripts before using Ruby for the first time.
# This helper will provide alias and variables to use in your scripts.
#
# To use gem or Ruby, use the alias `ynh_gem` and `ynh_ruby`
# Those alias will use the correct version installed for the app
# For example: use `ynh_gem install` instead of `gem install`
#
# With `sudo` or `ynh_exec_as`, use instead the fallback variables `$ynh_gem` and `$ynh_ruby`
# And propagate $PATH to sudo with $ynh_ruby_load_path
# Exemple: `ynh_exec_as $app $ynh_ruby_load_path $ynh_gem install`
#
# $PATH contains the path of the requested version of Ruby.
# However, $PATH is duplicated into $ruby_path to outlast any manipulation of $PATH
# You can use the variable `$ynh_ruby_load_path` to quickly load your Ruby version
#  in $PATH for an usage into a separate script.
# Exemple: $ynh_ruby_load_path $final_path/script_that_use_gem.sh`
#
#
# Finally, to start a Ruby service with the correct version, 2 solutions
#  Either the app is dependent of Ruby or gem, but does not called it directly.
#  In such situation, you need to load PATH
#    `Environment="__YNH_RUBY_LOAD_ENV_PATH__"`
#    `ExecStart=__FINALPATH__/my_app`
#     You will replace __YNH_RUBY_LOAD_ENV_PATH__ with $ynh_ruby_load_path
#
#  Or Ruby start the app directly, then you don't need to load the PATH variable
#    `ExecStart=__YNH_RUBY__ my_app run`
#     You will replace __YNH_RUBY__ with $ynh_ruby
#
#
# one other variable is also available
#   - $ruby_path: The absolute path to Ruby binaries for the chosen version.
#
# usage: ynh_use_ruby
#
# Requires YunoHost version 2.7.12 or higher.
ynh_use_ruby () {
    ruby_version=$(ynh_app_setting_get --app=$app --key=ruby_version)

    # Get the absolute path of this version of Ruby
    ruby_path="$ruby_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 Ruby and a variable as fallback
    ynh_ruby="$ruby_path/ruby"
    alias ynh_ruby="$ynh_ruby"
    # And gem
    ynh_gem="$ruby_path/gem"
    alias ynh_gem="$ynh_gem"

    # Load the path of this version of Ruby in $PATH
    if [[ :$PATH: != *":$ruby_path"* ]]; then
        PATH="$ruby_path:$PATH"
    fi
    # Create an alias to easily load the PATH
    ynh_ruby_load_path="PATH=$PATH"

    # Sets the local application-specific Ruby version
    pushd $final_path
        $rbenv_install_dir/bin/rbenv local $ruby_version
    popd
}

# Install a specific version of Ruby
#
# ynh_install_ruby will install the version of Ruby provided as argument by using rbenv.
#
# rbenv (Ruby Version Management) stores the target Ruby version in a .ruby_version file created in the target folder (using rbenv local <version>)
# It then uses that information for every Ruby user that uses rbenv provided Ruby command
#
# This helper creates a /etc/profile.d/rbenv.sh that configures PATH environment for rbenv
# for every LOGIN user, hence your user must have a defined shell (as opposed to /usr/sbin/nologin)
#
# Don't forget to execute ruby-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 rbenv shims (e.g. $RBENV_ROOT/shims/bundle)
#
# usage: ynh_install_ruby --ruby_version=ruby_version
# | arg: -v, --ruby_version= - Version of ruby to install.
#
# Requires YunoHost version 2.7.12 or higher.
ynh_install_ruby () {
    # Declare an array to define the options of this helper.
    local legacy_args=v
    local -A args_array=( [v]=ruby_version= )
    local ruby_version
    # Manage arguments with getopts
    ynh_handle_getopts_args "$@"

    # Load rbenv path in PATH
    local CLEAR_PATH="$rbenv_install_dir/bin:$PATH"

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

    # Move an existing Ruby binary, to avoid to block rbenv
    test -x /usr/bin/ruby && mv /usr/bin/ruby /usr/bin/ruby_rbenv

    # Instal or update rbenv
    rbenv="$(command -v rbenv $rbenv_install_dir/bin/rbenv | head -1)"
    if [ -n "$rbenv" ]; then
        ynh_print_info --message="rbenv already seems installed in \`$rbenv'."
        pushd "${rbenv%/*/*}"
            if git remote -v 2>/dev/null | grep -q rbenv; then
                echo "Trying to update with git..."
                git pull -q --tags origin master
                cd ..
                ynh_ruby_try_bash_extension
            fi
        popd
    else
        ynh_print_info --message="Installing rbenv with git..."
        mkdir -p $rbenv_install_dir
        pushd $rbenv_install_dir
            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

    ruby_build="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-install rbenv-install | head -1)"
    if [ -n "$ruby_build" ]; then
        ynh_print_info --message="\`rbenv install' command already available in \`$ruby_build'."
        pushd "${ruby_build%/*/*}"
            if git remote -v 2>/dev/null | grep -q ruby-build; then
                ynh_print_info --message="Trying to update rbenv with git..."
                git pull -q origin master
            fi
        popd
    else
        ynh_print_info --message="Installing ruby-build with git..."
        mkdir -p "${rbenv_install_dir}/plugins"
        git clone -q https://github.com/rbenv/ruby-build.git "${rbenv_install_dir}/plugins/ruby-build"
    fi

    rb_alias="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-alias rbenv-alias | head -1)"
    if [ -n "$rb_alias" ]; then
        ynh_print_info --message="\`rbenv alias' command already available in \`$rb_alias'."
        pushd "${rb_alias%/*/*}"
            if git remote -v 2>/dev/null | grep -q rbenv-aliases; then
                ynh_print_info --message="Trying to update rbenv-aliases with git..."
                git pull -q origin master
            fi
        popd
    else
        ynh_print_info --message="Installing rbenv-aliases with git..."
        mkdir -p "${rbenv_install_dir}/plugins"
        git clone -q https://github.com/tpope/rbenv-aliases.git "${rbenv_install_dir}/plugins/rbenv-aliase"
    fi

    rb_latest="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-latest rbenv-latest | head -1)"
    if [ -n "$rb_latest" ]; then
        ynh_print_info --message="\`rbenv latest' command already available in \`$rb_latest'."
        pushd "${rb_latest%/*/*}"
            if git remote -v 2>/dev/null | grep -q xxenv-latest; then
                ynh_print_info --message="Trying to update xxenv-latest with git..."
                git pull -q origin master
            fi
        popd
    else
        ynh_print_info --message="Installing xxenv-latest with git..."
        mkdir -p "${rbenv_install_dir}/plugins"
        git clone -q https://github.com/momo-lab/xxenv-latest.git "${rbenv_install_dir}/plugins/xxenv-latest"
    fi

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

    # Create shims directory if needed
    mkdir -p "${rbenv_install_dir}/shims"

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

    # And replace the old Ruby binary
    test -x /usr/bin/ruby_rbenv && mv /usr/bin/ruby_rbenv /usr/bin/ruby

    # Install the requested version of Ruby
    local final_ruby_version=$(rbenv latest --print $ruby_version)
    ynh_print_info --message="Installing Ruby-$final_ruby_version"
    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=$YNH_APP_INSTANCE_NAME --key=ruby_version --value=$final_ruby_version

    # Remove app virtualenv
    if  `rbenv alias --list | grep --quiet "$YNH_APP_INSTANCE_NAME " 1>/dev/null 2>&1`
    then
        rbenv alias $YNH_APP_INSTANCE_NAME --remove
    fi

    # Create app virtualenv
    rbenv alias $YNH_APP_INSTANCE_NAME $final_ruby_version

    # Cleanup Ruby versions
    ynh_cleanup_ruby

    # Set environment for Ruby users
    echo  "#rbenv
export RBENV_ROOT=$rbenv_install_dir
export PATH=\"$rbenv_install_dir/bin:$PATH\"
eval \"\$(rbenv init -)\"
    #rbenv" > /etc/profile.d/rbenv.sh

    # Load the environment
    eval "$(rbenv init -)"
}

# Remove the version of Ruby used by the app.
#
# This helper will also cleanup Ruby versions
#
# usage: ynh_remove_ruby
ynh_remove_ruby () {
    local ruby_version=$(ynh_app_setting_get --app=$YNH_APP_INSTANCE_NAME --key=ruby_version)

    # Load rbenv path in PATH
    local CLEAR_PATH="$rbenv_install_dir/bin:$PATH"

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

    rbenv alias $YNH_APP_INSTANCE_NAME --remove

    # Remove the line for this app
    ynh_app_setting_delete --app=$YNH_APP_INSTANCE_NAME --key=ruby_version

    # Cleanup Ruby versions
    ynh_cleanup_ruby
}

# Remove no more needed versions of Ruby used by the app.
#
# This helper will check what Ruby version are no more required,
# and uninstall them
# If no app uses Ruby, rbenv will be also removed.
#
# usage: ynh_cleanup_ruby
ynh_cleanup_ruby () {

    # List required Ruby versions
    local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$')
    local required_ruby_versions=""
    for installed_app in $installed_apps
    do
        local installed_app_ruby_version=$(yunohost app setting $installed_app ruby_version)
        if [[ $installed_app_ruby_version ]]
        then
            required_ruby_versions="${installed_app_ruby_version}\n${required_ruby_versions}"
        fi
    done
    
    # Remove no more needed Ruby versions
    local installed_ruby_versions=$(rbenv versions --bare --skip-aliases | grep -Ev '/')
    for installed_ruby_version in $installed_ruby_versions
    do
        if ! `echo ${required_ruby_versions} | grep "${installed_ruby_version}" 1>/dev/null 2>&1`
        then
            ynh_print_info --message="Removing of Ruby-$installed_ruby_version"
            $rbenv_install_dir/bin/rbenv uninstall --force $installed_ruby_version
        fi
    done

    # If none Ruby version is required
    if [[ ! $required_ruby_versions ]]
    then
        # Remove rbenv environment configuration
        ynh_print_info --message="Removing of rbenv-$rbenv_version"
        ynh_secure_remove --file="$rbenv_install_dir"
        ynh_secure_remove --file="/etc/profile.d/rbenv.sh"
    fi
}