From d34dba4bca390250bd03f6816c11a632ca6150e3 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 1 Sep 2021 14:10:41 +0200 Subject: [PATCH 01/39] Add screenshot --- doc/DISCLAIMER.md | 12 ------------ doc/screenshots/DESCRIPTION.md | 1 + doc/screenshots/example.jpg | Bin 35451 -> 0 bytes doc/screenshots/screenshot.png | Bin 0 -> 53242 bytes manifest.json | 1 - 5 files changed, 1 insertion(+), 13 deletions(-) create mode 100644 doc/screenshots/DESCRIPTION.md delete mode 100644 doc/screenshots/example.jpg create mode 100644 doc/screenshots/screenshot.png diff --git a/doc/DISCLAIMER.md b/doc/DISCLAIMER.md index aded581..e69de29 100644 --- a/doc/DISCLAIMER.md +++ b/doc/DISCLAIMER.md @@ -1,12 +0,0 @@ -* Any known limitations, constrains or stuff not working, such as (but not limited to): - * requiring a full dedicated domain ? - * architectures not supported ? - * not-working single-sign on or LDAP integration ? - * the app requires an important amount of RAM / disk / .. to install or to work properly - * etc... - -* Other infos that people should be aware of, such as: - * any specific step to perform after installing (such as manually finishing the install, specific admin credentials, ...) - * how to configure / administrate the application if it ain't obvious - * upgrade process / specificities / things to be aware of ? - * security considerations ? diff --git a/doc/screenshots/DESCRIPTION.md b/doc/screenshots/DESCRIPTION.md new file mode 100644 index 0000000..50a4b84 --- /dev/null +++ b/doc/screenshots/DESCRIPTION.md @@ -0,0 +1 @@ +Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. diff --git a/doc/screenshots/example.jpg b/doc/screenshots/example.jpg deleted file mode 100644 index a1efa1a36d593384df59dc13db03fa83b0436d69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35451 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 UE-)&$xd9C0IsX9d#{5|Pe`qLcKmY&$ diff --git a/doc/screenshots/screenshot.png b/doc/screenshots/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..a01df2b18408dc398ff582855f2a002b8826eb69 GIT binary patch literal 53242 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 JM8@*N{{bnGpr-%; literal 0 HcmV?d00001 diff --git a/manifest.json b/manifest.json index 465c35e..e362465 100644 --- a/manifest.json +++ b/manifest.json @@ -13,7 +13,6 @@ "website": "https://libretranslate.com/", "demo": "https://libretranslate.com/", "admindoc": "https://libretranslate.com/docs/", - "userdoc": "https://yunohost.org/apps", "code": "https://github.com/LibreTranslate/LibreTranslate" }, "license": "AGPL-3.0", From 900685cc271fd5812f399c47d88282df53d97ef9 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Wed, 1 Sep 2021 12:10:47 +0000 Subject: [PATCH 02/39] Auto-update README --- README.md | 19 ++----------------- README_fr.md | 19 ++----------------- 2 files changed, 4 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 99eae95..1d12cb4 100644 --- a/README.md +++ b/README.md @@ -23,27 +23,12 @@ Open Source Machine Translation API, entirely self-hosted ## Screenshots -![](./doc/screenshots/example.jpg) - -## Disclaimers / important information - -* Any known limitations, constrains or stuff not working, such as (but not limited to): - * requiring a full dedicated domain ? - * architectures not supported ? - * not-working single-sign on or LDAP integration ? - * the app requires an important amount of RAM / disk / .. to install or to work properly - * etc... - -* Other infos that people should be aware of, such as: - * any specific step to perform after installing (such as manually finishing the install, specific admin credentials, ...) - * how to configure / administrate the application if it ain't obvious - * upgrade process / specificities / things to be aware of ? - * security considerations ? +![](./doc/screenshots/screenshot.png) +![](./doc/screenshots/DESCRIPTION.md) ## Documentation and resources * Official app website: https://libretranslate.com/ -* Official user documentation: https://yunohost.org/apps * Official admin documentation: https://libretranslate.com/docs/ * Upstream app code repository: https://github.com/LibreTranslate/LibreTranslate * YunoHost documentation for this app: https://yunohost.org/app_libretranslate diff --git a/README_fr.md b/README_fr.md index c8dbcb7..98f56ce 100644 --- a/README_fr.md +++ b/README_fr.md @@ -19,27 +19,12 @@ API de traduction automatique Open Source, entièrement auto-hébergée ## Captures d'écran -![](./doc/screenshots/example.jpg) - -## Avertissements / informations importantes - -* Any known limitations, constrains or stuff not working, such as (but not limited to): - * requiring a full dedicated domain ? - * architectures not supported ? - * not-working single-sign on or LDAP integration ? - * the app requires an important amount of RAM / disk / .. to install or to work properly - * etc... - -* Other infos that people should be aware of, such as: - * any specific step to perform after installing (such as manually finishing the install, specific admin credentials, ...) - * how to configure / administrate the application if it ain't obvious - * upgrade process / specificities / things to be aware of ? - * security considerations ? +![](./doc/screenshots/screenshot.png) +![](./doc/screenshots/DESCRIPTION.md) ## Documentations et ressources * Site officiel de l'app : https://libretranslate.com/ -* Documentation officielle utilisateur : https://yunohost.org/apps * Documentation officielle de l'admin : https://libretranslate.com/docs/ * Dépôt de code officiel de l'app : https://github.com/LibreTranslate/LibreTranslate * Documentation YunoHost pour cette app : https://yunohost.org/app_libretranslate From 461da2b8d5a30019e843abcc1edc52690b930fa0 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Thu, 2 Sep 2021 19:05:25 +0200 Subject: [PATCH 03/39] fix --- conf/nginx.conf | 3 +-- conf/systemd.service | 2 +- manifest.json | 6 ------ scripts/change_url | 4 ++-- scripts/install | 2 +- 5 files changed, 5 insertions(+), 12 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 938d989..7de9e02 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,5 +1,4 @@ -#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; -location __PATH__/ { +location / { if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; diff --git a/conf/systemd.service b/conf/systemd.service index a34b132..2d8e073 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -9,7 +9,7 @@ Group=__APP__ Restart=always Type=simple WorkingDirectory=__FINALPATH__ -ExecStart=/usr/local/bin/pipenv run python3 __FINALPATH__/.venv/bin/libretranslate --host 127.0.0.1 --port __PORT__ +ExecStart=/usr/local/bin/pipenv run python3 __FINALPATH__/.venv/bin/libretranslate --host 127.0.0.1 --port __PORT__ --load-only en,fr --frontend-language-target en [Install] WantedBy=multi-user.target diff --git a/manifest.json b/manifest.json index e362465..bf8f34b 100644 --- a/manifest.json +++ b/manifest.json @@ -34,12 +34,6 @@ "type": "domain", "example": "example.com" }, - { - "name": "path", - "type": "path", - "example": "/libretranslate", - "default": "/libretranslate" - }, { "name": "is_public", "type": "boolean", diff --git a/scripts/change_url b/scripts/change_url index f5bfd03..e47e357 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -24,7 +24,7 @@ app=$YNH_APP_INSTANCE_NAME #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --time --weight=1 +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) @@ -32,7 +32,7 @@ final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= # BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP #================================================= -ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." --time --weight=1 +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 diff --git a/scripts/install b/scripts/install index 02df7ac..142a247 100755 --- a/scripts/install +++ b/scripts/install @@ -25,7 +25,7 @@ ynh_abort_if_errors #================================================= domain=$YNH_APP_ARG_DOMAIN -path_url=$YNH_APP_ARG_PATH +path_url="/" is_public=$YNH_APP_ARG_IS_PUBLIC app=$YNH_APP_INSTANCE_NAME From a3b9020cc58c4b8b02ef878c072835492368ceba Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Thu, 2 Sep 2021 19:06:50 +0200 Subject: [PATCH 04/39] fix --- conf/nginx.conf | 2 +- conf/systemd.service | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 938d989..7a5c477 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -5,7 +5,7 @@ location __PATH__/ { rewrite ^ https://$server_name$request_uri? permanent; } - proxy_pass http://127.0.0.1:__PORT__/; + proxy_pass http://127.0.0.1:__PORT__; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; diff --git a/conf/systemd.service b/conf/systemd.service index a34b132..2d8e073 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -9,7 +9,7 @@ Group=__APP__ Restart=always Type=simple WorkingDirectory=__FINALPATH__ -ExecStart=/usr/local/bin/pipenv run python3 __FINALPATH__/.venv/bin/libretranslate --host 127.0.0.1 --port __PORT__ +ExecStart=/usr/local/bin/pipenv run python3 __FINALPATH__/.venv/bin/libretranslate --host 127.0.0.1 --port __PORT__ --load-only en,fr --frontend-language-target en [Install] WantedBy=multi-user.target From 3122cccdf7169f3ea601cce67360b145901c5cf5 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Thu, 2 Sep 2021 21:03:26 +0200 Subject: [PATCH 05/39] add description --- doc/{screenshots => }/DESCRIPTION.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/{screenshots => }/DESCRIPTION.md (100%) diff --git a/doc/screenshots/DESCRIPTION.md b/doc/DESCRIPTION.md similarity index 100% rename from doc/screenshots/DESCRIPTION.md rename to doc/DESCRIPTION.md From 772cee8750c64966c1ebc043dde09ca3334381d6 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Thu, 2 Sep 2021 19:03:32 +0000 Subject: [PATCH 06/39] Auto-update README --- README.md | 4 ++-- README_fr.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1d12cb4..8e40e63 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in ## Overview -Open Source Machine Translation API, entirely self-hosted +Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. + **Shipped version:** 1.2.3~ynh1 @@ -24,7 +25,6 @@ Open Source Machine Translation API, entirely self-hosted ## Screenshots ![](./doc/screenshots/screenshot.png) -![](./doc/screenshots/DESCRIPTION.md) ## Documentation and resources diff --git a/README_fr.md b/README_fr.md index 98f56ce..c635cfb 100644 --- a/README_fr.md +++ b/README_fr.md @@ -11,7 +11,8 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour ## Vue d'ensemble -API de traduction automatique Open Source, entièrement auto-hébergée +Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. + **Version incluse :** 1.2.3~ynh1 @@ -20,7 +21,6 @@ API de traduction automatique Open Source, entièrement auto-hébergée ## Captures d'écran ![](./doc/screenshots/screenshot.png) -![](./doc/screenshots/DESCRIPTION.md) ## Documentations et ressources From c1b1feef8917379e5baebcf8c28857740c7c3d19 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Thu, 2 Sep 2021 21:08:08 +0200 Subject: [PATCH 07/39] Create DESCRIPTION.md --- doc/screenshots/DESCRIPTION.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/screenshots/DESCRIPTION.md diff --git a/doc/screenshots/DESCRIPTION.md b/doc/screenshots/DESCRIPTION.md new file mode 100644 index 0000000..50a4b84 --- /dev/null +++ b/doc/screenshots/DESCRIPTION.md @@ -0,0 +1 @@ +Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. From 5cf0871c9f27c1e1651a1a8a592c83fcda8a5bd8 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Thu, 2 Sep 2021 19:08:26 +0000 Subject: [PATCH 08/39] Auto-update README --- README.md | 1 + README_fr.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 8e40e63..1c64ef6 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Free and Open Source Machine Translation API, entirely self-hosted. Unlike other ## Screenshots ![](./doc/screenshots/screenshot.png) +![](./doc/screenshots/DESCRIPTION.md) ## Documentation and resources diff --git a/README_fr.md b/README_fr.md index c635cfb..d2be25a 100644 --- a/README_fr.md +++ b/README_fr.md @@ -21,6 +21,7 @@ Free and Open Source Machine Translation API, entirely self-hosted. Unlike other ## Captures d'écran ![](./doc/screenshots/screenshot.png) +![](./doc/screenshots/DESCRIPTION.md) ## Documentations et ressources From afb0f8ea5d734cc28bf7a7c9791614ca2c65c4c7 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 3 Nov 2021 23:06:39 +0100 Subject: [PATCH 09/39] Fix --- manifest.json | 3 +-- scripts/restore | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/manifest.json b/manifest.json index bf8f34b..190b96d 100644 --- a/manifest.json +++ b/manifest.json @@ -31,8 +31,7 @@ "install" : [ { "name": "domain", - "type": "domain", - "example": "example.com" + "type": "domain" }, { "name": "is_public", diff --git a/scripts/restore b/scripts/restore index 14a4b3f..b18fcf8 100755 --- a/scripts/restore +++ b/scripts/restore @@ -24,7 +24,7 @@ ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --time --weight=1 +ynh_script_progression --message="Loading installation settings..." --weight=1 app=$YNH_APP_INSTANCE_NAME @@ -35,10 +35,8 @@ final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= # CHECK IF THE APP CAN BE RESTORED #================================================= -ynh_script_progression --message="Validating restoration parameters..." --time --weight=1 +ynh_script_progression --message="Validating restoration parameters..." --weight=1 -ynh_webpath_available --domain=$domain --path_url=$path_url \ - || ynh_die --message="Path not available: ${domain}${path_url}" test ! -d $final_path \ || ynh_die --message="There is already a directory: $final_path " @@ -47,14 +45,14 @@ test ! -d $final_path \ #================================================= # RESTORE THE NGINX CONFIGURATION #================================================= -ynh_script_progression --message="Restoring the NGINX configuration..." --time --weight=1 +ynh_script_progression --message="Restoring the NGINX configuration..." --weight=1 ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" #================================================= # RECREATE THE DEDICATED USER #================================================= -ynh_script_progression --message="Recreating the dedicated system user..." --time --weight=1 +ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 # Create the dedicated user (if not existing) ynh_system_user_create --username=$app --home_dir="$final_path" @@ -62,7 +60,7 @@ ynh_system_user_create --username=$app --home_dir="$final_path" #================================================= # RESTORE THE APP MAIN DIR #================================================= -ynh_script_progression --message="Restoring the app main directory..." --time --weight=1 +ynh_script_progression --message="Restoring the app main directory..." --weight=1 ynh_restore_file --origin_path="$final_path" @@ -75,7 +73,7 @@ chown -R $app:www-data "$final_path" #================================================= # REINSTALL DEPENDENCIES #================================================= -ynh_script_progression --message="Reinstalling dependencies..." --time --weight=1 +ynh_script_progression --message="Reinstalling dependencies..." --weight=1 # Define and install dependencies ynh_install_app_dependencies $pkg_dependencies @@ -83,7 +81,7 @@ ynh_install_app_dependencies $pkg_dependencies #================================================= # RESTORE SYSTEMD #================================================= -ynh_script_progression --message="Restoring the systemd configuration..." --time --weight=1 +ynh_script_progression --message="Restoring the systemd configuration..." --weight=1 ynh_restore_file --origin_path="/etc/systemd/system/$app.service" systemctl enable $app.service --quiet @@ -91,21 +89,21 @@ systemctl enable $app.service --quiet #================================================= # INTEGRATE SERVICE IN YUNOHOST #================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --time --weight=1 +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" #================================================= # START SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Starting a systemd service..." --time --weight=1 +ynh_script_progression --message="Starting a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" #================================================= # RESTORE THE LOGROTATE CONFIGURATION #================================================= -ynh_script_progression --message="Restoring the logrotate configuration..." --time --weight=1 +ynh_script_progression --message="Restoring the logrotate configuration..." --weight=1 ynh_restore_file --origin_path="/etc/logrotate.d/$app" @@ -114,7 +112,7 @@ ynh_restore_file --origin_path="/etc/logrotate.d/$app" #================================================= # RELOAD NGINX AND PHP-FPM #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --time --weight=1 +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 ynh_systemd_action --service_name=nginx --action=reload @@ -122,4 +120,4 @@ ynh_systemd_action --service_name=nginx --action=reload # END OF SCRIPT #================================================= -ynh_script_progression --message="Restoration completed for $app" --time --last +ynh_script_progression --message="Restoration completed for $app" --last From cb902ed1925365204276f51922594510002776b5 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Thu, 9 Dec 2021 16:13:43 +0100 Subject: [PATCH 10/39] 1.2.5 --- conf/app.src | 5 ++--- conf/nginx.conf | 4 ---- manifest.json | 4 ++-- scripts/_common.sh | 2 +- scripts/restore | 3 +-- 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/conf/app.src b/conf/app.src index 7a4f3e2..1042b70 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,7 +1,6 @@ -SOURCE_URL=https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.2.3.tar.gz -SOURCE_SUM=2dcebaf97cb35fc5bb8c998d477ab0c7f9d5aabc96fd30dbf587bb10311be099 +SOURCE_URL=https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.2.5.tar.gz +SOURCE_SUM=22b6880ef5dca0c98e9ce72d52ff8f1a70071080cfbcb3898d28b789f16f4a3e SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=tar.gz SOURCE_IN_SUBDIR=true -SOURCE_FILENAME= SOURCE_EXTRACT=true diff --git a/conf/nginx.conf b/conf/nginx.conf index 731626d..e47f93a 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,9 +1,5 @@ location / { - if ($scheme = http) { - rewrite ^ https://$server_name$request_uri? permanent; - } - proxy_pass http://127.0.0.1:__PORT__; proxy_redirect off; proxy_set_header Host $host; diff --git a/manifest.json b/manifest.json index 190b96d..9d37218 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Open Source Machine Translation API, entirely self-hosted", "fr": "API de traduction automatique Open Source, entièrement auto-hébergée" }, - "version": "1.2.3~ynh1", + "version": "1.2.5~ynh1", "url": "https://libretranslate.com/", "upstream": { "license": "AGPL-3.0", @@ -21,7 +21,7 @@ "email": "john.doe@example.com" }, "requirements": { - "yunohost": ">= 4.2.4" + "yunohost": ">= 4.3.0" }, "multi_instance": true, "services": [ diff --git a/scripts/_common.sh b/scripts/_common.sh index dea49e9..a30e07f 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -7,7 +7,7 @@ # dependencies used by the app pkg_dependencies="libicu-dev python3-venv python3-icu pkg-config python3 python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools" -libretranslate_version="1.2.3" +libretranslate_version="1.2.5" #================================================= # PERSONAL HELPERS diff --git a/scripts/restore b/scripts/restore index b18fcf8..d64e57c 100755 --- a/scripts/restore +++ b/scripts/restore @@ -37,8 +37,7 @@ final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= ynh_script_progression --message="Validating restoration parameters..." --weight=1 -test ! -d $final_path \ - || ynh_die --message="There is already a directory: $final_path " +test ! -d $final_path || ynh_die --message="There is already a directory: $final_path " #================================================= # STANDARD RESTORATION STEPS From 890f946adf27831d8a8f97e8790a320976228103 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Thu, 9 Dec 2021 15:13:51 +0000 Subject: [PATCH 11/39] Auto-update README --- README.md | 2 +- README_fr.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1c64ef6..5484f85 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. -**Shipped version:** 1.2.3~ynh1 +**Shipped version:** 1.2.5~ynh1 **Demo:** https://libretranslate.com/ diff --git a/README_fr.md b/README_fr.md index d2be25a..c1cf668 100644 --- a/README_fr.md +++ b/README_fr.md @@ -14,7 +14,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. -**Version incluse :** 1.2.3~ynh1 +**Version incluse :** 1.2.5~ynh1 **Démo :** https://libretranslate.com/ From 965739ac01419cde49aefe182362cdd74c14d7ab Mon Sep 17 00:00:00 2001 From: Tagadda <36127788+Tagadda@users.noreply.github.com> Date: Fri, 18 Mar 2022 12:37:33 +0000 Subject: [PATCH 12/39] Implement auto-updater --- .github/workflows/updater.sh | 104 ++++++++++++++++++++++++++++++++++ .github/workflows/updater.yml | 49 ++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 .github/workflows/updater.sh create mode 100644 .github/workflows/updater.yml diff --git a/.github/workflows/updater.sh b/.github/workflows/updater.sh new file mode 100644 index 0000000..2c57665 --- /dev/null +++ b/.github/workflows/updater.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +#================================================= +# PACKAGE UPDATING HELPER +#================================================= + +# This script is meant to be run by GitHub Actions +# The YunoHost-Apps organisation offers a template Action to run this script periodically +# Since each app is different, maintainers can adapt its contents so as to perform +# automatic actions when a new upstream release is detected. + +#================================================= +# FETCHING LATEST RELEASE AND ITS ASSETS +#================================================= + +# Fetching information +current_version=$(cat manifest.json | jq -j '.version|split("~")[0]') +repo=$(cat manifest.json | jq -j '.upstream.code|split("https://github.com/")[1]') +# Some jq magic is needed, because the latest upstream release is not always the latest version (e.g. security patches for older versions) +version=$(curl --silent "https://api.github.com/repos/$repo/releases" | jq -r '.[] | select( .prerelease != true ) | .tag_name' | sort -V | tail -1) +assets="https://github.com/$repo/archive/refs/tags/$version.tar.gz" + +# Later down the script, we assume the version has only digits and dots +# Sometimes the release name starts with a "v", so let's filter it out. +# You may need more tweaks here if the upstream repository has different naming conventions. +if [[ ${version:0:1} == "v" || ${version:0:1} == "V" ]]; then + version=${version:1} +fi + +# Setting up the environment variables +echo "Current version: $current_version" +echo "Latest release from upstream: $version" +echo "VERSION=$version" >> $GITHUB_ENV +# For the time being, let's assume the script will fail +echo "PROCEED=false" >> $GITHUB_ENV + +# Proceed only if the retrieved version is greater than the current one +if ! dpkg --compare-versions "$current_version" "lt" "$version" ; then + echo "::warning ::No new version available" + exit 0 +# Proceed only if a PR for this new version does not already exist +elif git ls-remote -q --exit-code --heads https://github.com/$GITHUB_REPOSITORY.git ci-auto-update-v$version ; then + echo "::warning ::A branch already exists for this update" + exit 0 +fi + +#================================================= +# UPDATE SOURCE FILES +#================================================= + +# Let's download source tarball +asset_url=$assets +echo "Handling asset at $asset_url" +src="app" + +# Create the temporary directory +tempdir="$(mktemp -d)" + +# Download sources and calculate checksum +filename=${asset_url##*/} +curl --silent -4 -L $asset_url -o "$tempdir/$filename" +checksum=$(sha256sum "$tempdir/$filename" | head -c 64) + +# Delete temporary directory +rm -rf $tempdir + +# Get extension +if [[ $filename == *.tar.gz ]]; then + extension=tar.gz +else + extension=${filename##*.} +fi + +# Rewrite source file +cat < conf/$src.src +SOURCE_URL=$asset_url +SOURCE_SUM=$checksum +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=$extension +SOURCE_IN_SUBDIR=true +SOURCE_FILENAME= +EOT +echo "... conf/$src.src updated" + +# +#================================================= +# SPECIFIC UPDATE STEPS +#================================================= + +# Any action on the app's source code can be done. +# The GitHub Action workflow takes care of committing all changes after this script ends. + +#================================================= +# GENERIC FINALIZATION +#================================================= + +# Replace new version in manifest +echo "$(jq -s --indent 4 ".[] | .version = \"$version~ynh1\"" manifest.json)" > manifest.json + +# No need to update the README, yunohost-bot takes care of it + +# The Action will proceed only if the PROCEED environment variable is set to true +echo "PROCEED=true" >> $GITHUB_ENV +exit 0 diff --git a/.github/workflows/updater.yml b/.github/workflows/updater.yml new file mode 100644 index 0000000..fb72ba0 --- /dev/null +++ b/.github/workflows/updater.yml @@ -0,0 +1,49 @@ +# This workflow allows GitHub Actions to automagically update your app whenever a new upstream release is detected. +# You need to enable Actions in your repository settings, and fetch this Action from the YunoHost-Apps organization. +# This file should be enough by itself, but feel free to tune it to your needs. +# It calls updater.sh, which is where you should put the app-specific update steps. +name: Check for new upstream releases +on: + # Allow to manually trigger the workflow + workflow_dispatch: + # Run it every day at 6:00 UTC + schedule: + - cron: '0 6 * * *' +jobs: + updater: + runs-on: ubuntu-latest + steps: + - name: Fetch the source code + uses: actions/checkout@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run the updater script + id: run_updater + run: | + # Setting up Git user + git config --global user.name 'yunohost-bot' + git config --global user.email 'yunohost-bot@users.noreply.github.com' + # Run the updater script + /bin/bash .github/workflows/updater.sh + - name: Commit changes + id: commit + if: ${{ env.PROCEED == 'true' }} + run: | + git commit -am "Upgrade to v$VERSION" + - name: Create Pull Request + id: cpr + if: ${{ env.PROCEED == 'true' }} + uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Update to version ${{ env.VERSION }} + committer: 'yunohost-bot ' + author: 'yunohost-bot ' + signoff: false + base: testing + branch: ci-auto-update-v${{ env.VERSION }} + delete-branch: true + title: 'Upgrade to version ${{ env.VERSION }}' + body: | + Upgrade to v${{ env.VERSION }} + draft: false From f70340c9c746a17f71ac284f3e0ee0828e8cb1f3 Mon Sep 17 00:00:00 2001 From: Tagadda <36127788+Tagadda@users.noreply.github.com> Date: Fri, 18 Mar 2022 12:37:44 +0000 Subject: [PATCH 13/39] Bump 1.2.7~ynh1 --- conf/app.src | 6 +++--- manifest.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/conf/app.src b/conf/app.src index 1042b70..e3f9fc8 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,6 +1,6 @@ -SOURCE_URL=https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.2.5.tar.gz -SOURCE_SUM=22b6880ef5dca0c98e9ce72d52ff8f1a70071080cfbcb3898d28b789f16f4a3e +SOURCE_URL=https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.2.7.tar.gz +SOURCE_SUM=aa0d9696d4b1f49c649f4ce69aad3a129bf743add3486571b28866c65376edb5 SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=tar.gz SOURCE_IN_SUBDIR=true -SOURCE_EXTRACT=true +SOURCE_FILENAME= diff --git a/manifest.json b/manifest.json index 9d37218..4d66b3e 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Open Source Machine Translation API, entirely self-hosted", "fr": "API de traduction automatique Open Source, entièrement auto-hébergée" }, - "version": "1.2.5~ynh1", + "version": "1.2.7~ynh1", "url": "https://libretranslate.com/", "upstream": { "license": "AGPL-3.0", @@ -28,7 +28,7 @@ "nginx" ], "arguments": { - "install" : [ + "install": [ { "name": "domain", "type": "domain" From 9548e3adbbf5103ea87d6bc33ef001ea551d5ec6 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 18 Mar 2022 22:40:30 +0100 Subject: [PATCH 14/39] add port variable --- scripts/change_url | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/change_url b/scripts/change_url index e47e357..730a148 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -28,6 +28,7 @@ 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) +port=$(ynh_app_setting_get --app=$app --key=port) #================================================= # BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP From 672efafb198b0e6eddf1e56c14c31d3db2e6b3ec Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 18 Mar 2022 22:41:52 +0100 Subject: [PATCH 15/39] remove admin permission --- scripts/install | 1 - scripts/upgrade | 5 ----- 2 files changed, 6 deletions(-) diff --git a/scripts/install b/scripts/install index 142a247..836545d 100755 --- a/scripts/install +++ b/scripts/install @@ -148,7 +148,6 @@ ynh_script_progression --message="Configuring permissions..." --weight=1 # Make app public if necessary if [ $is_public -eq 1 ] then - ynh_permission_update --permission="main" --add="visitors" fi diff --git a/scripts/upgrade b/scripts/upgrade index d167499..ea2ffd9 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -64,11 +64,6 @@ if ynh_legacy_permissions_exists; then ynh_app_setting_delete --app=$app --key=is_public fi -if ! ynh_permission_exists --permission="admin"; then - # Create the required permissions - ynh_permission_create --permission="admin" --url="/admin" --allowed=$admin -fi - # Create a permission if needed if ! ynh_permission_exists --permission="api"; then ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --show_tile="false" --protected="true" From ac61b059f4410d14f954b403a484b27281c03afb Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 18 Mar 2022 22:42:49 +0100 Subject: [PATCH 16/39] remove multi_instance --- check_process | 3 +-- manifest.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/check_process b/check_process index fc00632..4b16641 100644 --- a/check_process +++ b/check_process @@ -3,7 +3,6 @@ domain="domain.tld" path="/path" is_public=1 - port="666" ; Checks pkg_linter=1 setup_sub_dir=1 @@ -14,7 +13,7 @@ upgrade=1 #upgrade=1 from_commit=CommitHash backup_restore=1 - multi_instance=1 + multi_instance=0 change_url=1 ;;; Options Email= diff --git a/manifest.json b/manifest.json index 4d66b3e..f9b0f6c 100644 --- a/manifest.json +++ b/manifest.json @@ -23,7 +23,7 @@ "requirements": { "yunohost": ">= 4.3.0" }, - "multi_instance": true, + "multi_instance": false, "services": [ "nginx" ], From 7b4409f19dd55aef97a9bddce234c428706b9aa7 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Fri, 18 Mar 2022 22:44:10 +0100 Subject: [PATCH 17/39] Update check_process --- check_process | 1 - 1 file changed, 1 deletion(-) diff --git a/check_process b/check_process index 4b16641..e335371 100644 --- a/check_process +++ b/check_process @@ -21,4 +21,3 @@ Notification=none ;;; Upgrade options ; commit=CommitHash name=Name and date of the commit. - manifest_arg=domain=DOMAIN&path=PATH&admin=USER&language=fr&is_public=1&password=pass&port=666& From 2f31c399237eeb2a5e3f3551adea35b370cb0901 Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Fri, 18 Mar 2022 21:45:14 +0000 Subject: [PATCH 18/39] Auto-update README --- README.md | 2 +- README_fr.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5484f85..98b3784 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. -**Shipped version:** 1.2.5~ynh1 +**Shipped version:** 1.2.7~ynh1 **Demo:** https://libretranslate.com/ diff --git a/README_fr.md b/README_fr.md index c1cf668..858e7d4 100644 --- a/README_fr.md +++ b/README_fr.md @@ -14,7 +14,7 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. -**Version incluse :** 1.2.5~ynh1 +**Version incluse :** 1.2.7~ynh1 **Démo :** https://libretranslate.com/ From d80ad014e888e2d5fa2b8b405aabead86f3dd5a0 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 19 Mar 2022 11:51:14 +0100 Subject: [PATCH 19/39] Update check_process --- check_process | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/check_process b/check_process index e335371..05d8ab4 100644 --- a/check_process +++ b/check_process @@ -5,7 +5,7 @@ is_public=1 ; Checks pkg_linter=1 - setup_sub_dir=1 + setup_sub_dir=0 setup_root=1 setup_nourl=0 setup_private=1 From 66ea0d8fd342daea19e4a5db6e6e8dd84adebd3c Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 19 Mar 2022 11:52:03 +0100 Subject: [PATCH 20/39] Update upgrade --- scripts/upgrade | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/upgrade b/scripts/upgrade index ea2ffd9..505fbea 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -19,6 +19,7 @@ app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) path_url=$(ynh_app_setting_get --app=$app --key=path) final_path=$(ynh_app_setting_get --app=$app --key=final_path) +port=$(ynh_app_setting_get --app=$app --key=port) #================================================= # CHECK VERSION From 93e30bdac4cbd6f73b0f1f9339618ae8c9281d7c Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Sun, 10 Apr 2022 20:39:06 +0200 Subject: [PATCH 21/39] 1.2.7 --- scripts/_common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/_common.sh b/scripts/_common.sh index a30e07f..6cf7301 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -7,7 +7,7 @@ # dependencies used by the app pkg_dependencies="libicu-dev python3-venv python3-icu pkg-config python3 python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools" -libretranslate_version="1.2.5" +libretranslate_version="1.2.7" #================================================= # PERSONAL HELPERS From bbd88018c44d387edf0ecd0ee4296d225b69723c Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 6 Nov 2022 08:50:27 +0100 Subject: [PATCH 22/39] 1.3.0 --- conf/app.src | 4 ++-- manifest.json | 4 ++-- scripts/_common.sh | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/conf/app.src b/conf/app.src index e3f9fc8..a7fab59 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.2.7.tar.gz -SOURCE_SUM=aa0d9696d4b1f49c649f4ce69aad3a129bf743add3486571b28866c65376edb5 +SOURCE_URL=https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.3.0.tar.gz +SOURCE_SUM=6f73d4d7d2e3b5a9bb0bb06877708d5b9101e7928fa15d82744ce0eca6af9773 SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=tar.gz SOURCE_IN_SUBDIR=true diff --git a/manifest.json b/manifest.json index f9b0f6c..75c2d0f 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Open Source Machine Translation API, entirely self-hosted", "fr": "API de traduction automatique Open Source, entièrement auto-hébergée" }, - "version": "1.2.7~ynh1", + "version": "1.3.0~ynh1", "url": "https://libretranslate.com/", "upstream": { "license": "AGPL-3.0", @@ -21,7 +21,7 @@ "email": "john.doe@example.com" }, "requirements": { - "yunohost": ">= 4.3.0" + "yunohost": ">= 11.0.9" }, "multi_instance": false, "services": [ diff --git a/scripts/_common.sh b/scripts/_common.sh index 6cf7301..2ee333b 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -7,7 +7,7 @@ # dependencies used by the app pkg_dependencies="libicu-dev python3-venv python3-icu pkg-config python3 python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools" -libretranslate_version="1.2.7" +libretranslate_version="1.3.0" #================================================= # PERSONAL HELPERS From 0a5d68c85c9324dc582c3bff80eed61aeaf6037b Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Sun, 6 Nov 2022 07:50:32 +0000 Subject: [PATCH 23/39] Auto-update README --- README.md | 23 ++++++++++++----------- README_fr.md | 29 +++++++++++++++++------------ 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 98b3784..aa18632 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ It shall NOT be edited by hand. # LibreTranslate for YunoHost -[![Integration level](https://dash.yunohost.org/integration/libretranslate.svg)](https://dash.yunohost.org/appci/app/libretranslate) ![](https://ci-apps.yunohost.org/ci/badges/libretranslate.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/libretranslate.maintain.svg) +[![Integration level](https://dash.yunohost.org/integration/libretranslate.svg)](https://dash.yunohost.org/appci/app/libretranslate) ![Working status](https://ci-apps.yunohost.org/ci/badges/libretranslate.status.svg) ![Maintenance status](https://ci-apps.yunohost.org/ci/badges/libretranslate.maintain.svg) [![Install LibreTranslate with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=libretranslate) *[Lire ce readme en français.](./README_fr.md)* @@ -18,32 +18,33 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. -**Shipped version:** 1.2.7~ynh1 +**Shipped version:** 1.3.0~ynh1 **Demo:** https://libretranslate.com/ ## Screenshots -![](./doc/screenshots/screenshot.png) -![](./doc/screenshots/DESCRIPTION.md) +![Screenshot of LibreTranslate](./doc/screenshots/screenshot.png) +![Screenshot of LibreTranslate](./doc/screenshots/DESCRIPTION.md) ## Documentation and resources -* Official app website: https://libretranslate.com/ -* Official admin documentation: https://libretranslate.com/docs/ -* Upstream app code repository: https://github.com/LibreTranslate/LibreTranslate -* YunoHost documentation for this app: https://yunohost.org/app_libretranslate -* Report a bug: https://github.com/YunoHost-Apps/libretranslate_ynh/issues +* Official app website: +* Official admin documentation: +* Upstream app code repository: +* YunoHost documentation for this app: +* Report a bug: ## Developer info Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/libretranslate_ynh/tree/testing). To try the testing branch, please proceed like that. -``` + +``` bash sudo yunohost app install https://github.com/YunoHost-Apps/libretranslate_ynh/tree/testing --debug or sudo yunohost app upgrade libretranslate -u https://github.com/YunoHost-Apps/libretranslate_ynh/tree/testing --debug ``` -**More info regarding app packaging:** https://yunohost.org/packaging_apps \ No newline at end of file +**More info regarding app packaging:** diff --git a/README_fr.md b/README_fr.md index 858e7d4..8208702 100644 --- a/README_fr.md +++ b/README_fr.md @@ -1,10 +1,14 @@ + + # LibreTranslate pour YunoHost -[![Niveau d'intégration](https://dash.yunohost.org/integration/libretranslate.svg)](https://dash.yunohost.org/appci/app/libretranslate) ![](https://ci-apps.yunohost.org/ci/badges/libretranslate.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/libretranslate.maintain.svg) +[![Niveau d'intégration](https://dash.yunohost.org/integration/libretranslate.svg)](https://dash.yunohost.org/appci/app/libretranslate) ![Statut du fonctionnement](https://ci-apps.yunohost.org/ci/badges/libretranslate.status.svg) ![Statut de maintenance](https://ci-apps.yunohost.org/ci/badges/libretranslate.maintain.svg) [![Installer LibreTranslate avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=libretranslate) *[Read this readme in english.](./README.md)* -*[Lire ce readme en français.](./README_fr.md)* > *Ce package vous permet d'installer LibreTranslate rapidement et simplement sur un serveur YunoHost. Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l'installer et en profiter.* @@ -14,32 +18,33 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. -**Version incluse :** 1.2.7~ynh1 +**Version incluse :** 1.3.0~ynh1 **Démo :** https://libretranslate.com/ ## Captures d'écran -![](./doc/screenshots/screenshot.png) -![](./doc/screenshots/DESCRIPTION.md) +![Capture d'écran de LibreTranslate](./doc/screenshots/screenshot.png) +![Capture d'écran de LibreTranslate](./doc/screenshots/DESCRIPTION.md) ## Documentations et ressources -* Site officiel de l'app : https://libretranslate.com/ -* Documentation officielle de l'admin : https://libretranslate.com/docs/ -* Dépôt de code officiel de l'app : https://github.com/LibreTranslate/LibreTranslate -* Documentation YunoHost pour cette app : https://yunohost.org/app_libretranslate -* Signaler un bug : https://github.com/YunoHost-Apps/libretranslate_ynh/issues +* Site officiel de l'app : +* Documentation officielle de l'admin : +* Dépôt de code officiel de l'app : +* Documentation YunoHost pour cette app : +* Signaler un bug : ## Informations pour les développeurs Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/libretranslate_ynh/tree/testing). Pour essayer la branche testing, procédez comme suit. -``` + +``` bash sudo yunohost app install https://github.com/YunoHost-Apps/libretranslate_ynh/tree/testing --debug ou sudo yunohost app upgrade libretranslate -u https://github.com/YunoHost-Apps/libretranslate_ynh/tree/testing --debug ``` -**Plus d'infos sur le packaging d'applications :** https://yunohost.org/packaging_apps \ No newline at end of file +**Plus d'infos sur le packaging d'applications :** From 029d2210dd64fafd826606379a647b41732dee9f Mon Sep 17 00:00:00 2001 From: tituspijean Date: Fri, 24 Feb 2023 00:33:23 +0100 Subject: [PATCH 24/39] [autopatch] Upgrade auto-updater --- .github/workflows/updater.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/updater.yml b/.github/workflows/updater.yml index fb72ba0..a56d7cb 100644 --- a/.github/workflows/updater.yml +++ b/.github/workflows/updater.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Fetch the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Run the updater script @@ -33,7 +33,7 @@ jobs: - name: Create Pull Request id: cpr if: ${{ env.PROCEED == 'true' }} - uses: peter-evans/create-pull-request@v3 + uses: peter-evans/create-pull-request@v4 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: Update to version ${{ env.VERSION }} From da4abf6596729c2589a8f9e0d6bdde68fe1a7b53 Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Thu, 23 Feb 2023 23:33:24 +0000 Subject: [PATCH 25/39] Auto-update README --- README.md | 3 ++- README_fr.md | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index aa18632..a1a24cd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ It shall NOT be edited by hand. # LibreTranslate for YunoHost -[![Integration level](https://dash.yunohost.org/integration/libretranslate.svg)](https://dash.yunohost.org/appci/app/libretranslate) ![Working status](https://ci-apps.yunohost.org/ci/badges/libretranslate.status.svg) ![Maintenance status](https://ci-apps.yunohost.org/ci/badges/libretranslate.maintain.svg) +[![Integration level](https://dash.yunohost.org/integration/libretranslate.svg)](https://dash.yunohost.org/appci/app/libretranslate) ![Working status](https://ci-apps.yunohost.org/ci/badges/libretranslate.status.svg) ![Maintenance status](https://ci-apps.yunohost.org/ci/badges/libretranslate.maintain.svg) + [![Install LibreTranslate with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=libretranslate) *[Lire ce readme en français.](./README_fr.md)* diff --git a/README_fr.md b/README_fr.md index 8208702..6a9f364 100644 --- a/README_fr.md +++ b/README_fr.md @@ -5,15 +5,16 @@ It shall NOT be edited by hand. # LibreTranslate pour YunoHost -[![Niveau d'intégration](https://dash.yunohost.org/integration/libretranslate.svg)](https://dash.yunohost.org/appci/app/libretranslate) ![Statut du fonctionnement](https://ci-apps.yunohost.org/ci/badges/libretranslate.status.svg) ![Statut de maintenance](https://ci-apps.yunohost.org/ci/badges/libretranslate.maintain.svg) +[![Niveau d’intégration](https://dash.yunohost.org/integration/libretranslate.svg)](https://dash.yunohost.org/appci/app/libretranslate) ![Statut du fonctionnement](https://ci-apps.yunohost.org/ci/badges/libretranslate.status.svg) ![Statut de maintenance](https://ci-apps.yunohost.org/ci/badges/libretranslate.maintain.svg) + [![Installer LibreTranslate avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=libretranslate) *[Read this readme in english.](./README.md)* -> *Ce package vous permet d'installer LibreTranslate rapidement et simplement sur un serveur YunoHost. -Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l'installer et en profiter.* +> *Ce package vous permet d’installer LibreTranslate rapidement et simplement sur un serveur YunoHost. +Si vous n’avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l’installer et en profiter.* -## Vue d'ensemble +## Vue d’ensemble Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. @@ -22,16 +23,16 @@ Free and Open Source Machine Translation API, entirely self-hosted. Unlike other **Démo :** https://libretranslate.com/ -## Captures d'écran +## Captures d’écran -![Capture d'écran de LibreTranslate](./doc/screenshots/screenshot.png) -![Capture d'écran de LibreTranslate](./doc/screenshots/DESCRIPTION.md) +![Capture d’écran de LibreTranslate](./doc/screenshots/screenshot.png) +![Capture d’écran de LibreTranslate](./doc/screenshots/DESCRIPTION.md) ## Documentations et ressources -* Site officiel de l'app : -* Documentation officielle de l'admin : -* Dépôt de code officiel de l'app : +* Site officiel de l’app : +* Documentation officielle de l’admin : +* Dépôt de code officiel de l’app : * Documentation YunoHost pour cette app : * Signaler un bug : @@ -47,4 +48,4 @@ ou sudo yunohost app upgrade libretranslate -u https://github.com/YunoHost-Apps/libretranslate_ynh/tree/testing --debug ``` -**Plus d'infos sur le packaging d'applications :** +**Plus d’infos sur le packaging d’applications :** \ No newline at end of file From b7cc2ec1285314f72d440325405d775b1da2c30b Mon Sep 17 00:00:00 2001 From: Thomas <51749973+Thovi98@users.noreply.github.com> Date: Sun, 2 Apr 2023 00:24:48 +0200 Subject: [PATCH 26/39] initial v2 --- tests.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests.toml diff --git a/tests.toml b/tests.toml new file mode 100644 index 0000000..eb73b8d --- /dev/null +++ b/tests.toml @@ -0,0 +1,3 @@ +test_format = 1.0 + +[default] \ No newline at end of file From 24efc96570f0c5c7cf271d264fb5640516fb70a7 Mon Sep 17 00:00:00 2001 From: Thomas <51749973+Thovi98@users.noreply.github.com> Date: Sun, 2 Apr 2023 00:25:46 +0200 Subject: [PATCH 27/39] initial v2 --- .github/ISSUE_TEMPLATE.md | 55 ++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 16 +++++ .github/workflows/updater.sh | 104 ------------------------------- .github/workflows/updater.yml | 49 --------------- check_process | 23 ------- conf/app.src | 6 -- conf/systemd.service | 4 +- doc/{DISCLAIMER.md => ADMIN.md} | 0 doc/screenshots/DESCRIPTION.md | 1 - manifest.toml | 59 ++++++++++++++++++ scripts/_common.sh | 2 +- scripts/backup | 14 ++--- scripts/change_url | 64 ++++++++++--------- scripts/install | 64 +++++++++---------- scripts/remove | 22 +++---- scripts/restore | 34 +++++----- scripts/upgrade | 50 +++++++-------- 17 files changed, 258 insertions(+), 309 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md delete mode 100644 .github/workflows/updater.sh delete mode 100644 .github/workflows/updater.yml delete mode 100644 check_process delete mode 100644 conf/app.src rename doc/{DISCLAIMER.md => ADMIN.md} (100%) delete mode 100644 doc/screenshots/DESCRIPTION.md create mode 100644 manifest.toml diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..2729a6b --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,55 @@ +--- +name: Bug report +about: When creating a bug report, please use the following template to provide all the relevant information and help debugging efficiently. + +--- + +**How to post a meaningful bug report** +1. *Read this whole template first.* +2. *Determine if you are on the right place:* + - *If you were performing an action on the app from the webadmin or the CLI (install, update, backup, restore, change_url...), you are on the right place!* + - *Otherwise, the issue may be due to the app itself. Refer to its documentation or repository for help.* + - *When in doubt, post here and we will figure it out together.* +3. *Delete the italic comments as you write over them below, and remove this guide.* +--- + +### Describe the bug + +*A clear and concise description of what the bug is.* + +### Context + +- Hardware: *VPS bought online / Old laptop or computer / Raspberry Pi at home / Internet Cube with VPN / Other ARM board / ...* +- YunoHost version: x.x.x +- I have access to my server: *Through SSH | through the webadmin | direct access via keyboard / screen | ...* +- Are you in a special context or did you perform some particular tweaking on your YunoHost instance?: *no / yes* + - If yes, please explain: +- Using, or trying to install package version/branch: +- If upgrading, current package version: *can be found in the admin, or with `yunohost app info $app_id`* + +### Steps to reproduce + +- *If you performed a command from the CLI, the command itself is enough. For example:* + ```sh + sudo yunohost app install the_app + ``` +- *If you used the webadmin, please perform the equivalent command from the CLI first.* +- *If the error occurs in your browser, explain what you did:* + 1. *Go to '...'* + 2. *Click on '...'* + 3. *Scroll down to '...'* + 4. *See error* + +### Expected behavior + +*A clear and concise description of what you expected to happen. You can remove this section if the command above is enough to understand your intent.* + +### Logs + +*When an operation fails, YunoHost provides a simple way to share the logs.* +- *In the webadmin, the error message contains a link to the relevant log page. On that page, you will be able to 'Share with Yunopaste'. If you missed it, the logs of previous operations are also available under Tools > Logs.* +- *In command line, the command to share the logs is displayed at the end of the operation and looks like `yunohost log display [log name] --share`. If you missed it, you can find the log ID of a previous operation using `yunohost log list`.* + +*After sharing the log, please copypaste directly the link provided by YunoHost (to help readability, no need to copypaste the entire content of the log here, just the link is enough...)* + +*If applicable and useful, add screenshots to help explain your problem.* diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..ef70e18 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +## Problem + +- *Description of why you made this PR* + +## Solution + +- *And how do you fix that problem* + +## PR Status + +- [ ] Code finished and ready to be reviewed/tested +- [ ] The fix/enhancement were manually tested (if applicable) + +## Automatic tests + +Automatic tests can be triggered on https://ci-apps-dev.yunohost.org/ *after creating the PR*, by commenting "!testme", "!gogogadgetoci" or "By the power of systemd, I invoke The Great App CI to test this Pull Request!". (N.B. : for this to work you need to be a member of the Yunohost-Apps organization) diff --git a/.github/workflows/updater.sh b/.github/workflows/updater.sh deleted file mode 100644 index 2c57665..0000000 --- a/.github/workflows/updater.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/bash - -#================================================= -# PACKAGE UPDATING HELPER -#================================================= - -# This script is meant to be run by GitHub Actions -# The YunoHost-Apps organisation offers a template Action to run this script periodically -# Since each app is different, maintainers can adapt its contents so as to perform -# automatic actions when a new upstream release is detected. - -#================================================= -# FETCHING LATEST RELEASE AND ITS ASSETS -#================================================= - -# Fetching information -current_version=$(cat manifest.json | jq -j '.version|split("~")[0]') -repo=$(cat manifest.json | jq -j '.upstream.code|split("https://github.com/")[1]') -# Some jq magic is needed, because the latest upstream release is not always the latest version (e.g. security patches for older versions) -version=$(curl --silent "https://api.github.com/repos/$repo/releases" | jq -r '.[] | select( .prerelease != true ) | .tag_name' | sort -V | tail -1) -assets="https://github.com/$repo/archive/refs/tags/$version.tar.gz" - -# Later down the script, we assume the version has only digits and dots -# Sometimes the release name starts with a "v", so let's filter it out. -# You may need more tweaks here if the upstream repository has different naming conventions. -if [[ ${version:0:1} == "v" || ${version:0:1} == "V" ]]; then - version=${version:1} -fi - -# Setting up the environment variables -echo "Current version: $current_version" -echo "Latest release from upstream: $version" -echo "VERSION=$version" >> $GITHUB_ENV -# For the time being, let's assume the script will fail -echo "PROCEED=false" >> $GITHUB_ENV - -# Proceed only if the retrieved version is greater than the current one -if ! dpkg --compare-versions "$current_version" "lt" "$version" ; then - echo "::warning ::No new version available" - exit 0 -# Proceed only if a PR for this new version does not already exist -elif git ls-remote -q --exit-code --heads https://github.com/$GITHUB_REPOSITORY.git ci-auto-update-v$version ; then - echo "::warning ::A branch already exists for this update" - exit 0 -fi - -#================================================= -# UPDATE SOURCE FILES -#================================================= - -# Let's download source tarball -asset_url=$assets -echo "Handling asset at $asset_url" -src="app" - -# Create the temporary directory -tempdir="$(mktemp -d)" - -# Download sources and calculate checksum -filename=${asset_url##*/} -curl --silent -4 -L $asset_url -o "$tempdir/$filename" -checksum=$(sha256sum "$tempdir/$filename" | head -c 64) - -# Delete temporary directory -rm -rf $tempdir - -# Get extension -if [[ $filename == *.tar.gz ]]; then - extension=tar.gz -else - extension=${filename##*.} -fi - -# Rewrite source file -cat < conf/$src.src -SOURCE_URL=$asset_url -SOURCE_SUM=$checksum -SOURCE_SUM_PRG=sha256sum -SOURCE_FORMAT=$extension -SOURCE_IN_SUBDIR=true -SOURCE_FILENAME= -EOT -echo "... conf/$src.src updated" - -# -#================================================= -# SPECIFIC UPDATE STEPS -#================================================= - -# Any action on the app's source code can be done. -# The GitHub Action workflow takes care of committing all changes after this script ends. - -#================================================= -# GENERIC FINALIZATION -#================================================= - -# Replace new version in manifest -echo "$(jq -s --indent 4 ".[] | .version = \"$version~ynh1\"" manifest.json)" > manifest.json - -# No need to update the README, yunohost-bot takes care of it - -# The Action will proceed only if the PROCEED environment variable is set to true -echo "PROCEED=true" >> $GITHUB_ENV -exit 0 diff --git a/.github/workflows/updater.yml b/.github/workflows/updater.yml deleted file mode 100644 index a56d7cb..0000000 --- a/.github/workflows/updater.yml +++ /dev/null @@ -1,49 +0,0 @@ -# This workflow allows GitHub Actions to automagically update your app whenever a new upstream release is detected. -# You need to enable Actions in your repository settings, and fetch this Action from the YunoHost-Apps organization. -# This file should be enough by itself, but feel free to tune it to your needs. -# It calls updater.sh, which is where you should put the app-specific update steps. -name: Check for new upstream releases -on: - # Allow to manually trigger the workflow - workflow_dispatch: - # Run it every day at 6:00 UTC - schedule: - - cron: '0 6 * * *' -jobs: - updater: - runs-on: ubuntu-latest - steps: - - name: Fetch the source code - uses: actions/checkout@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - name: Run the updater script - id: run_updater - run: | - # Setting up Git user - git config --global user.name 'yunohost-bot' - git config --global user.email 'yunohost-bot@users.noreply.github.com' - # Run the updater script - /bin/bash .github/workflows/updater.sh - - name: Commit changes - id: commit - if: ${{ env.PROCEED == 'true' }} - run: | - git commit -am "Upgrade to v$VERSION" - - name: Create Pull Request - id: cpr - if: ${{ env.PROCEED == 'true' }} - uses: peter-evans/create-pull-request@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - commit-message: Update to version ${{ env.VERSION }} - committer: 'yunohost-bot ' - author: 'yunohost-bot ' - signoff: false - base: testing - branch: ci-auto-update-v${{ env.VERSION }} - delete-branch: true - title: 'Upgrade to version ${{ env.VERSION }}' - body: | - Upgrade to v${{ env.VERSION }} - draft: false diff --git a/check_process b/check_process deleted file mode 100644 index 05d8ab4..0000000 --- a/check_process +++ /dev/null @@ -1,23 +0,0 @@ -;; Test complet - ; Manifest - domain="domain.tld" - path="/path" - is_public=1 - ; Checks - pkg_linter=1 - setup_sub_dir=0 - setup_root=1 - setup_nourl=0 - setup_private=1 - setup_public=1 - upgrade=1 - #upgrade=1 from_commit=CommitHash - backup_restore=1 - multi_instance=0 - change_url=1 -;;; Options -Email= -Notification=none -;;; Upgrade options - ; commit=CommitHash - name=Name and date of the commit. diff --git a/conf/app.src b/conf/app.src deleted file mode 100644 index a7fab59..0000000 --- a/conf/app.src +++ /dev/null @@ -1,6 +0,0 @@ -SOURCE_URL=https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.3.0.tar.gz -SOURCE_SUM=6f73d4d7d2e3b5a9bb0bb06877708d5b9101e7928fa15d82744ce0eca6af9773 -SOURCE_SUM_PRG=sha256sum -SOURCE_FORMAT=tar.gz -SOURCE_IN_SUBDIR=true -SOURCE_FILENAME= diff --git a/conf/systemd.service b/conf/systemd.service index 2d8e073..9cfc992 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -8,8 +8,8 @@ User=__APP__ Group=__APP__ Restart=always Type=simple -WorkingDirectory=__FINALPATH__ -ExecStart=/usr/local/bin/pipenv run python3 __FINALPATH__/.venv/bin/libretranslate --host 127.0.0.1 --port __PORT__ --load-only en,fr --frontend-language-target en +WorkingDirectory=__INSTALL_DIR__ +ExecStart=/usr/local/bin/pipenv run python3 __INSTALL_DIR__/.venv/bin/libretranslate --host 127.0.0.1 --port __PORT__ --load-only en,fr --frontend-language-target en [Install] WantedBy=multi-user.target diff --git a/doc/DISCLAIMER.md b/doc/ADMIN.md similarity index 100% rename from doc/DISCLAIMER.md rename to doc/ADMIN.md diff --git a/doc/screenshots/DESCRIPTION.md b/doc/screenshots/DESCRIPTION.md deleted file mode 100644 index 50a4b84..0000000 --- a/doc/screenshots/DESCRIPTION.md +++ /dev/null @@ -1 +0,0 @@ -Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. diff --git a/manifest.toml b/manifest.toml new file mode 100644 index 0000000..1be2c95 --- /dev/null +++ b/manifest.toml @@ -0,0 +1,59 @@ +packaging_format = 2 + +id = "libretranslate" +name = "LibreTranslate" +description.en = "Open Source Machine Translation API, entirely self-hosted" +description.fr = "API de traduction automatique Open Source, entièrement auto-hébergée" + +version = "1.3.0~ynh1" + +maintainers = ["John doe"] + +[upstream] +license = "AGPL-3.0" +website = "https://libretranslate.com/" +demo = "https://libretranslate.com/" +admindoc = "https://libretranslate.com/docs/" +code = "https://github.com/LibreTranslate/LibreTranslate" +cpe = "???" # FIXME: optional but recommended if relevant, this is meant to contain the Common Platform Enumeration, which is sort of a standard id for applications defined by the NIST. In particular, Yunohost may use this is in the future to easily track CVE (=security reports) related to apps. The CPE may be obtained by searching here: https://nvd.nist.gov/products/cpe/search. For example, for Nextcloud, the CPE is 'cpe:2.3:a:nextcloud:nextcloud' (no need to include the version number) +fund = "???" # FIXME: optional but recommended (or remove if irrelevant / not applicable). This is meant to be an URL where people can financially support this app, especially when its development is based on volunteers and/or financed by its community. YunoHost may later advertise it in the webadmin. + +[integration] +yunohost = ">= 11.0.9" +architectures = "all" # FIXME: can be replaced by a list of supported archs using the dpkg --print-architecture nomenclature (amd64/i386/armhf/arm64), for example: ["amd64", "i386"] +multi_instance = false +ldap = "?" # FIXME: replace with true, false, or "not_relevant". Not to confuse with the "sso" key : the "ldap" key corresponds to wether or not a user *can* login on the app using its YunoHost credentials. +sso = "?" # FIXME: replace with true, false, or "not_relevant". Not to confuse with the "ldap" key : the "sso" key corresponds to wether or not a user is *automatically logged-in* on the app when logged-in on the YunoHost portal. +disk = "50M" # FIXME: replace with an **estimate** minimum disk requirement. e.g. 20M, 400M, 1G, ... +ram.build = "50M" # FIXME: replace with an **estimate** minimum ram requirement. e.g. 50M, 400M, 1G, ... +ram.runtime = "50M" # FIXME: replace with an **estimate** minimum ram requirement. e.g. 50M, 400M, 1G, ... + +[install] + [install.domain] + # this is a generic question - ask strings are automatically handled by Yunohost's core + type = "domain" + full_domain = true + + [install.init_main_permission] + type = "group" + default = "visitors" + +[resources] + [resources.sources] + [resources.sources.main] + url = "https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.3.0.tar.gz" + sha256 = "6f73d4d7d2e3b5a9bb0bb06877708d5b9101e7928fa15d82744ce0eca6af9773" + + + [resources.system_user] + + [resources.install_dir] + + [resources.permissions] + main.url = "/" + + [resources.ports] + main.default = 5000 + + [resources.apt] + packages = "libicu-dev, python3-venv, python3-icu, pkg-config, python3, python3-pip, python3-dev, build-essential, libssl-dev, libffi-dev, python3-setuptools" diff --git a/scripts/_common.sh b/scripts/_common.sh index 2ee333b..fb3c2e9 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -5,7 +5,7 @@ #================================================= # dependencies used by the app -pkg_dependencies="libicu-dev python3-venv python3-icu pkg-config python3 python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools" +#REMOVEME? pkg_dependencies="libicu-dev python3-venv python3-icu pkg-config python3 python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools" libretranslate_version="1.3.0" diff --git a/scripts/backup b/scripts/backup index bfc28b4..3bcf144 100755 --- a/scripts/backup +++ b/scripts/backup @@ -14,22 +14,22 @@ source /usr/share/yunohost/helpers # MANAGE SCRIPT FAILURE #================================================= -ynh_clean_setup () { +#REMOVEME? ynh_clean_setup () { ### Remove this function if there's nothing to clean before calling the remove script. true } # Exit if an error occurs during the execution of the script -ynh_abort_if_errors +#REMOVEME? ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= -ynh_print_info --message="Loading installation settings..." +#REMOVEME? ynh_print_info --message="Loading installation settings..." -app=$YNH_APP_INSTANCE_NAME +#REMOVEME? app=$YNH_APP_INSTANCE_NAME -final_path=$(ynh_app_setting_get --app=$app --key=final_path) -domain=$(ynh_app_setting_get --app=$app --key=domain) +#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) +#REMOVEME? domain=$(ynh_app_setting_get --app=$app --key=domain) #================================================= # DECLARE DATA AND CONF FILES TO BACKUP @@ -40,7 +40,7 @@ ynh_print_info --message="Declaring files to be backed up..." # BACKUP THE APP MAIN DIR #================================================= -ynh_backup --src_path="$final_path" +ynh_backup --src_path="$install_dir" #================================================= # BACKUP THE NGINX CONFIGURATION diff --git a/scripts/change_url b/scripts/change_url index 730a148..01468d3 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -13,54 +13,54 @@ source /usr/share/yunohost/helpers # RETRIEVE ARGUMENTS #================================================= -old_domain=$YNH_APP_OLD_DOMAIN -old_path=$YNH_APP_OLD_PATH +#REMOVEME? old_domain=$YNH_APP_OLD_DOMAIN +#REMOVEME? old_path=$YNH_APP_OLD_PATH -new_domain=$YNH_APP_NEW_DOMAIN -new_path=$YNH_APP_NEW_PATH +#REMOVEME? new_domain=$YNH_APP_NEW_DOMAIN +#REMOVEME? new_path=$YNH_APP_NEW_PATH -app=$YNH_APP_INSTANCE_NAME +#REMOVEME? app=$YNH_APP_INSTANCE_NAME #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --weight=1 +#REMOVEME? 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) -port=$(ynh_app_setting_get --app=$app --key=port) +#REMOVEME? # Needed for helper "ynh_add_nginx_config" +#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) +#REMOVEME? port=$(ynh_app_setting_get --app=$app --key=port) #================================================= # BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP #================================================= -ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." --weight=1 +#REMOVEME? 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 () { +#REMOVEME? ynh_backup_before_upgrade +#REMOVEME? 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" +#REMOVEME? ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" # Restore it if the upgrade fails - ynh_restore_upgradebackup +#REMOVEME? ynh_restore_upgradebackup } # Exit if an error occurs during the execution of the script -ynh_abort_if_errors +#REMOVEME? ynh_abort_if_errors #================================================= # CHECK WHICH PARTS SHOULD BE CHANGED #================================================= -change_domain=0 -if [ "$old_domain" != "$new_domain" ] +#REMOVEME? change_domain=0 +#REMOVEME? if [ "$old_domain" != "$new_domain" ] then - change_domain=1 + #REMOVEME? change_domain=1 fi -change_path=0 -if [ "$old_path" != "$new_path" ] +#REMOVEME? change_path=0 +#REMOVEME? if [ "$old_path" != "$new_path" ] then - change_path=1 + #REMOVEME? change_path=1 fi #================================================= @@ -77,28 +77,30 @@ ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app #================================================= ynh_script_progression --message="Updating NGINX web server configuration..." --time --weight=1 -nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf +ynh_change_url_nginx_config + +#REMOVEME? 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" +#REMOVEME? ynh_backup_if_checksum_is_different --file="$nginx_conf_path" # Set global variables for NGINX helper - domain="$old_domain" - path_url="$new_path" +#REMOVEME? domain="$old_domain" +#REMOVEME? path="$new_path" # Create a dedicated NGINX config - ynh_add_nginx_config +#REMOVEME? 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 +#REMOVEME? ynh_delete_file_checksum --file="$nginx_conf_path" +#REMOVEME? 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" +#REMOVEME? ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" fi #================================================= @@ -113,9 +115,9 @@ ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$ap #================================================= # RELOAD NGINX #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --time --weight=1 +#REMOVEME? ynh_script_progression --message="Reloading NGINX web server..." --time --weight=1 -ynh_systemd_action --service_name=nginx --action=reload +#REMOVEME? #REMOVEME? ynh_systemd_action --service_name=nginx --action=reload #================================================= # END OF SCRIPT diff --git a/scripts/install b/scripts/install index 836545d..01d1a10 100755 --- a/scripts/install +++ b/scripts/install @@ -13,80 +13,80 @@ source /usr/share/yunohost/helpers # MANAGE SCRIPT FAILURE #================================================= -ynh_clean_setup () { +#REMOVEME? ynh_clean_setup () { ### Remove this function if there's nothing to clean before calling the remove script. true } # Exit if an error occurs during the execution of the script -ynh_abort_if_errors +#REMOVEME? ynh_abort_if_errors #================================================= # RETRIEVE ARGUMENTS FROM THE MANIFEST #================================================= -domain=$YNH_APP_ARG_DOMAIN -path_url="/" -is_public=$YNH_APP_ARG_IS_PUBLIC +#REMOVEME? domain=$YNH_APP_ARG_DOMAIN +path="/" +#REMOVEME? is_public=$YNH_APP_ARG_IS_PUBLIC -app=$YNH_APP_INSTANCE_NAME +#REMOVEME? app=$YNH_APP_INSTANCE_NAME #================================================= # CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS #================================================= -ynh_script_progression --message="Validating installation parameters..." --weight=1 +#REMOVEME? ynh_script_progression --message="Validating installation parameters..." --weight=1 -final_path=/var/www/$app -test ! -e "$final_path" || ynh_die --message="This path already contains a folder" +#REMOVEME? install_dir=/var/www/$app +#REMOVEME? test ! -e "$install_dir" || ynh_die --message="This path already contains a folder" # Register (book) web path -ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url +#REMOVEME? ynh_webpath_register --app=$app --domain=$domain --path=$path #================================================= # STORE SETTINGS FROM MANIFEST #================================================= -ynh_script_progression --message="Storing installation settings..." --weight=1 +#REMOVEME? ynh_script_progression --message="Storing installation settings..." --weight=1 -ynh_app_setting_set --app=$app --key=domain --value=$domain -ynh_app_setting_set --app=$app --key=path --value=$path_url +#REMOVEME? ynh_app_setting_set --app=$app --key=domain --value=$domain +#REMOVEME? ynh_app_setting_set --app=$app --key=path --value=$path #================================================= # STANDARD MODIFICATIONS #================================================= # FIND AND OPEN A PORT #================================================= -ynh_script_progression --message="Finding an available port..." --weight=1 +#REMOVEME? ynh_script_progression --message="Finding an available port..." --weight=1 # Find an available port -port=$(ynh_find_port --port=5000) -ynh_app_setting_set --app=$app --key=port --value=$port +#REMOVEME? port=$(ynh_find_port --port=5000) +#REMOVEME? ynh_app_setting_set --app=$app --key=port --value=$port #================================================= # INSTALL DEPENDENCIES #================================================= -ynh_script_progression --message="Installing dependencies..." --weight=20 +#REMOVEME? ynh_script_progression --message="Installing dependencies..." --weight=20 -ynh_install_app_dependencies $pkg_dependencies +#REMOVEME? ynh_install_app_dependencies $pkg_dependencies #================================================= # CREATE DEDICATED USER #================================================= -ynh_script_progression --message="Configuring system user..." --weight=1 +#REMOVEME? ynh_script_progression --message="Configuring system user..." --weight=1 # Create a system user -ynh_system_user_create --username=$app --home_dir="$final_path" +#REMOVEME? ynh_system_user_create --username=$app --home_dir="$install_dir" #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= ynh_script_progression --message="Setting up source files..." --weight=1 -ynh_app_setting_set --app=$app --key=final_path --value=$final_path +#REMOVEME? ynh_app_setting_set --app=$app --key=install_dir --value=$install_dir # Download, check integrity, uncompress and patch the source from app.src -ynh_setup_source --dest_dir="$final_path" +ynh_setup_source --dest_dir="$install_dir" -chmod 750 "$final_path" -chmod -R o-rwx "$final_path" -chown -R $app:www-data "$final_path" +chmod 750 "$install_dir" +chmod -R o-rwx "$install_dir" +chown -R $app:www-data "$install_dir" #================================================= # NGINX CONFIGURATION @@ -103,7 +103,7 @@ ynh_script_progression --message="Installing LibreTranslate..." --weight=1 sudo -u $app python3 -m pip install pipenv -pushd $final_path +pushd $install_dir sudo -u $app PIPENV_VENV_IN_PROJECT="enabled" PIPENV_SKIP_LOCK=true python3 -m pipenv install libretranslate==$libretranslate_version 2>&1 popd @@ -143,22 +143,22 @@ ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$ap #================================================= # SETUP SSOWAT #================================================= -ynh_script_progression --message="Configuring permissions..." --weight=1 +#REMOVEME? ynh_script_progression --message="Configuring permissions..." --weight=1 # Make app public if necessary -if [ $is_public -eq 1 ] +#REMOVEME? if [ $is_public -eq 1 ] then - ynh_permission_update --permission="main" --add="visitors" +#REMOVEME? ynh_permission_update --permission="main" --add="visitors" fi -ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --auth_header="false" --show_tile="false" --protected="true" +#REMOVEME? ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --auth_header="false" --show_tile="false" --protected="true" #================================================= # RELOAD NGINX #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --weight=1 +#REMOVEME? ynh_script_progression --message="Reloading NGINX web server..." --weight=1 -ynh_systemd_action --service_name=nginx --action=reload +#REMOVEME? ynh_systemd_action --service_name=nginx --action=reload #================================================= # END OF SCRIPT diff --git a/scripts/remove b/scripts/remove index d5c442b..cf5a2bc 100755 --- a/scripts/remove +++ b/scripts/remove @@ -12,13 +12,13 @@ source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --weight=1 +#REMOVEME? ynh_script_progression --message="Loading installation settings..." --weight=1 -app=$YNH_APP_INSTANCE_NAME +#REMOVEME? app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get --app=$app --key=domain) -port=$(ynh_app_setting_get --app=$app --key=port) -final_path=$(ynh_app_setting_get --app=$app --key=final_path) +#REMOVEME? domain=$(ynh_app_setting_get --app=$app --key=domain) +#REMOVEME? port=$(ynh_app_setting_get --app=$app --key=port) +#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) #================================================= # STANDARD REMOVE @@ -44,18 +44,18 @@ ynh_remove_systemd_config #================================================= # REMOVE DEPENDENCIES #================================================= -ynh_script_progression --message="Removing dependencies..." --weight=4 +#REMOVEME? ynh_script_progression --message="Removing dependencies..." --weight=4 # Remove metapackage and its dependencies -ynh_remove_app_dependencies +#REMOVEME? ynh_remove_app_dependencies #================================================= # REMOVE APP MAIN DIR #================================================= -ynh_script_progression --message="Removing app main directory..." --weight=3 +#REMOVEME? ynh_script_progression --message="Removing app main directory..." --weight=3 # Remove the app directory securely -ynh_secure_remove --file="$final_path" +#REMOVEME? ynh_secure_remove --file="$install_dir" #================================================= # REMOVE NGINX CONFIGURATION @@ -78,10 +78,10 @@ ynh_remove_logrotate #================================================= # REMOVE DEDICATED USER #================================================= -ynh_script_progression --message="Removing the dedicated system user..." --weight=1 +#REMOVEME? ynh_script_progression --message="Removing the dedicated system user..." --weight=1 # Delete a system user -ynh_system_user_delete --username=$app +#REMOVEME? ynh_system_user_delete --username=$app #================================================= # END OF SCRIPT diff --git a/scripts/restore b/scripts/restore index d64e57c..96c9cdc 100755 --- a/scripts/restore +++ b/scripts/restore @@ -14,30 +14,30 @@ source /usr/share/yunohost/helpers # MANAGE SCRIPT FAILURE #================================================= -ynh_clean_setup () { +#REMOVEME? ynh_clean_setup () { #### Remove this function if there's nothing to clean before calling the remove script. true } # Exit if an error occurs during the execution of the script -ynh_abort_if_errors +#REMOVEME? ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --weight=1 +#REMOVEME? ynh_script_progression --message="Loading installation settings..." --weight=1 -app=$YNH_APP_INSTANCE_NAME +#REMOVEME? app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get --app=$app --key=domain) -path_url=$(ynh_app_setting_get --app=$app --key=path) -final_path=$(ynh_app_setting_get --app=$app --key=final_path) +#REMOVEME? domain=$(ynh_app_setting_get --app=$app --key=domain) +#REMOVEME? path=$(ynh_app_setting_get --app=$app --key=path) +#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) #================================================= # CHECK IF THE APP CAN BE RESTORED #================================================= -ynh_script_progression --message="Validating restoration parameters..." --weight=1 +#REMOVEME? ynh_script_progression --message="Validating restoration parameters..." --weight=1 -test ! -d $final_path || ynh_die --message="There is already a directory: $final_path " +#REMOVEME? test ! -d $install_dir || ynh_die --message="There is already a directory: $install_dir " #================================================= # STANDARD RESTORATION STEPS @@ -51,31 +51,31 @@ ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" #================================================= # RECREATE THE DEDICATED USER #================================================= -ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 +#REMOVEME? ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 # Create the dedicated user (if not existing) -ynh_system_user_create --username=$app --home_dir="$final_path" +#REMOVEME? ynh_system_user_create --username=$app --home_dir="$install_dir" #================================================= # RESTORE THE APP MAIN DIR #================================================= ynh_script_progression --message="Restoring the app main directory..." --weight=1 -ynh_restore_file --origin_path="$final_path" +ynh_restore_file --origin_path="$install_dir" -chmod 750 "$final_path" -chmod -R o-rwx "$final_path" -chown -R $app:www-data "$final_path" +chmod 750 "$install_dir" +chmod -R o-rwx "$install_dir" +chown -R $app:www-data "$install_dir" #================================================= # SPECIFIC RESTORATION #================================================= # REINSTALL DEPENDENCIES #================================================= -ynh_script_progression --message="Reinstalling dependencies..." --weight=1 +#REMOVEME? ynh_script_progression --message="Reinstalling dependencies..." --weight=1 # Define and install dependencies -ynh_install_app_dependencies $pkg_dependencies +#REMOVEME? ynh_install_app_dependencies $pkg_dependencies #================================================= # RESTORE SYSTEMD diff --git a/scripts/upgrade b/scripts/upgrade index 505fbea..246174a 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -12,14 +12,14 @@ source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading installation settings..." --weight=1 +#REMOVEME? ynh_script_progression --message="Loading installation settings..." --weight=1 -app=$YNH_APP_INSTANCE_NAME +#REMOVEME? app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get --app=$app --key=domain) -path_url=$(ynh_app_setting_get --app=$app --key=path) -final_path=$(ynh_app_setting_get --app=$app --key=final_path) -port=$(ynh_app_setting_get --app=$app --key=port) +#REMOVEME? domain=$(ynh_app_setting_get --app=$app --key=domain) +#REMOVEME? path=$(ynh_app_setting_get --app=$app --key=path) +#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) +#REMOVEME? port=$(ynh_app_setting_get --app=$app --key=port) #================================================= # CHECK VERSION @@ -30,16 +30,16 @@ upgrade_type=$(ynh_check_app_version_changed) #================================================= # BACKUP BEFORE UPGRADE THEN ACTIVE TRAP #================================================= -ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=1 +#REMOVEME? ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=1 # Backup the current version of the app -ynh_backup_before_upgrade -ynh_clean_setup () { +#REMOVEME? ynh_backup_before_upgrade +#REMOVEME? ynh_clean_setup () { # Restore it if the upgrade fails - ynh_restore_upgradebackup +#REMOVEME? ynh_restore_upgradebackup } # Exit if an error occurs during the execution of the script -ynh_abort_if_errors +#REMOVEME? ynh_abort_if_errors #================================================= # STANDARD UPGRADE STEPS @@ -59,24 +59,24 @@ ynh_script_progression --message="Ensuring downward compatibility..." --weight=1 ### then you may safely remove these lines # Cleaning legacy permissions -if ynh_legacy_permissions_exists; then - ynh_legacy_permissions_delete_all +#REMOVEME? if ynh_legacy_permissions_exists; then +#REMOVEME? ynh_legacy_permissions_delete_all ynh_app_setting_delete --app=$app --key=is_public fi # Create a permission if needed -if ! ynh_permission_exists --permission="api"; then - ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --show_tile="false" --protected="true" +#REMOVEME? if ! ynh_permission_exists --permission="api"; then +#REMOVEME? ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --show_tile="false" --protected="true" fi #================================================= # CREATE DEDICATED USER #================================================= -ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 +#REMOVEME? ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 # Create a dedicated user (if not existing) -ynh_system_user_create --username=$app --home_dir="$final_path" +#REMOVEME? ynh_system_user_create --username=$app --home_dir="$install_dir" #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE @@ -87,12 +87,12 @@ then ynh_script_progression --message="Upgrading source files..." --weight=1 # Download, check integrity, uncompress and patch the source from app.src - ynh_setup_source --dest_dir="$final_path" + ynh_setup_source --dest_dir="$install_dir" fi -chmod 750 "$final_path" -chmod -R o-rwx "$final_path" -chown -R $app:www-data "$final_path" +chmod 750 "$install_dir" +chmod -R o-rwx "$install_dir" +chown -R $app:www-data "$install_dir" #================================================= # NGINX CONFIGURATION @@ -105,9 +105,9 @@ ynh_add_nginx_config #================================================= # UPGRADE DEPENDENCIES #================================================= -ynh_script_progression --message="Upgrading dependencies..." --weight=1 +#REMOVEME? ynh_script_progression --message="Upgrading dependencies..." --weight=1 -ynh_install_app_dependencies $pkg_dependencies +#REMOVEME? ynh_install_app_dependencies $pkg_dependencies #================================================= # SETUP SYSTEMD @@ -144,9 +144,9 @@ ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$ap #================================================= # RELOAD NGINX #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --weight=1 +#REMOVEME? ynh_script_progression --message="Reloading NGINX web server..." --weight=1 -ynh_systemd_action --service_name=nginx --action=reload +#REMOVEME? ynh_systemd_action --service_name=nginx --action=reload #================================================= # END OF SCRIPT From 7fa133debeb41ceb3f5724ebda5d2c5ed068fc1e Mon Sep 17 00:00:00 2001 From: Thomas <51749973+Thovi98@users.noreply.github.com> Date: Sun, 2 Apr 2023 00:44:00 +0200 Subject: [PATCH 28/39] first v2 version --- manifest.json | 43 --------------------- manifest.toml | 25 +++++-------- scripts/_common.sh | 5 +-- scripts/install | 93 +--------------------------------------------- 4 files changed, 12 insertions(+), 154 deletions(-) delete mode 100644 manifest.json diff --git a/manifest.json b/manifest.json deleted file mode 100644 index 75c2d0f..0000000 --- a/manifest.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "LibreTranslate", - "id": "libretranslate", - "packaging_format": 1, - "description": { - "en": "Open Source Machine Translation API, entirely self-hosted", - "fr": "API de traduction automatique Open Source, entièrement auto-hébergée" - }, - "version": "1.3.0~ynh1", - "url": "https://libretranslate.com/", - "upstream": { - "license": "AGPL-3.0", - "website": "https://libretranslate.com/", - "demo": "https://libretranslate.com/", - "admindoc": "https://libretranslate.com/docs/", - "code": "https://github.com/LibreTranslate/LibreTranslate" - }, - "license": "AGPL-3.0", - "maintainer": { - "name": "John doe", - "email": "john.doe@example.com" - }, - "requirements": { - "yunohost": ">= 11.0.9" - }, - "multi_instance": false, - "services": [ - "nginx" - ], - "arguments": { - "install": [ - { - "name": "domain", - "type": "domain" - }, - { - "name": "is_public", - "type": "boolean", - "default": true - } - ] - } -} diff --git a/manifest.toml b/manifest.toml index 1be2c95..c634b07 100644 --- a/manifest.toml +++ b/manifest.toml @@ -5,7 +5,7 @@ name = "LibreTranslate" description.en = "Open Source Machine Translation API, entirely self-hosted" description.fr = "API de traduction automatique Open Source, entièrement auto-hébergée" -version = "1.3.0~ynh1" +version = "1.3.10~ynh1" maintainers = ["John doe"] @@ -15,22 +15,19 @@ website = "https://libretranslate.com/" demo = "https://libretranslate.com/" admindoc = "https://libretranslate.com/docs/" code = "https://github.com/LibreTranslate/LibreTranslate" -cpe = "???" # FIXME: optional but recommended if relevant, this is meant to contain the Common Platform Enumeration, which is sort of a standard id for applications defined by the NIST. In particular, Yunohost may use this is in the future to easily track CVE (=security reports) related to apps. The CPE may be obtained by searching here: https://nvd.nist.gov/products/cpe/search. For example, for Nextcloud, the CPE is 'cpe:2.3:a:nextcloud:nextcloud' (no need to include the version number) -fund = "???" # FIXME: optional but recommended (or remove if irrelevant / not applicable). This is meant to be an URL where people can financially support this app, especially when its development is based on volunteers and/or financed by its community. YunoHost may later advertise it in the webadmin. [integration] -yunohost = ">= 11.0.9" -architectures = "all" # FIXME: can be replaced by a list of supported archs using the dpkg --print-architecture nomenclature (amd64/i386/armhf/arm64), for example: ["amd64", "i386"] -multi_instance = false -ldap = "?" # FIXME: replace with true, false, or "not_relevant". Not to confuse with the "sso" key : the "ldap" key corresponds to wether or not a user *can* login on the app using its YunoHost credentials. -sso = "?" # FIXME: replace with true, false, or "not_relevant". Not to confuse with the "ldap" key : the "sso" key corresponds to wether or not a user is *automatically logged-in* on the app when logged-in on the YunoHost portal. -disk = "50M" # FIXME: replace with an **estimate** minimum disk requirement. e.g. 20M, 400M, 1G, ... -ram.build = "50M" # FIXME: replace with an **estimate** minimum ram requirement. e.g. 50M, 400M, 1G, ... -ram.runtime = "50M" # FIXME: replace with an **estimate** minimum ram requirement. e.g. 50M, 400M, 1G, ... +yunohost = ">= 11.1.15" +architectures = "all" +multi_instance = true +ldap = "not_relevant" +sso = "not_relevant" +disk = "50M" +ram.build = "50M" +ram.runtime = "50M" [install] [install.domain] - # this is a generic question - ask strings are automatically handled by Yunohost's core type = "domain" full_domain = true @@ -40,10 +37,6 @@ ram.runtime = "50M" # FIXME: replace with an **estimate** minimum ram requiremen [resources] [resources.sources] - [resources.sources.main] - url = "https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.3.0.tar.gz" - sha256 = "6f73d4d7d2e3b5a9bb0bb06877708d5b9101e7928fa15d82744ce0eca6af9773" - [resources.system_user] diff --git a/scripts/_common.sh b/scripts/_common.sh index fb3c2e9..4f0aae7 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -4,10 +4,7 @@ # COMMON VARIABLES #================================================= -# dependencies used by the app -#REMOVEME? pkg_dependencies="libicu-dev python3-venv python3-icu pkg-config python3 python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools" - -libretranslate_version="1.3.0" +libretranslate_version="1.3.10" #================================================= # PERSONAL HELPERS diff --git a/scripts/install b/scripts/install index 01d1a10..139abb9 100755 --- a/scripts/install +++ b/scripts/install @@ -9,81 +9,11 @@ source _common.sh source /usr/share/yunohost/helpers -#================================================= -# MANAGE SCRIPT FAILURE -#================================================= - -#REMOVEME? ynh_clean_setup () { - ### Remove this function if there's nothing to clean before calling the remove script. - true -} -# Exit if an error occurs during the execution of the script -#REMOVEME? ynh_abort_if_errors - -#================================================= -# RETRIEVE ARGUMENTS FROM THE MANIFEST -#================================================= - -#REMOVEME? domain=$YNH_APP_ARG_DOMAIN -path="/" -#REMOVEME? is_public=$YNH_APP_ARG_IS_PUBLIC - -#REMOVEME? app=$YNH_APP_INSTANCE_NAME - -#================================================= -# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS -#================================================= -#REMOVEME? ynh_script_progression --message="Validating installation parameters..." --weight=1 - -#REMOVEME? install_dir=/var/www/$app -#REMOVEME? test ! -e "$install_dir" || ynh_die --message="This path already contains a folder" - -# Register (book) web path -#REMOVEME? ynh_webpath_register --app=$app --domain=$domain --path=$path - -#================================================= -# STORE SETTINGS FROM MANIFEST -#================================================= -#REMOVEME? ynh_script_progression --message="Storing installation settings..." --weight=1 - -#REMOVEME? ynh_app_setting_set --app=$app --key=domain --value=$domain -#REMOVEME? ynh_app_setting_set --app=$app --key=path --value=$path - -#================================================= -# STANDARD MODIFICATIONS -#================================================= -# FIND AND OPEN A PORT -#================================================= -#REMOVEME? ynh_script_progression --message="Finding an available port..." --weight=1 - -# Find an available port -#REMOVEME? port=$(ynh_find_port --port=5000) -#REMOVEME? ynh_app_setting_set --app=$app --key=port --value=$port - -#================================================= -# INSTALL DEPENDENCIES -#================================================= -#REMOVEME? ynh_script_progression --message="Installing dependencies..." --weight=20 - -#REMOVEME? ynh_install_app_dependencies $pkg_dependencies - -#================================================= -# CREATE DEDICATED USER -#================================================= -#REMOVEME? ynh_script_progression --message="Configuring system user..." --weight=1 - -# Create a system user -#REMOVEME? ynh_system_user_create --username=$app --home_dir="$install_dir" - #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= ynh_script_progression --message="Setting up source files..." --weight=1 -#REMOVEME? ynh_app_setting_set --app=$app --key=install_dir --value=$install_dir -# Download, check integrity, uncompress and patch the source from app.src -ynh_setup_source --dest_dir="$install_dir" - chmod 750 "$install_dir" chmod -R o-rwx "$install_dir" chown -R $app:www-data "$install_dir" @@ -104,7 +34,8 @@ ynh_script_progression --message="Installing LibreTranslate..." --weight=1 sudo -u $app python3 -m pip install pipenv pushd $install_dir - sudo -u $app PIPENV_VENV_IN_PROJECT="enabled" PIPENV_SKIP_LOCK=true python3 -m pipenv install libretranslate==$libretranslate_version 2>&1 + mkdir -p .venv + PIPENV_VENV_IN_PROJECT="enabled" PIPENV_SKIP_LOCK=true ynh_exec_warn_less python3 -m pipenv install libretranslate==$libretranslate_version 2>&1 popd #================================================= @@ -140,26 +71,6 @@ ynh_script_progression --message="Starting a systemd service..." --weight=1 # Start a systemd service ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" -#================================================= -# SETUP SSOWAT -#================================================= -#REMOVEME? ynh_script_progression --message="Configuring permissions..." --weight=1 - -# Make app public if necessary -#REMOVEME? if [ $is_public -eq 1 ] -then -#REMOVEME? ynh_permission_update --permission="main" --add="visitors" -fi - -#REMOVEME? ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --auth_header="false" --show_tile="false" --protected="true" - -#================================================= -# RELOAD NGINX -#================================================= -#REMOVEME? ynh_script_progression --message="Reloading NGINX web server..." --weight=1 - -#REMOVEME? ynh_systemd_action --service_name=nginx --action=reload - #================================================= # END OF SCRIPT #================================================= From 95ce5d855f4513871cb9769beb1753259fe1a097 Mon Sep 17 00:00:00 2001 From: Thomas <51749973+Thovi98@users.noreply.github.com> Date: Sun, 2 Apr 2023 00:52:30 +0200 Subject: [PATCH 29/39] test --- manifest.toml | 2 +- scripts/install | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest.toml b/manifest.toml index c634b07..089bdc0 100644 --- a/manifest.toml +++ b/manifest.toml @@ -49,4 +49,4 @@ ram.runtime = "50M" main.default = 5000 [resources.apt] - packages = "libicu-dev, python3-venv, python3-icu, pkg-config, python3, python3-pip, python3-dev, build-essential, libssl-dev, libffi-dev, python3-setuptools" + packages = "python3, python3-venv" diff --git a/scripts/install b/scripts/install index 139abb9..9e25765 100755 --- a/scripts/install +++ b/scripts/install @@ -31,7 +31,7 @@ ynh_add_nginx_config #================================================= ynh_script_progression --message="Installing LibreTranslate..." --weight=1 -sudo -u $app python3 -m pip install pipenv +ynh_exec_warn_less python3 -m pip install pipenv pushd $install_dir mkdir -p .venv From b86af03068971f54549d21ad50408c00c5d0f980 Mon Sep 17 00:00:00 2001 From: Thomas <51749973+Thovi98@users.noreply.github.com> Date: Sun, 2 Apr 2023 09:28:32 +0200 Subject: [PATCH 30/39] full v2 --- scripts/backup | 21 ------------ scripts/change_url | 85 ---------------------------------------------- scripts/install | 4 ++- scripts/remove | 37 -------------------- scripts/restore | 47 ------------------------- scripts/upgrade | 83 +++++++------------------------------------- 6 files changed, 15 insertions(+), 262 deletions(-) diff --git a/scripts/backup b/scripts/backup index 3bcf144..737146f 100755 --- a/scripts/backup +++ b/scripts/backup @@ -10,27 +10,6 @@ source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -#================================================= -# MANAGE SCRIPT FAILURE -#================================================= - -#REMOVEME? ynh_clean_setup () { - ### Remove this function if there's nothing to clean before calling the remove script. - true -} -# Exit if an error occurs during the execution of the script -#REMOVEME? ynh_abort_if_errors - -#================================================= -# LOAD SETTINGS -#================================================= -#REMOVEME? ynh_print_info --message="Loading installation settings..." - -#REMOVEME? app=$YNH_APP_INSTANCE_NAME - -#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) -#REMOVEME? domain=$(ynh_app_setting_get --app=$app --key=domain) - #================================================= # DECLARE DATA AND CONF FILES TO BACKUP #================================================= diff --git a/scripts/change_url b/scripts/change_url index 01468d3..f5ff536 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -9,60 +9,6 @@ source _common.sh source /usr/share/yunohost/helpers -#================================================= -# RETRIEVE ARGUMENTS -#================================================= - -#REMOVEME? old_domain=$YNH_APP_OLD_DOMAIN -#REMOVEME? old_path=$YNH_APP_OLD_PATH - -#REMOVEME? new_domain=$YNH_APP_NEW_DOMAIN -#REMOVEME? new_path=$YNH_APP_NEW_PATH - -#REMOVEME? app=$YNH_APP_INSTANCE_NAME - -#================================================= -# LOAD SETTINGS -#================================================= -#REMOVEME? ynh_script_progression --message="Loading installation settings..." --weight=1 - -#REMOVEME? # Needed for helper "ynh_add_nginx_config" -#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) -#REMOVEME? port=$(ynh_app_setting_get --app=$app --key=port) - -#================================================= -# BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP -#================================================= -#REMOVEME? 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 -#REMOVEME? ynh_backup_before_upgrade -#REMOVEME? ynh_clean_setup () { - # Remove the new domain config file, the remove script won't do it as it doesn't know yet its location. -#REMOVEME? ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" - - # Restore it if the upgrade fails -#REMOVEME? ynh_restore_upgradebackup -} -# Exit if an error occurs during the execution of the script -#REMOVEME? ynh_abort_if_errors - -#================================================= -# CHECK WHICH PARTS SHOULD BE CHANGED -#================================================= - -#REMOVEME? change_domain=0 -#REMOVEME? if [ "$old_domain" != "$new_domain" ] -then - #REMOVEME? change_domain=1 -fi - -#REMOVEME? change_path=0 -#REMOVEME? if [ "$old_path" != "$new_path" ] -then - #REMOVEME? change_path=1 -fi - #================================================= # STANDARD MODIFICATIONS #================================================= @@ -79,30 +25,6 @@ ynh_script_progression --message="Updating NGINX web server configuration..." -- ynh_change_url_nginx_config -#REMOVEME? 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 -#REMOVEME? ynh_backup_if_checksum_is_different --file="$nginx_conf_path" - # Set global variables for NGINX helper -#REMOVEME? domain="$old_domain" -#REMOVEME? path="$new_path" - # Create a dedicated NGINX config -#REMOVEME? 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 -#REMOVEME? ynh_delete_file_checksum --file="$nginx_conf_path" -#REMOVEME? mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf - # Store file checksum for the new config file location -#REMOVEME? ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" -fi - #================================================= # GENERIC FINALISATION #================================================= @@ -112,13 +34,6 @@ ynh_script_progression --message="Starting a systemd service..." --time --weight ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" -#================================================= -# RELOAD NGINX -#================================================= -#REMOVEME? ynh_script_progression --message="Reloading NGINX web server..." --time --weight=1 - -#REMOVEME? #REMOVEME? ynh_systemd_action --service_name=nginx --action=reload - #================================================= # END OF SCRIPT #================================================= diff --git a/scripts/install b/scripts/install index 9e25765..593f1c2 100755 --- a/scripts/install +++ b/scripts/install @@ -29,10 +29,12 @@ ynh_add_nginx_config #================================================= # SPECIFIC SETUP #================================================= -ynh_script_progression --message="Installing LibreTranslate..." --weight=1 +ynh_script_progression --message="Installing dependencies..." --weight=2 ynh_exec_warn_less python3 -m pip install pipenv +ynh_script_progression --message="Installing LibreTranslate..." --weight=2 + pushd $install_dir mkdir -p .venv PIPENV_VENV_IN_PROJECT="enabled" PIPENV_SKIP_LOCK=true ynh_exec_warn_less python3 -m pipenv install libretranslate==$libretranslate_version 2>&1 diff --git a/scripts/remove b/scripts/remove index cf5a2bc..9183bee 100755 --- a/scripts/remove +++ b/scripts/remove @@ -9,17 +9,6 @@ source _common.sh source /usr/share/yunohost/helpers -#================================================= -# LOAD SETTINGS -#================================================= -#REMOVEME? ynh_script_progression --message="Loading installation settings..." --weight=1 - -#REMOVEME? app=$YNH_APP_INSTANCE_NAME - -#REMOVEME? domain=$(ynh_app_setting_get --app=$app --key=domain) -#REMOVEME? port=$(ynh_app_setting_get --app=$app --key=port) -#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) - #================================================= # STANDARD REMOVE #================================================= @@ -41,22 +30,6 @@ ynh_script_progression --message="Stopping and removing the systemd service..." # Remove the dedicated systemd config ynh_remove_systemd_config -#================================================= -# REMOVE DEPENDENCIES -#================================================= -#REMOVEME? ynh_script_progression --message="Removing dependencies..." --weight=4 - -# Remove metapackage and its dependencies -#REMOVEME? ynh_remove_app_dependencies - -#================================================= -# REMOVE APP MAIN DIR -#================================================= -#REMOVEME? ynh_script_progression --message="Removing app main directory..." --weight=3 - -# Remove the app directory securely -#REMOVEME? ynh_secure_remove --file="$install_dir" - #================================================= # REMOVE NGINX CONFIGURATION #================================================= @@ -73,16 +46,6 @@ ynh_script_progression --message="Removing logrotate configuration..." --weight= # Remove the app-specific logrotate config ynh_remove_logrotate -#================================================= -# GENERIC FINALIZATION -#================================================= -# REMOVE DEDICATED USER -#================================================= -#REMOVEME? ynh_script_progression --message="Removing the dedicated system user..." --weight=1 - -# Delete a system user -#REMOVEME? ynh_system_user_delete --username=$app - #================================================= # END OF SCRIPT #================================================= diff --git a/scripts/restore b/scripts/restore index 96c9cdc..c3271d1 100755 --- a/scripts/restore +++ b/scripts/restore @@ -10,35 +10,6 @@ source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -#================================================= -# MANAGE SCRIPT FAILURE -#================================================= - -#REMOVEME? ynh_clean_setup () { - #### Remove this function if there's nothing to clean before calling the remove script. - true -} -# Exit if an error occurs during the execution of the script -#REMOVEME? ynh_abort_if_errors - -#================================================= -# LOAD SETTINGS -#================================================= -#REMOVEME? ynh_script_progression --message="Loading installation settings..." --weight=1 - -#REMOVEME? app=$YNH_APP_INSTANCE_NAME - -#REMOVEME? domain=$(ynh_app_setting_get --app=$app --key=domain) -#REMOVEME? path=$(ynh_app_setting_get --app=$app --key=path) -#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) - -#================================================= -# CHECK IF THE APP CAN BE RESTORED -#================================================= -#REMOVEME? ynh_script_progression --message="Validating restoration parameters..." --weight=1 - -#REMOVEME? test ! -d $install_dir || ynh_die --message="There is already a directory: $install_dir " - #================================================= # STANDARD RESTORATION STEPS #================================================= @@ -48,14 +19,6 @@ ynh_script_progression --message="Restoring the NGINX configuration..." --weight ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" -#================================================= -# RECREATE THE DEDICATED USER -#================================================= -#REMOVEME? ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 - -# Create the dedicated user (if not existing) -#REMOVEME? ynh_system_user_create --username=$app --home_dir="$install_dir" - #================================================= # RESTORE THE APP MAIN DIR #================================================= @@ -67,16 +30,6 @@ chmod 750 "$install_dir" chmod -R o-rwx "$install_dir" chown -R $app:www-data "$install_dir" -#================================================= -# SPECIFIC RESTORATION -#================================================= -# REINSTALL DEPENDENCIES -#================================================= -#REMOVEME? ynh_script_progression --message="Reinstalling dependencies..." --weight=1 - -# Define and install dependencies -#REMOVEME? ynh_install_app_dependencies $pkg_dependencies - #================================================= # RESTORE SYSTEMD #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index 246174a..1d12878 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -9,37 +9,12 @@ source _common.sh source /usr/share/yunohost/helpers -#================================================= -# LOAD SETTINGS -#================================================= -#REMOVEME? ynh_script_progression --message="Loading installation settings..." --weight=1 - -#REMOVEME? app=$YNH_APP_INSTANCE_NAME - -#REMOVEME? domain=$(ynh_app_setting_get --app=$app --key=domain) -#REMOVEME? path=$(ynh_app_setting_get --app=$app --key=path) -#REMOVEME? #REMOVEME? install_dir=$(ynh_app_setting_get --app=$app --key=install_dir) -#REMOVEME? port=$(ynh_app_setting_get --app=$app --key=port) - #================================================= # CHECK VERSION #================================================= upgrade_type=$(ynh_check_app_version_changed) -#================================================= -# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP -#================================================= -#REMOVEME? ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=1 - -# Backup the current version of the app -#REMOVEME? ynh_backup_before_upgrade -#REMOVEME? ynh_clean_setup () { - # Restore it if the upgrade fails -#REMOVEME? ynh_restore_upgradebackup -} -# Exit if an error occurs during the execution of the script -#REMOVEME? ynh_abort_if_errors #================================================= # STANDARD UPGRADE STEPS @@ -50,45 +25,10 @@ ynh_script_progression --message="Stopping a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" -#================================================= -# ENSURE DOWNWARD COMPATIBILITY -#================================================= -ynh_script_progression --message="Ensuring downward compatibility..." --weight=1 - -### If nobody installed your app before 4.1, -### then you may safely remove these lines - -# Cleaning legacy permissions -#REMOVEME? if ynh_legacy_permissions_exists; then -#REMOVEME? ynh_legacy_permissions_delete_all - - ynh_app_setting_delete --app=$app --key=is_public -fi - -# Create a permission if needed -#REMOVEME? if ! ynh_permission_exists --permission="api"; then -#REMOVEME? ynh_permission_create --permission="api" --url="/api" --allowed="visitors" --show_tile="false" --protected="true" -fi - -#================================================= -# CREATE DEDICATED USER -#================================================= -#REMOVEME? ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 - -# Create a dedicated user (if not existing) -#REMOVEME? ynh_system_user_create --username=$app --home_dir="$install_dir" - #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= - -if [ "$upgrade_type" == "UPGRADE_APP" ] -then - ynh_script_progression --message="Upgrading source files..." --weight=1 - - # Download, check integrity, uncompress and patch the source from app.src - ynh_setup_source --dest_dir="$install_dir" -fi +ynh_script_progression --message="Setting up source files..." --weight=1 chmod 750 "$install_dir" chmod -R o-rwx "$install_dir" @@ -103,11 +43,19 @@ ynh_script_progression --message="Upgrading NGINX web server configuration..." - ynh_add_nginx_config #================================================= -# UPGRADE DEPENDENCIES +# SPECIFIC SETUP #================================================= -#REMOVEME? ynh_script_progression --message="Upgrading dependencies..." --weight=1 +ynh_script_progression --message="Installing dependencies..." --weight=2 + +ynh_exec_warn_less python3 -m pip install pipenv + + +ynh_script_progression --message="Installing LibreTranslate..." --weight=2 +pushd $install_dir + mkdir -p .venv + PIPENV_VENV_IN_PROJECT="enabled" PIPENV_SKIP_LOCK=true ynh_exec_warn_less python3 -m pipenv install libretranslate==$libretranslate_version 2>&1 +popd -#REMOVEME? ynh_install_app_dependencies $pkg_dependencies #================================================= # SETUP SYSTEMD @@ -141,13 +89,6 @@ ynh_script_progression --message="Starting a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" -#================================================= -# RELOAD NGINX -#================================================= -#REMOVEME? ynh_script_progression --message="Reloading NGINX web server..." --weight=1 - -#REMOVEME? ynh_systemd_action --service_name=nginx --action=reload - #================================================= # END OF SCRIPT #================================================= From c092a0445927645b2cd3dbd1ff3fdf46e4b2a7f3 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 2 Apr 2023 10:11:26 +0200 Subject: [PATCH 31/39] Update _common.sh --- scripts/_common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/_common.sh b/scripts/_common.sh index 2ee333b..e24e5ec 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -7,7 +7,7 @@ # dependencies used by the app pkg_dependencies="libicu-dev python3-venv python3-icu pkg-config python3 python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools" -libretranslate_version="1.3.0" +libretranslate_version="1.3.10" #================================================= # PERSONAL HELPERS From 66c93fff13772d3c33823e79777bd98fb8ef4c47 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 2 Apr 2023 10:11:56 +0200 Subject: [PATCH 32/39] Update manifest.json --- manifest.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index 75c2d0f..0ffceaf 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Open Source Machine Translation API, entirely self-hosted", "fr": "API de traduction automatique Open Source, entièrement auto-hébergée" }, - "version": "1.3.0~ynh1", + "version": "1.3.10~ynh1", "url": "https://libretranslate.com/", "upstream": { "license": "AGPL-3.0", @@ -17,8 +17,8 @@ }, "license": "AGPL-3.0", "maintainer": { - "name": "John doe", - "email": "john.doe@example.com" + "name": "", + "email": "" }, "requirements": { "yunohost": ">= 11.0.9" From 6635ab6963c96f5e6dd13122be2802ec4f5bcf05 Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Sun, 2 Apr 2023 08:12:01 +0000 Subject: [PATCH 33/39] Auto-update README --- README.md | 2 +- README_fr.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a1a24cd..43514f3 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. -**Shipped version:** 1.3.0~ynh1 +**Shipped version:** 1.3.10~ynh1 **Demo:** https://libretranslate.com/ diff --git a/README_fr.md b/README_fr.md index 6a9f364..5dcfeb4 100644 --- a/README_fr.md +++ b/README_fr.md @@ -19,7 +19,7 @@ Si vous n’avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) po Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library. -**Version incluse :** 1.3.0~ynh1 +**Version incluse :** 1.3.10~ynh1 **Démo :** https://libretranslate.com/ From 69b66926043e114ff6169fd18044bd83b9a5b0dc Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 2 Apr 2023 10:12:55 +0200 Subject: [PATCH 34/39] Update app.src --- conf/app.src | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/app.src b/conf/app.src index a7fab59..265cf81 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.3.0.tar.gz -SOURCE_SUM=6f73d4d7d2e3b5a9bb0bb06877708d5b9101e7928fa15d82744ce0eca6af9773 +SOURCE_URL=https://github.com/LibreTranslate/LibreTranslate/archive/refs/tags/v1.3.10.tar.gz +SOURCE_SUM=e6ce896b2da48e2a87d294d206db8e2d347b7f3e06d037a2b93ca01c0a6d5b4e SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=tar.gz SOURCE_IN_SUBDIR=true From f9915e03f6ee3afc416254b2c96bcd50a2bb15ef Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 2 Apr 2023 10:25:34 +0200 Subject: [PATCH 35/39] cleaning --- conf/nginx.conf | 5 ++++- conf/systemd.service | 34 ++++++++++++++++++++++++++++++++++ manifest.toml | 11 +++++------ scripts/change_url | 8 ++++---- scripts/install | 29 ++++++----------------------- scripts/remove | 22 ++++------------------ scripts/restore | 42 +++++++++++------------------------------- scripts/upgrade | 37 ++++++++----------------------------- 8 files changed, 76 insertions(+), 112 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index e47f93a..c275c3a 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,4 +1,5 @@ -location / { +#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; +location __PATH__/ { proxy_pass http://127.0.0.1:__PORT__; proxy_redirect off; @@ -8,4 +9,6 @@ location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; + # Include SSOWAT user panel. + include conf.d/yunohost_panel.conf.inc; } diff --git a/conf/systemd.service b/conf/systemd.service index 9cfc992..a0c4a37 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -11,5 +11,39 @@ Type=simple WorkingDirectory=__INSTALL_DIR__ ExecStart=/usr/local/bin/pipenv run python3 __INSTALL_DIR__/.venv/bin/libretranslate --host 127.0.0.1 --port __PORT__ --load-only en,fr --frontend-language-target en +# Sandboxing options to harden security +# Depending on specificities of your service/app, you may need to tweak these +# .. but this should be a good baseline +# Details for these options: https://www.freedesktop.org/software/systemd/man/systemd.exec.html +NoNewPrivileges=yes +PrivateTmp=yes +PrivateDevices=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK +RestrictNamespaces=yes +RestrictRealtime=yes +DevicePolicy=closed +ProtectClock=yes +ProtectHostname=yes +ProtectProc=invisible +ProtectSystem=full +ProtectControlGroups=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +LockPersonality=yes +SystemCallArchitectures=native +SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap @cpu-emulation @privileged + +# Denying access to capabilities that should not be relevant for webapps +# Doc: https://man7.org/linux/man-pages/man7/capabilities.7.html +CapabilityBoundingSet=~CAP_RAWIO CAP_MKNOD +CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE +CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_PACCT +CapabilityBoundingSet=~CAP_LEASE CAP_LINUX_IMMUTABLE CAP_IPC_LOCK +CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_WAKE_ALARM +CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG +CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE +CapabilityBoundingSet=~CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW +CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYSLOG + [Install] WantedBy=multi-user.target diff --git a/manifest.toml b/manifest.toml index 089bdc0..aa31e17 100644 --- a/manifest.toml +++ b/manifest.toml @@ -2,12 +2,12 @@ packaging_format = 2 id = "libretranslate" name = "LibreTranslate" -description.en = "Open Source Machine Translation API, entirely self-hosted" -description.fr = "API de traduction automatique Open Source, entièrement auto-hébergée" +description.en = "Open Source Machine Translation API" +description.fr = "API de traduction automatique Open Source" version = "1.3.10~ynh1" -maintainers = ["John doe"] +maintainers = [""] [upstream] license = "AGPL-3.0" @@ -20,8 +20,8 @@ code = "https://github.com/LibreTranslate/LibreTranslate" yunohost = ">= 11.1.15" architectures = "all" multi_instance = true -ldap = "not_relevant" -sso = "not_relevant" +ldap = false +sso = true disk = "50M" ram.build = "50M" ram.runtime = "50M" @@ -46,7 +46,6 @@ ram.runtime = "50M" main.url = "/" [resources.ports] - main.default = 5000 [resources.apt] packages = "python3, python3-venv" diff --git a/scripts/change_url b/scripts/change_url index f5ff536..ae914ad 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -14,14 +14,14 @@ source /usr/share/yunohost/helpers #================================================= # STOP SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 +ynh_script_progression --message="Stopping a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" #================================================= # MODIFY URL IN NGINX CONF #================================================= -ynh_script_progression --message="Updating NGINX web server configuration..." --time --weight=1 +ynh_script_progression --message="Updating NGINX web server configuration..." --weight=1 ynh_change_url_nginx_config @@ -30,7 +30,7 @@ ynh_change_url_nginx_config #================================================= # START SYSTEMD SERVICE #================================================= -ynh_script_progression --message="Starting a systemd service..." --time --weight=1 +ynh_script_progression --message="Starting a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" @@ -38,4 +38,4 @@ ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$ap # END OF SCRIPT #================================================= -ynh_script_progression --message="Change of URL completed for $app" --time --last +ynh_script_progression --message="Change of URL completed for $app" --last diff --git a/scripts/install b/scripts/install index 593f1c2..e784878 100755 --- a/scripts/install +++ b/scripts/install @@ -18,14 +18,6 @@ chmod 750 "$install_dir" chmod -R o-rwx "$install_dir" chown -R $app:www-data "$install_dir" -#================================================= -# NGINX CONFIGURATION -#================================================= -ynh_script_progression --message="Configuring NGINX web server..." --weight=1 - -# Create a dedicated NGINX config -ynh_add_nginx_config - #================================================= # SPECIFIC SETUP #================================================= @@ -41,29 +33,20 @@ pushd $install_dir popd #================================================= -# SETUP SYSTEMD +# SYSTEM CONFIGURATION #================================================= -ynh_script_progression --message="Configuring a systemd service..." --weight=1 +ynh_script_progression --message="Adding system configurations related to $app..." --weight=5 + +# Create a dedicated NGINX config +ynh_add_nginx_config # Create a dedicated systemd config ynh_add_systemd_config -#================================================= -# GENERIC FINALIZATION -#================================================= -# SETUP LOGROTATE -#================================================= -ynh_script_progression --message="Configuring log rotation..." --weight=1 - # Use logrotate to manage application logfile(s) ynh_use_logrotate -#================================================= -# INTEGRATE SERVICE IN YUNOHOST -#================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 - -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" +yunohost service add $app --description="Machine Translation API" --log="/var/log/$app/$app.log" #================================================= # START SYSTEMD SERVICE diff --git a/scripts/remove b/scripts/remove index 9183bee..a97ceeb 100755 --- a/scripts/remove +++ b/scripts/remove @@ -10,39 +10,25 @@ source _common.sh source /usr/share/yunohost/helpers #================================================= -# STANDARD REMOVE +# REMOVE SYSTEM CONFIGURATIONS #================================================= -# REMOVE SERVICE INTEGRATION IN YUNOHOST +# REMOVE SYSTEMD SERVICE #================================================= +ynh_script_progression --message="Removing system configurations related to $app..." --weight=5 # Remove the service from the list of services known by YunoHost (added from `yunohost service add`) if ynh_exec_warn_less yunohost service status $app >/dev/null then - ynh_script_progression --message="Removing $app service integration..." --weight=2 + ynh_script_progression --message="Removing $app service integration..." --weight=1 yunohost service remove $app fi -#================================================= -# STOP AND REMOVE SERVICE -#================================================= -ynh_script_progression --message="Stopping and removing the systemd service..." --weight=1 - # Remove the dedicated systemd config ynh_remove_systemd_config -#================================================= -# REMOVE NGINX CONFIGURATION -#================================================= -ynh_script_progression --message="Removing NGINX web server configuration..." --weight=1 - # Remove the dedicated NGINX config ynh_remove_nginx_config -#================================================= -# REMOVE LOGROTATE CONFIGURATION -#================================================= -ynh_script_progression --message="Removing logrotate configuration..." --weight=1 - # Remove the app-specific logrotate config ynh_remove_logrotate diff --git a/scripts/restore b/scripts/restore index c3271d1..d2b5d13 100755 --- a/scripts/restore +++ b/scripts/restore @@ -10,15 +10,6 @@ source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -#================================================= -# STANDARD RESTORATION STEPS -#================================================= -# RESTORE THE NGINX CONFIGURATION -#================================================= -ynh_script_progression --message="Restoring the NGINX configuration..." --weight=1 - -ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" - #================================================= # RESTORE THE APP MAIN DIR #================================================= @@ -31,40 +22,29 @@ chmod -R o-rwx "$install_dir" chown -R $app:www-data "$install_dir" #================================================= -# RESTORE SYSTEMD +# RESTORE SYSTEM CONFIGURATIONS #================================================= -ynh_script_progression --message="Restoring the systemd configuration..." --weight=1 +# RESTORE THE PHP-FPM CONFIGURATION +#================================================= +ynh_script_progression --message="Restoring system configurations related to $app..." --weight=5 + +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" ynh_restore_file --origin_path="/etc/systemd/system/$app.service" systemctl enable $app.service --quiet -#================================================= -# INTEGRATE SERVICE IN YUNOHOST -#================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 - -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" - -#================================================= -# START SYSTEMD SERVICE -#================================================= -ynh_script_progression --message="Starting a systemd service..." --weight=1 - -ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" - -#================================================= -# RESTORE THE LOGROTATE CONFIGURATION -#================================================= -ynh_script_progression --message="Restoring the logrotate configuration..." --weight=1 +yunohost service add $app --description="Machine Translation API" --log="/var/log/$app/$app.log" ynh_restore_file --origin_path="/etc/logrotate.d/$app" #================================================= # GENERIC FINALIZATION #================================================= -# RELOAD NGINX AND PHP-FPM +# RELOAD NGINX AND PHP-FPM OR THE APP SERVICE #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --weight=1 +ynh_script_progression --message="Reloading NGINX web server and $app's service..." --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" ynh_systemd_action --service_name=nginx --action=reload diff --git a/scripts/upgrade b/scripts/upgrade index 1d12878..9ef093e 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -15,7 +15,6 @@ source /usr/share/yunohost/helpers upgrade_type=$(ynh_check_app_version_changed) - #================================================= # STANDARD UPGRADE STEPS #================================================= @@ -34,53 +33,33 @@ chmod 750 "$install_dir" chmod -R o-rwx "$install_dir" chown -R $app:www-data "$install_dir" -#================================================= -# NGINX CONFIGURATION -#================================================= -ynh_script_progression --message="Upgrading NGINX web server configuration..." --weight=1 - -# Create a dedicated NGINX config -ynh_add_nginx_config - #================================================= # SPECIFIC SETUP #================================================= -ynh_script_progression --message="Installing dependencies..." --weight=2 +ynh_script_progression --message="Installing LibreTranslate..." --weight=2 ynh_exec_warn_less python3 -m pip install pipenv - -ynh_script_progression --message="Installing LibreTranslate..." --weight=2 pushd $install_dir mkdir -p .venv PIPENV_VENV_IN_PROJECT="enabled" PIPENV_SKIP_LOCK=true ynh_exec_warn_less python3 -m pipenv install libretranslate==$libretranslate_version 2>&1 popd +#================================================= +# REAPPLY SYSTEM CONFIGURATIONS +#================================================= +ynh_script_progression --message="Upgrading system configurations related to $app..." --weight=1 -#================================================= -# SETUP SYSTEMD -#================================================= -ynh_script_progression --message="Upgrading systemd configuration..." --weight=1 +# Create a dedicated NGINX config +ynh_add_nginx_config # Create a dedicated systemd config ynh_add_systemd_config -#================================================= -# GENERIC FINALIZATION -#================================================= -# SETUP LOGROTATE -#================================================= -ynh_script_progression --message="Upgrading logrotate configuration..." --weight=1 - # Use logrotate to manage app-specific logfile(s) ynh_use_logrotate --non-append -#================================================= -# INTEGRATE SERVICE IN YUNOHOST -#================================================= -ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 - -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" +yunohost service add $app --description="Machine Translation API" --log="/var/log/$app/$app.log" #================================================= # START SYSTEMD SERVICE From 0764f0fc4879e9a659e1665f76821f43755b3d91 Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Sun, 2 Apr 2023 08:25:39 +0000 Subject: [PATCH 36/39] Auto-update README --- README.md | 1 - README_fr.md | 1 - 2 files changed, 2 deletions(-) diff --git a/README.md b/README.md index 43514f3..df74d1e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,6 @@ Free and Open Source Machine Translation API, entirely self-hosted. Unlike other ## Screenshots ![Screenshot of LibreTranslate](./doc/screenshots/screenshot.png) -![Screenshot of LibreTranslate](./doc/screenshots/DESCRIPTION.md) ## Documentation and resources diff --git a/README_fr.md b/README_fr.md index 5dcfeb4..1aaf2da 100644 --- a/README_fr.md +++ b/README_fr.md @@ -26,7 +26,6 @@ Free and Open Source Machine Translation API, entirely self-hosted. Unlike other ## Captures d’écran ![Capture d’écran de LibreTranslate](./doc/screenshots/screenshot.png) -![Capture d’écran de LibreTranslate](./doc/screenshots/DESCRIPTION.md) ## Documentations et ressources From d3fe96c519a629628845a976877aed30159beac5 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sun, 2 Apr 2023 10:27:38 +0200 Subject: [PATCH 37/39] Update manifest.toml --- manifest.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.toml b/manifest.toml index aa31e17..f0d0336 100644 --- a/manifest.toml +++ b/manifest.toml @@ -23,7 +23,7 @@ multi_instance = true ldap = false sso = true disk = "50M" -ram.build = "50M" +ram.build = "1500M" ram.runtime = "50M" [install] From cd2783d3604641e4c2e5ff709ad67da8dd4a0095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?E=CC=81ric=20Gaspar?= <46165813+ericgaspar@users.noreply.github.com> Date: Sun, 2 Apr 2023 11:04:10 +0200 Subject: [PATCH 38/39] Update restore --- scripts/restore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/restore b/scripts/restore index d2b5d13..e279eed 100755 --- a/scripts/restore +++ b/scripts/restore @@ -28,6 +28,8 @@ chown -R $app:www-data "$install_dir" #================================================= ynh_script_progression --message="Restoring system configurations related to $app..." --weight=5 +ynh_exec_warn_less python3 -m pip install pipenv + ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" ynh_restore_file --origin_path="/etc/systemd/system/$app.service" From c44bc3ef267c275484d1c8b314d8289149499bda Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Sun, 2 Apr 2023 10:33:45 +0000 Subject: [PATCH 39/39] Auto-update README --- README.md | 1 - README_fr.md | 1 - 2 files changed, 2 deletions(-) diff --git a/README.md b/README.md index 43514f3..df74d1e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,6 @@ Free and Open Source Machine Translation API, entirely self-hosted. Unlike other ## Screenshots ![Screenshot of LibreTranslate](./doc/screenshots/screenshot.png) -![Screenshot of LibreTranslate](./doc/screenshots/DESCRIPTION.md) ## Documentation and resources diff --git a/README_fr.md b/README_fr.md index 5dcfeb4..1aaf2da 100644 --- a/README_fr.md +++ b/README_fr.md @@ -26,7 +26,6 @@ Free and Open Source Machine Translation API, entirely self-hosted. Unlike other ## Captures d’écran ![Capture d’écran de LibreTranslate](./doc/screenshots/screenshot.png) -![Capture d’écran de LibreTranslate](./doc/screenshots/DESCRIPTION.md) ## Documentations et ressources