diff --git a/check_process b/check_process index ed1eab47..0da03b43 100644 --- a/check_process +++ b/check_process @@ -14,6 +14,8 @@ # upgrade=1 from_commit=605a47aac7553fdcc6012531ee67add8dbe37b97 # 0.10.7 # upgrade=1 from_commit=7fa86c3e6e6db6668be0a165213d554850b9fce8 + # 0.10.8 + upgrade=1 from_commit=10c3703567d1e9504ea4f298778464c7dd561470 backup_restore=1 multi_instance=1 # This test is no longer necessary since the version 2.7 (PR: https://github.com/YunoHost/yunohost/pull/304), you can still do it if your app could be installed with this version. diff --git a/conf/horizon.conf b/conf/horizon.conf new file mode 100644 index 00000000..0b7996cd --- /dev/null +++ b/conf/horizon.conf @@ -0,0 +1,9 @@ +[program:__APP__-horizon] +process_name=%(program_name)s +command=php7.3 __FINALPATH__/artisan horizon +autostart=true +autorestart=true +user=__APP__ +redirect_stderr=true +stdout_logfile=/var/log/__APP__/__APP__-horizon.log +stopwaitsecs=3600 \ No newline at end of file diff --git a/conf/horizon.service b/conf/horizon.service deleted file mode 100644 index eb53dfd2..00000000 --- a/conf/horizon.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=__APP__ Horizon Service -After=network.target - -[Service] -Type=simple -User=__APP__ -Group=__APP__ -WorkingDirectory=__FINALPATH__/ -ExecStart=/usr/bin/php7.3 __FINALPATH__/artisan horizon -Restart=on-failure - -[Install] -WantedBy=multi-user.target diff --git a/manifest.json b/manifest.json index 6c543005..b89b30dd 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "ActivityPub Federated Image Sharing", "fr": "Logiciel de partage d'image fédéré via ActivityPub" }, - "version": "0.10.9~ynh1", + "version": "0.10.9~ynh2", "url": "https://pixelfed.org/", "license": "AGPL-3.0-or-later", "maintainer": [ diff --git a/scripts/_common.sh b/scripts/_common.sh index e26a1941..f644938f 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -5,9 +5,10 @@ #================================================= # dependencies used by the app -pkg_dependencies="postgresql redis-server imagemagick jpegoptim optipng pngquant" +pkg_dependencies="postgresql redis-server imagemagick jpegoptim optipng pngquant supervisor" -extra_pkg_dependencies="php7.3-bcmath php7.3-ctype php7.3-curl php7.3-exif php7.3-iconv php7.3-intl php7.3-json php7.3-mbstring php7.3-openssl php7.3-tokenizer php7.3-xml php7.3-zip php7.3-pgsql" +extra_pkg_dependencies="php7.3-bcmath php7.3-ctype php7.3-curl php7.3-exif php7.3-iconv php7.3-intl php7.3-json php7.3-mbstring php7.3-tokenizer php7.3-xml php7.3-zip php7.3-pgsql" +# php7.3-openssl #================================================= # PERSONAL HELPERS diff --git a/scripts/backup b/scripts/backup index 8c6b7521..057cb238 100644 --- a/scripts/backup +++ b/scripts/backup @@ -8,6 +8,7 @@ #Keep this path for calling _common.sh inside the execution's context of backup and restore scripts source ../settings/scripts/_common.sh +source ../settings/scripts/ynh_supervisor source /usr/share/yunohost/helpers #================================================= @@ -35,11 +36,11 @@ db_name=$(ynh_app_setting_get --app="$app" --key=db_name) #================================================= # STANDARD BACKUP STEPS #================================================= -# STOP SYSTEMD SERVICE +# STOP SUPERVISOR SERVICE #================================================= -ynh_print_info --message="Stopping a systemd service..." +ynh_print_info --message="Stopping a supervisor service..." -ynh_systemd_action --service_name="${app}-horizon" --action="stop" --log_path=systemd +ynh_supervisor_action --service_name="${app}-horizon" --action="stop" --log_path="/var/log/$app/${app}-horizon.log" #================================================= # BACKUP THE APP MAIN DIR @@ -72,18 +73,25 @@ ynh_psql_dump_db --database="$db_name" > db.sql #================================================= # SPECIFIC BACKUP #================================================= -# BACKUP SYSTEMD +# BACKUP LOGROTATE #================================================= -ynh_print_info --message="Backing up systemd configuration..." +ynh_print_info --message="Backing up logrotate configuration..." -ynh_backup --src_path="/etc/systemd/system/${app}-horizon.service" +ynh_backup --src_path="/etc/logrotate.d/$app" #================================================= -# START SYSTEMD SERVICE +# BACKUP SUPERVISOR #================================================= -ynh_print_info --message="Starting a systemd service..." +ynh_print_info --message="Backing up supervisor configuration..." -ynh_systemd_action --service_name="${app}-horizon" --action="start" --log_path=systemd +ynh_backup --src_path="/etc/supervisor/conf.d/${app}-horizon.conf" + +#================================================= +# START SUPERVISOR SERVICE +#================================================= +ynh_print_info --message="Starting a supervisor service..." + +ynh_supervisor_action --service_name="${app}-horizon" --action="start" --log_path="/var/log/$app/${app}-horizon.log" #================================================= # END OF SCRIPT diff --git a/scripts/change_url b/scripts/change_url index e541478d..946f8232 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -64,6 +64,13 @@ fi #================================================= # STANDARD MODIFICATIONS +#================================================= +# STOP SUPERVISOR SERVICE +#================================================= +ynh_print_info --message="Stopping a supervisor service..." + +ynh_supervisor_action --service_name="${app}-horizon" --action="stop" --log_path="/var/log/$app/${app}-horizon.log" + #================================================= # MODIFY URL IN NGINX CONF #================================================= @@ -119,6 +126,13 @@ popd #================================================= # GENERIC FINALISATION +#================================================= +# START SUPERVISOR SERVICE +#================================================= +ynh_print_info --message="Starting a supervisor service..." + +ynh_supervisor_action --service_name="${app}-horizon" --action="start" --log_path="/var/log/$app/${app}-horizon.log" + #================================================= # RELOAD NGINX #================================================= diff --git a/scripts/install b/scripts/install index 4466a2b2..f34c2c6e 100644 --- a/scripts/install +++ b/scripts/install @@ -10,6 +10,7 @@ source _common.sh source ynh_composer__2 source ynh_add_extra_apt_repos__3 source ynh_install_php__3 +source ynh_supervisor source /usr/share/yunohost/helpers #================================================= @@ -138,12 +139,21 @@ ynh_install_composer --phpversion="7.3" --workdir="$final_path" #================================================= # SPECIFIC SETUP #================================================= -# SETUP SYSTEMD +# CREATE LOG FILE #================================================= -ynh_print_info --message="Configuring a systemd service..." +ynh_print_info --message="Creating log file..." -# Create a dedicated systemd config -ynh_add_systemd_config --service="${app}-horizon" --template=horizon.service +mkdir -p "/var/log/$app/" +touch "/var/log/$app/${app}-horizon.log" +chown -R root: "/var/log/$app/" + +#================================================= +# SETUP SUPERVISOR +#================================================= +ynh_print_info --message="Configuring a supervisor service..." + +# Create a dedicated supervisor config +ynh_add_supervisor_config --service="${app}-horizon" --template=horizon.conf #================================================= # MODIFY A CONFIG FILE @@ -199,6 +209,14 @@ ynh_print_info --message="Securing files and directories..." chown -R root: "$final_path" chown -R "$app": "$final_path/storage/" +#================================================= +# SETUP LOGROTATE +#================================================= +ynh_print_info --message="Configuring log rotation..." + +# Use logrotate to manage application logfile(s) +ynh_use_logrotate --logfile="/var/log/$app/${app}-horizon.log" + #================================================= # INTEGRATE SERVICE IN YUNOHOST #================================================= @@ -207,12 +225,12 @@ ynh_print_info --message="Integrating service in YunoHost..." yunohost service add "${app}-horizon" --description "${app}-horizon daemon for $app" --log "/var/log/$app/${app}-horizon.log" #================================================= -# START SYSTEMD SERVICE +# START SUPERVISOR SERVICE #================================================= -ynh_print_info --message="Starting a systemd service..." +ynh_print_info --message="Starting a supervisor service..." -# Start a systemd service -ynh_systemd_action --service_name="${app}-horizon" --action="start" --log_path=systemd +# Start a supervisor service +ynh_supervisor_action --service_name="${app}-horizon" --action="start" --log_path="/var/log/$app/${app}-horizon.log" --line_match="Horizon started successfully" #================================================= # SETUP SSOWAT diff --git a/scripts/remove b/scripts/remove index e73ea107..7a7fd426 100644 --- a/scripts/remove +++ b/scripts/remove @@ -9,6 +9,7 @@ source _common.sh source ynh_add_extra_apt_repos__3 source ynh_install_php__3 +source ynh_supervisor source /usr/share/yunohost/helpers #================================================= @@ -40,10 +41,10 @@ fi #================================================= # STOP AND REMOVE SERVICE #================================================= -ynh_print_info --message="Stopping and removing the systemd service..." +ynh_print_info --message="Stopping and removing the supervisor service..." -# Remove the dedicated systemd config -ynh_remove_systemd_config --service="${app}-horizon" +# Remove the dedicated supervisor config +ynh_remove_supervisor_config --service="${app}-horizon" #================================================= # REMOVE THE POSTGRESQL DATABASE @@ -88,6 +89,24 @@ ynh_print_info --message="Removing php-fpm configuration..." # Remove the dedicated php-fpm config ynh_remove_fpm_config +#================================================= +# REMOVE LOGROTATE CONFIGURATION +#================================================= +ynh_print_info --message="Removing logrotate configuration..." + +# Remove the app-specific logrotate config +ynh_remove_logrotate + +#================================================= +# SPECIFIC REMOVE +#================================================= +# REMOVE THE LOG FILE +#================================================= +ynh_print_info --message="Removing the log file..." + +# Remove the log files +ynh_secure_remove --file="/var/log/$app" + #================================================= # GENERIC FINALIZATION #================================================= diff --git a/scripts/restore b/scripts/restore index 15192fba..7882de6a 100644 --- a/scripts/restore +++ b/scripts/restore @@ -10,6 +10,7 @@ source ../settings/scripts/_common.sh source ../settings/scripts/ynh_add_extra_apt_repos__3 source ../settings/scripts/ynh_install_php__3 +source ../settings/scripts/ynh_supervisor source /usr/share/yunohost/helpers #================================================= @@ -117,12 +118,21 @@ ynh_psql_setup_db --db_user="$db_user" --db_name="$db_name" --db_pwd="$db_pwd" ynh_psql_execute_file_as_root --file="./db.sql" --database="$db_name" #================================================= -# RESTORE SYSTEMD +# CREATE LOG FILE #================================================= -ynh_print_info --message="Restoring the systemd configuration..." +ynh_print_info --message="Creating log file..." -ynh_restore_file --origin_path="/etc/systemd/system/${app}-horizon.service" -systemctl enable ${app}-horizon.service +mkdir -p "/var/log/$app/" +touch "/var/log/$app/${app}-horizon.log" +chown -R root: "/var/log/$app/" + +#================================================= +# RESTORE SUPERVISOR +#================================================= +ynh_print_info --message="Restoring the supervisor configuration..." + +ynh_restore_file --origin_path="/etc/supervisor/conf.d/${app}-horizon.conf" +supervisorctl reread && supervisorctl update #================================================= # INTEGRATE SERVICE IN YUNOHOST @@ -132,11 +142,18 @@ ynh_print_info --message="Integrating service in YunoHost..." yunohost service add "${app}-horizon" --log "/var/log/$app/${app}-horizon.log" #================================================= -# START SYSTEMD SERVICE +# START SUPERVISOR SERVICE #================================================= -ynh_print_info --message="Starting a systemd service..." +ynh_print_info --message="Starting a supervisor service..." -ynh_systemd_action --service_name="${app}-horizon" --action="start" --log_path=systemd +ynh_supervisor_action --service_name="${app}-horizon" --action="start" --log_path="/var/log/$app/${app}-horizon.log" + +#================================================= +# RESTORE THE LOGROTATE CONFIGURATION +#================================================= +ynh_print_info --message="Restoring the logrotate configuration..." + +ynh_restore_file --origin_path="/etc/logrotate.d/$app" #================================================= # GENERIC FINALIZATION diff --git a/scripts/upgrade b/scripts/upgrade index 95826f98..cbe5aed8 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -10,6 +10,7 @@ source _common.sh source ynh_composer__2 source ynh_add_extra_apt_repos__3 source ynh_install_php__3 +source ynh_supervisor source /usr/share/yunohost/helpers #================================================= @@ -63,16 +64,6 @@ if [ -z "$final_path" ]; then ynh_app_setting_set --app="$app" --key=final_path --value="$final_path" fi -# If app_key doesn't exist, retrieve it -if [ -z "$app_key" ]; then - app_key=$(grep -oP "APP_KEY=\Kbase64.*" "$final_path/.env") - ynh_app_setting_set --app="$app" --key=app_key --value="$app_key" -fi - -if dpkg --compare-versions "0.9.0~ynh3" gt "$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)" ; then - ynh_add_systemd_config --service="${app}-horizon" --template=horizon.service -fi - #================================================= # BACKUP BEFORE UPGRADE THEN ACTIVE TRAP #================================================= @@ -87,14 +78,39 @@ ynh_clean_setup () { # Exit if an error occurs during the execution of the script ynh_abort_if_errors +#================================================= +# ENSURE UPGRADE COMPATIBILITY +#================================================= +ynh_print_info --message="Ensuring upgrade compatibility..." + +# If app_key doesn't exist, retrieve it +if [ -z "$app_key" ]; then + app_key=$(grep -oP "APP_KEY=\Kbase64.*" "$final_path/.env") + ynh_app_setting_set --app="$app" --key=app_key --value="$app_key" +fi + +if dpkg --compare-versions "0.9.0~ynh3" gt "$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)" ; then + ynh_add_systemd_config --service="${app}-horizon" --template=horizon.service +fi + +if dpkg --compare-versions "0.10.9~ynh2" gt "$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)" ; then + ynh_remove_systemd_config --service="${app}-horizon" + ynh_install_app_dependencies "$pkg_dependencies" + mkdir -p "/var/log/$app/" + touch "/var/log/$app/${app}-horizon.log" + chown -R root: "/var/log/$app/" + ynh_add_supervisor_config --service="${app}-horizon" --template=horizon.conf + ynh_supervisor_action --service_name="${app}-horizon" --action="start" --log_path="/var/log/$app/${app}-horizon.log" +fi + #================================================= # STANDARD UPGRADE STEPS #================================================= -# STOP SYSTEMD SERVICE +# STOP SUPERVISOR SERVICE #================================================= -ynh_print_info --message="Stopping a systemd service..." +ynh_print_info --message="Stopping a supervisor service..." -ynh_systemd_action --service_name="${app}-horizon" --action="stop" --log_path=systemd +ynh_supervisor_action --service_name="${app}-horizon" --action="stop" --log_path="/var/log/$app/${app}-horizon.log" #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE @@ -202,12 +218,29 @@ pushd "$final_path" popd #================================================= -# SETUP SYSTEMD +# CREATE LOG FILE #================================================= -ynh_print_info --message="Upgrading systemd configuration..." +ynh_print_info --message="Creating log file..." -# Create a dedicated systemd config -ynh_add_systemd_config --service="${app}-horizon" --template=horizon.service +mkdir -p "/var/log/$app/" +touch "/var/log/$app/${app}-horizon.log" +chown -R root: "/var/log/$app/" + +#================================================= +# SETUP LOGROTATE +#================================================= +ynh_script_progression --message="Upgrading logrotate configuration..." --time --weight=1 + +# Use logrotate to manage app-specific logfile(s) +ynh_use_logrotate --non-append + +#================================================= +# SETUP SUPERVISOR +#================================================= +ynh_print_info --message="Upgrading supervisor configuration..." + +# Create a dedicated supervisor config +ynh_add_supervisor_config --service="${app}-horizon" --template=horizon.service #================================================= # GENERIC FINALIZATION @@ -232,11 +265,11 @@ then fi #================================================= -# START SYSTEMD SERVICE +# START SUPERVISOR SERVICE #================================================= -ynh_print_info --message="Starting a systemd service..." +ynh_print_info --message="Starting a supervisor service..." -ynh_systemd_action --service_name="${app}-horizon" --action="start" --log_path=systemd +ynh_supervisor_action --service_name="${app}-horizon" --action="start" --log_path="/var/log/$app/${app}-horizon.log" #================================================= # RELOAD NGINX diff --git a/scripts/ynh_supervisor b/scripts/ynh_supervisor new file mode 100644 index 00000000..838224d6 --- /dev/null +++ b/scripts/ynh_supervisor @@ -0,0 +1,177 @@ +#!/bin/bash + +# Create a dedicated supervisor config +# +# usage: ynh_add_supervisor_config [--service=service] [--template=template] +# | arg: -s, --service - Service name (optionnal, $app by default) +# | arg: -t, --template - Name of template file (optionnal, this is 'supervisor' by default, meaning ./conf/supervisor.service will be used as template) +# +# This will use the template ../conf/.service +# to generate a supervisor config, by replacing the following keywords +# with global variables that should be defined before calling +# this helper : +# +# __APP__ by $app +# __FINALPATH__ by $final_path +# +# Requires YunoHost version 2.7.2 or higher. +ynh_add_supervisor_config () { + # Declare an array to define the options of this helper. + local legacy_args=st + declare -Ar args_array=( [s]=service= [t]=template= ) + local service + local template + # Manage arguments with getopts + ynh_handle_getopts_args "$@" + local service="${service:-$app}" + local template="${template:-supervisor.service}" + + finalsupervisorconf="/etc/supervisor/conf.d/$service.conf" + ynh_backup_if_checksum_is_different --file="$finalsupervisorconf" + cp ../conf/$template "$finalsupervisorconf" + + # To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable. + # Substitute in a nginx config file only if the variable is not empty + if test -n "${final_path:-}"; then + ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalsupervisorconf" + fi + if test -n "${app:-}"; then + ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$finalsupervisorconf" + fi + ynh_store_file_checksum --file="$finalsupervisorconf" + + chown root: "$finalsupervisorconf" + supervisorctl reread + supervisorctl update +} + +# Remove the dedicated supervisor config +# +# usage: ynh_remove_supervisor_config [--service=service] +# | arg: -s, --service - Service name (optionnal, $app by default) +# +# Requires YunoHost version 2.7.2 or higher. +ynh_remove_supervisor_config () { + # Declare an array to define the options of this helper. + local legacy_args=s + declare -Ar args_array=( [s]=service= ) + local service + # Manage arguments with getopts + ynh_handle_getopts_args "$@" + local service="${service:-$app}" + + local finalsupervisorconf="/etc/supervisor/conf.d/$service.conf" + if [ -e "$finalsupervisorconf" ]; then + ynh_supervisor_action --service_name=$service --action=stop + ynh_secure_remove --file="$finalsupervisorconf" + supervisorctl reread + supervisorctl update + fi +} + +# Start (or other actions) a service, print a log in case of failure and optionnaly wait until the service is completely started +# +# usage: ynh_supervisor_action [-n service_name] [-a action] [ [-l "line to match"] [-p log_path] [-t timeout] [-e length] ] +# | arg: -n, --service_name= - Name of the service to start. Default : $app +# | arg: -a, --action= - Action to perform with supervisorctl. Default: start +# | arg: -l, --line_match= - Line to match - The line to find in the log to attest the service have finished to boot. If not defined it don't wait until the service is completely started. WARNING: When using --line_match, you should always add `ynh_clean_check_starting` into your `ynh_clean_setup` at the beginning of the script. Otherwise, tail will not stop in case of failure of the script. The script will then hang forever. +# | arg: -p, --log_path= - Log file - Path to the log file. Default : /var/log/$app/$app.log +# | arg: -t, --timeout= - Timeout - The maximum time to wait before ending the watching. Default : 300 seconds. +# | arg: -e, --length= - Length of the error log : Default : 20 +ynh_supervisor_action() { + # Declare an array to define the options of this helper. + local legacy_args=nalpte + declare -Ar args_array=( [n]=service_name= [a]=action= [l]=line_match= [p]=log_path= [t]=timeout= [e]=length= ) + local service_name + local action + local line_match + local length + local log_path + local timeout + + # Manage arguments with getopts + ynh_handle_getopts_args "$@" + + local service_name="${service_name:-$app}" + local action=${action:-start} + local log_path="${log_path:-/var/log/$service_name/$service_name.log}" + local length=${length:-20} + local timeout=${timeout:-300} + + # Start to read the log + if [[ -n "${line_match:-}" ]] + then + local templog="$(mktemp)" + # Following the starting of the app in its log + if [ "$log_path" == "supervisor" ] ; then + # Read the supervisor journal + journalctl --unit=$service_name --follow --since=-0 --quiet > "$templog" & + # Get the PID of the journalctl command + local pid_tail=$! + else + # Read the specified log file + tail -F -n0 "$log_path" > "$templog" 2>&1 & + # Get the PID of the tail command + local pid_tail=$! + fi + fi + + # Use reload-or-restart instead of reload. So it wouldn't fail if the service isn't running. + if [ "$action" == "reload" ]; then + action="reload-or-restart" + fi + + supervisorctl $action $service_name \ + || ( journalctl --no-pager --lines=$length -u $service_name >&2 \ + ; test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2 \ + ; false ) + + # Start the timeout and try to find line_match + if [[ -n "${line_match:-}" ]] + then + local i=0 + for i in $(seq 1 $timeout) + do + # Read the log until the sentence is found, that means the app finished to start. Or run until the timeout + if grep --quiet "$line_match" "$templog" + then + ynh_print_info --message="The service $service_name has correctly executed the action ${action}." + break + fi + if [ $i -eq 3 ]; then + echo -n "Please wait, the service $service_name is ${action}ing" >&2 + fi + if [ $i -ge 3 ]; then + echo -n "." >&2 + fi + sleep 1 + done + if [ $i -ge 3 ]; then + echo "" >&2 + fi + if [ $i -eq $timeout ] + then + ynh_print_warn --message="The service $service_name didn't fully executed the action ${action} before the timeout." + ynh_print_warn --message="Please find here an extract of the end of the log of the service $service_name:" + journalctl --no-pager --lines=$length -u $service_name >&2 + test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2 + fi + ynh_clean_check_starting + fi +} + +# Clean temporary process and file used by ynh_check_starting +# (usually used in ynh_clean_setup scripts) +# +# usage: ynh_clean_check_starting +ynh_clean_check_starting () { + if [ -n "$pid_tail" ] + then + # Stop the execution of tail. + kill -s 15 $pid_tail 2>&1 + fi + if [ -n "$templog" ] + then + ynh_secure_remove "$templog" 2>&1 + fi +} \ No newline at end of file