mirror of
https://github.com/YunoHost-Apps/matomo_ynh.git
synced 2024-09-03 19:45:56 +02:00
Testing (#24)
* Add extra_php-fpm.conf * Increase memory_limit to 256M * Add Morpheus icons
This commit is contained in:
parent
580d3ab1f5
commit
fad51b9051
12 changed files with 228 additions and 51 deletions
|
@ -20,7 +20,7 @@
|
||||||
backup_restore=1
|
backup_restore=1
|
||||||
multi_instance=1
|
multi_instance=1
|
||||||
port_already_use=0
|
port_already_use=0
|
||||||
change_url=0
|
change_url=1
|
||||||
;;; Options
|
;;; Options
|
||||||
Email=anmol@datamol.org
|
Email=anmol@datamol.org
|
||||||
Notification=yes
|
Notification=yes
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
; file automatically generated or modified by Matomo; you can manually override the default values in global.ini.php by redefining them in this file.
|
; file automatically generated or modified by Matomo; you can manually override the default values in global.ini.php by redefining them in this file.
|
||||||
[database]
|
[database]
|
||||||
host = "127.0.0.1"
|
host = "127.0.0.1"
|
||||||
username = "__DB__"
|
username = "__DB_NAME__"
|
||||||
password = "__DB_PASSWORD__"
|
password = "__DB_PASSWORD__"
|
||||||
dbname = "__DB__"
|
dbname = "__DB_NAME__"
|
||||||
tables_prefix = "matomo_"
|
tables_prefix = "matomo_"
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
MAILTO="admin"
|
MAILTO="admin"
|
||||||
5 * * * * __USER__ /usr/bin/php YNH_WWW_PATH/console core:archive --url=https://__DOMAIN__/__PATH__ > /dev/null
|
5 * * * * __APP__ /usr/bin/php__PHPVERSION__ __FINALPATH__/console core:archive --url=https://__DOMAIN____PATH__ > /dev/null
|
||||||
|
|
5
conf/extra_php-fpm.conf
Normal file
5
conf/extra_php-fpm.conf
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
; Additional php.ini defines, specific to this pool of workers.
|
||||||
|
|
||||||
|
php_admin_value[upload_max_filesize] = 100M
|
||||||
|
php_admin_value[memory_limit] = 256M
|
||||||
|
php_admin_value[post_max_size] = 50M
|
6
conf/icons.src
Normal file
6
conf/icons.src
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
SOURCE_URL=https://github.com/matomo-org/matomo-icons/archive/e96ef33bf490794829831cbb795fd4ea67259699.tar.gz
|
||||||
|
SOURCE_SUM=9a6457d8f138216f911621db7a5af5fbce7214e62d6f184730f216986e498b53
|
||||||
|
SOURCE_SUM_PRG=sha256sum
|
||||||
|
SOURCE_FORMAT=tar.gz
|
||||||
|
SOURCE_IN_SUBDIR=true
|
||||||
|
SOURCE_FILENAME=
|
|
@ -11,8 +11,8 @@ location __PATH__/ {
|
||||||
|
|
||||||
index index.php;
|
index index.php;
|
||||||
|
|
||||||
# Common parameter to increase upload size limit in conjunction with dedicated php-fpm file
|
# Common parameter to increase upload size limit in conjunction with dedicated PHP-FPM file
|
||||||
#client_max_body_size 50M;
|
client_max_body_size 100M;
|
||||||
|
|
||||||
try_files $uri $uri/ index.php;
|
try_files $uri $uri/ index.php;
|
||||||
location ~ [^/]\.php(/|$) {
|
location ~ [^/]\.php(/|$) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"en": "Open source analytics platform for measuring Web statistics",
|
"en": "Open source analytics platform for measuring Web statistics",
|
||||||
"fr": "Plateforme d'analyse open source de mesure de statistiques Web"
|
"fr": "Plateforme d'analyse open source de mesure de statistiques Web"
|
||||||
},
|
},
|
||||||
"version": "4.0.5~ynh1",
|
"version": "4.0.5~ynh2",
|
||||||
"url": "https://matomo.org",
|
"url": "https://matomo.org",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"maintainer": {
|
"maintainer": {
|
||||||
|
@ -50,6 +50,10 @@
|
||||||
"en": "Is it a public application?",
|
"en": "Is it a public application?",
|
||||||
"fr": "Est-ce une application publique ?"
|
"fr": "Est-ce une application publique ?"
|
||||||
},
|
},
|
||||||
|
"help": {
|
||||||
|
"en": "If enabled, Matomo will be accessible by people who do not have an account. This can be changed later via the webadmin.",
|
||||||
|
"fr": "Si cette case est cochée, Matomo sera accessible aux personnes n’ayant pas de compte. Vous pourrez changer ceci plus tard via la webadmin."
|
||||||
|
},
|
||||||
"default": true
|
"default": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -76,3 +76,19 @@ $(yunohost tools diagnosis | grep -B 100 "services:" | sed '/services:/d')"
|
||||||
# Send the email to the recipients
|
# Send the email to the recipients
|
||||||
echo "$mail_message" | $mail_bin -a "Content-Type: text/plain; charset=UTF-8" -s "$mail_subject" "$recipients"
|
echo "$mail_message" | $mail_bin -a "Content-Type: text/plain; charset=UTF-8" -s "$mail_subject" "$recipients"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Execute a command as another user
|
||||||
|
# usage: ynh_exec_as USER COMMAND [ARG ...]
|
||||||
|
ynh_exec_as() {
|
||||||
|
local USER=$1
|
||||||
|
shift 1
|
||||||
|
|
||||||
|
if [[ $USER = $(whoami) ]]; then
|
||||||
|
eval "$@"
|
||||||
|
else
|
||||||
|
sudo -u "$USER" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
119
scripts/change_url
Normal file
119
scripts/change_url
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# GENERIC STARTING
|
||||||
|
#=================================================
|
||||||
|
# IMPORT GENERIC HELPERS
|
||||||
|
#=================================================
|
||||||
|
|
||||||
|
source _common.sh
|
||||||
|
source /usr/share/yunohost/helpers
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# RETRIEVE ARGUMENTS
|
||||||
|
#=================================================
|
||||||
|
|
||||||
|
old_domain=$YNH_APP_OLD_DOMAIN
|
||||||
|
old_path=$YNH_APP_OLD_PATH
|
||||||
|
|
||||||
|
new_domain=$YNH_APP_NEW_DOMAIN
|
||||||
|
new_path=$YNH_APP_NEW_PATH
|
||||||
|
|
||||||
|
app=$YNH_APP_INSTANCE_NAME
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# LOAD SETTINGS
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Loading installation settings..." --weight=1
|
||||||
|
|
||||||
|
# Needed for helper "ynh_add_nginx_config"
|
||||||
|
final_path=$(ynh_app_setting_get --app=$app --key=final_path)
|
||||||
|
phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." --weight=1
|
||||||
|
|
||||||
|
# Backup the current version of the app
|
||||||
|
ynh_backup_before_upgrade
|
||||||
|
ynh_clean_setup () {
|
||||||
|
# Remove the new domain config file, the remove script won't do it as it doesn't know yet its location.
|
||||||
|
ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf"
|
||||||
|
|
||||||
|
# Restore it if the upgrade fails
|
||||||
|
ynh_restore_upgradebackup
|
||||||
|
}
|
||||||
|
# Exit if an error occurs during the execution of the script
|
||||||
|
ynh_abort_if_errors
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# CHECK WHICH PARTS SHOULD BE CHANGED
|
||||||
|
#=================================================
|
||||||
|
|
||||||
|
change_domain=0
|
||||||
|
if [ "$old_domain" != "$new_domain" ]
|
||||||
|
then
|
||||||
|
change_domain=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
change_path=0
|
||||||
|
if [ "$old_path" != "$new_path" ]
|
||||||
|
then
|
||||||
|
change_path=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# MODIFY URL IN NGINX CONF
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Updating NGINX web server configuration..." --weight=3
|
||||||
|
|
||||||
|
nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf
|
||||||
|
|
||||||
|
# Change the path in the NGINX config file
|
||||||
|
if [ $change_path -eq 1 ]
|
||||||
|
then
|
||||||
|
# Make a backup of the original NGINX config file if modified
|
||||||
|
ynh_backup_if_checksum_is_different --file="$nginx_conf_path"
|
||||||
|
# Set global variables for NGINX helper
|
||||||
|
domain="$old_domain"
|
||||||
|
path_url="$new_path"
|
||||||
|
# Create a dedicated NGINX config
|
||||||
|
ynh_add_nginx_config
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Change the domain for NGINX
|
||||||
|
if [ $change_domain -eq 1 ]
|
||||||
|
then
|
||||||
|
# Delete file checksum for the old conf file location
|
||||||
|
ynh_delete_file_checksum --file="$nginx_conf_path"
|
||||||
|
mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf
|
||||||
|
# Store file checksum for the new config file location
|
||||||
|
ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# SETUP A CRON
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Setuping a cron..."
|
||||||
|
|
||||||
|
cp ../conf/cron /etc/cron.d/$app
|
||||||
|
|
||||||
|
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="/etc/cron.d/$app"
|
||||||
|
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="/etc/cron.d/$app"
|
||||||
|
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$new_domain" --target_file="/etc/cron.d/$app"
|
||||||
|
ynh_replace_string --match_string="__PATH__" --replace_string="$new_path" --target_file="/etc/cron.d/$app"
|
||||||
|
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="/etc/cron.d/$app"
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# RELOAD NGINX
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Reloading NGINX web server..." --weight=1
|
||||||
|
|
||||||
|
ynh_systemd_action --service_name=nginx --action=reload
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# END OF SCRIPT
|
||||||
|
#=================================================
|
||||||
|
|
||||||
|
ynh_script_progression --message="Change of URL completed for $app" --last
|
|
@ -96,43 +96,26 @@ phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||||
#=================================================
|
#=================================================
|
||||||
# INSTALL COMPOSER AND DEPENDENCIES
|
# INSTALL COMPOSER AND DEPENDENCIES
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Installing composer and dependencies..."
|
ynh_script_progression --message="Installing Composer and dependencies..."
|
||||||
|
|
||||||
ynh_install_composer --phpversion="$phpversion" --workdir="$final_path"
|
ynh_install_composer --phpversion="$phpversion" --workdir="$final_path"
|
||||||
|
|
||||||
|
# Install missing icons
|
||||||
|
ynh_setup_source --dest_dir="$final_path/plugins/Morpheus/icons" --source_id="icons"
|
||||||
|
chmod -R 755 "$final_path/plugins/Morpheus"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# SETUP A CRON
|
# SETUP A CRON
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Setuping a cron..."
|
ynh_script_progression --message="Setuping a cron..."
|
||||||
|
|
||||||
ynh_replace_string --match_string="YNH_WWW_PATH" --replace_string="$final_path" --target_file="../conf/cron"
|
cp ../conf/cron /etc/cron.d/$app
|
||||||
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="../conf/cron"
|
|
||||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="../conf/cron"
|
|
||||||
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="../conf/cron"
|
|
||||||
cp -f ../conf/cron /etc/cron.d/$app
|
|
||||||
|
|
||||||
#=================================================
|
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="/etc/cron.d/$app"
|
||||||
# MODIFY A CONFIG FILE (TO DO: Automate install)
|
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="/etc/cron.d/$app"
|
||||||
#=================================================
|
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="/etc/cron.d/$app"
|
||||||
ynh_script_progression --message="Modifying a config file..."
|
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="/etc/cron.d/$app"
|
||||||
|
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="/etc/cron.d/$app"
|
||||||
### `ynh_replace_string` is used to replace a string in a file.
|
|
||||||
### (It's compatible with sed regular expressions syntax)
|
|
||||||
## cp -f ../conf/config.ini.php "$final_path/config/config.ini.php"
|
|
||||||
## ynh_replace_string "__DB__" "$db_name" "$final_path/config/config.ini.php"
|
|
||||||
## ynh_replace_string "__DB_PASSWORD__" "$db_pwd" "$final_path/config/config.ini.php"
|
|
||||||
|
|
||||||
#=================================================
|
|
||||||
# STORE THE CONFIG FILE CHECKSUM
|
|
||||||
#=================================================
|
|
||||||
ynh_script_progression --message="Storing the config file checksum..."
|
|
||||||
|
|
||||||
### `ynh_store_file_checksum` is used to store the checksum of a file.
|
|
||||||
### That way, during the upgrade script, by using `ynh_backup_if_checksum_is_different`,
|
|
||||||
### you can make a backup of this file before modifying it again if the admin had modified it.
|
|
||||||
|
|
||||||
# Calculate and store the config file checksum into the app settings
|
|
||||||
## ynh_store_file_checksum --file="$final_path/CONFIG_FILE"
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# GENERIC FINALIZATION
|
# GENERIC FINALIZATION
|
||||||
|
@ -152,8 +135,6 @@ ynh_script_progression --message="Configuring SSOwat..."
|
||||||
# Make app public if necessary or protect it
|
# Make app public if necessary or protect it
|
||||||
if [ $is_public -eq 1 ]
|
if [ $is_public -eq 1 ]
|
||||||
then
|
then
|
||||||
# Everyone can access the app.
|
|
||||||
# The "main" permission is automatically created before the install script.
|
|
||||||
ynh_permission_update --permission "main" --add "visitors"
|
ynh_permission_update --permission "main" --add "visitors"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -169,10 +150,13 @@ ynh_systemd_action --service_name=nginx --action=reload
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Sending a readme for the admin..."
|
ynh_script_progression --message="Sending a readme for the admin..."
|
||||||
|
|
||||||
message=" $app was successfully installed :)
|
message="Matomo was successfully installed :)
|
||||||
|
|
||||||
Please open your $app domain: https://$domain$path_url
|
Please open your $app domain: https://$domain$path_url
|
||||||
|
|
||||||
Complete the registration process from the setup page displayed.
|
Complete the registration process from the setup page displayed.
|
||||||
Details for mysql database to be enterted while registration process:
|
Details for MySQL database to be enterted while registration process:
|
||||||
|
|
||||||
Database login: $app
|
Database login: $app
|
||||||
Database name: $app
|
Database name: $app
|
||||||
Database password: $db_pwd
|
Database password: $db_pwd
|
||||||
|
|
|
@ -22,6 +22,7 @@ path_url=$(ynh_app_setting_get --app=$app --key=path)
|
||||||
is_public=$(ynh_app_setting_get --app=$app --key=is_public)
|
is_public=$(ynh_app_setting_get --app=$app --key=is_public)
|
||||||
final_path=$(ynh_app_setting_get --app=$app --key=final_path)
|
final_path=$(ynh_app_setting_get --app=$app --key=final_path)
|
||||||
db_name=$(ynh_app_setting_get --app=$app --key=db_name)
|
db_name=$(ynh_app_setting_get --app=$app --key=db_name)
|
||||||
|
phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# CHECK VERSION
|
# CHECK VERSION
|
||||||
|
@ -80,8 +81,32 @@ if [ "$upgrade_type" == "UPGRADE_APP" ]
|
||||||
then
|
then
|
||||||
ynh_script_progression --message="Upgrading source files..."
|
ynh_script_progression --message="Upgrading source files..."
|
||||||
|
|
||||||
|
if [[ ! -f "$final_path/config/config.ini.php" ]]; then
|
||||||
|
# config.ini.php is only created during the post-install process...
|
||||||
|
# it is therefore not present when the CI tests are carried out...
|
||||||
|
# This condition is only for CI test to go through the upgrade process
|
||||||
|
ynh_secure_remove --file="$final_path"
|
||||||
# Download, check integrity, uncompress and patch the source from app.src
|
# Download, check integrity, uncompress and patch the source from app.src
|
||||||
ynh_setup_source --dest_dir="$final_path"
|
ynh_setup_source --dest_dir="$final_path"
|
||||||
|
else
|
||||||
|
# Create a temporary directory
|
||||||
|
tmpdir="$(mktemp -d)"
|
||||||
|
|
||||||
|
# Backup the config file in the temp dir
|
||||||
|
cp -a "$final_path/config/config.ini.php" "$tmpdir/config.ini.php"
|
||||||
|
|
||||||
|
# Remove the app directory securely
|
||||||
|
ynh_secure_remove --file="$final_path"
|
||||||
|
|
||||||
|
# Download, check integrity, uncompress and patch the source from app.src
|
||||||
|
ynh_setup_source --dest_dir="$final_path"
|
||||||
|
|
||||||
|
# Copy the admin saved settings from tmp directory to final path
|
||||||
|
cp -a "$tmpdir/config.ini.php" "$final_path/config/config.ini.php"
|
||||||
|
|
||||||
|
# Remove the tmp directory securely
|
||||||
|
ynh_secure_remove --file="$tmpdir"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
|
@ -105,9 +130,8 @@ ynh_system_user_create --username=$app
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Upgrading PHP-FPM configuration..."
|
ynh_script_progression --message="Upgrading PHP-FPM configuration..."
|
||||||
|
|
||||||
# Create a dedicated php-fpm config
|
# Create a dedicated PHP-FPM config
|
||||||
ynh_add_fpm_config --usage=low --footprint=low --package="$extra_php_dependencies"
|
ynh_add_fpm_config --usage=low --footprint=low --package="$extra_php_dependencies"
|
||||||
phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# SPECIFIC UPGRADE
|
# SPECIFIC UPGRADE
|
||||||
|
@ -118,16 +142,34 @@ ynh_script_progression --message="Installating composer and dependencies..."
|
||||||
|
|
||||||
ynh_install_composer --phpversion="$phpversion" --workdir="$final_path"
|
ynh_install_composer --phpversion="$phpversion" --workdir="$final_path"
|
||||||
|
|
||||||
|
if [[ -f "$final_path/config/config.ini.php" ]]; then
|
||||||
|
pushd "$final_path"
|
||||||
|
ynh_exec_as $app ./console core:update
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# INSTALL MISSING ICONS
|
||||||
|
#=================================================
|
||||||
|
|
||||||
|
if [ ! "$(ls -A "$final_path/plugins/Morpheus/icons")" ]
|
||||||
|
then
|
||||||
|
ynh_setup_source --dest_dir="$final_path/plugins/Morpheus/icons" --source_id="icons"
|
||||||
|
chmod -R 755 "$final_path/plugins/Morpheus"
|
||||||
|
fi
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# SETUP A CRON
|
# SETUP A CRON
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Setuping a cron..."
|
ynh_script_progression --message="Setuping a cron..."
|
||||||
|
|
||||||
ynh_replace_string --match_string="YNH_WWW_PATH" --replace_string="$final_path" --target_file="../conf/cron"
|
cp ../conf/cron /etc/cron.d/$app
|
||||||
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="../conf/cron"
|
|
||||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="../conf/cron"
|
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="/etc/cron.d/$app"
|
||||||
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="../conf/cron"
|
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="/etc/cron.d/$app"
|
||||||
cp -f ../conf/cron /etc/cron.d/$app
|
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="/etc/cron.d/$app"
|
||||||
|
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="/etc/cron.d/$app"
|
||||||
|
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="/etc/cron.d/$app"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# GENERIC FINALIZATION
|
# GENERIC FINALIZATION
|
||||||
|
|
Loading…
Reference in a new issue