From dd989551923ec3e7f05b3991fab91a6aca3c98d9 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Fri, 7 Aug 2026 03:22:26 -0400 Subject: [PATCH] [IMP] install: support Fedora, Debian, Ubuntu and Arch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a Fedora dependency installer, rewrites the Arch one on pacman rather than an AUR helper absent from cloud images, and repairs the Debian path: apt lock timeout, PostGIS best-effort, Ubuntu 26.04, Node 22. --- FR --- Ajoute un installeur de dépendances Fedora, réécrit celui d'Arch sur pacman plutôt qu'un assistant AUR absent des images cloud, et répare le chemin Debian : attente du verrou apt, PostGIS best-effort, Ubuntu 26.04, Node 22. Assisted-by: Claude Opus 4.8 Assisted-by: Claude Opus 5 --- script/install/install_arch_linux.sh | 158 +++++++++++++------ script/install/install_debian_dependency.sh | 96 +++++++---- script/install/install_dev.sh | 9 +- script/install/install_fedora_dependency.sh | 129 +++++++++++++++ script/install/install_locally.sh | 6 + script/manifest/update_manifest_local_dev.sh | 17 +- script/version/update_env_version.py | 79 +++++++++- 7 files changed, 410 insertions(+), 84 deletions(-) create mode 100755 script/install/install_fedora_dependency.sh diff --git a/script/install/install_arch_linux.sh b/script/install/install_arch_linux.sh index a350f96..3289b17 100755 --- a/script/install/install_arch_linux.sh +++ b/script/install/install_arch_linux.sh @@ -1,68 +1,126 @@ #!/usr/bin/env bash +# © 2021-2026 TechnoLibre (http://www.technolibre.ca) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +# +# Dépendances système ERPLibre pour Arch Linux (pacman). Réécrit pour les +# images cloud Arch : l'ancien script utilisait « yay » (helper AUR ABSENT +# d'une image cloud et qui refuse de tourner en root) et n'installait jamais +# « base-devel » -> pas de compilateur C -> échec de la compilation de Python +# par pyenv. On passe tout par pacman (dépôts officiels) ; l'AUR (wkhtmltopdf) +# est best-effort et ne bloque pas. -install_package() { - local package_name=$1 +. ./env_var.sh - # Check package is already installed - if pacman -Qs "$package_name" >/dev/null; then - echo "$package_name is already installed." - else - echo "Installation of package $package_name..." - yes | yay -S "$package_name" - fi -} +EL_USER=${USER} -# Odoo installation -install_package postgis -install_package postgresql -install_package mariadb -install_package libev -install_package wkhtmltopdf -install_package freetds +# pacman résilient : --needed saute ce qui est déjà là, --noconfirm en non +# interactif. +PAC="sudo pacman -S --needed --noconfirm" +# Mise à jour COMPLÈTE obligatoire : Arch est en rolling release et NE SUPPORTE +# PAS les mises à jour partielles. Sur une image cloud dont la glibc est +# ancienne, un « pacman -S » lie le binaire à une glibc plus +# récente que celle installée -> « /usr/bin/postgres: GLIBC_2.44 not found ». +# « -Syu » met à jour glibc (et tout le système) pour rester cohérent. +sudo pacman -Syu --noconfirm || true -echo "Need password to create symbolic link, create postgres user and install npm :" -sudo ln -fs /usr/lib/libldap.so /usr/lib/libldap_r.so +#-------------------------------------------------- +# Outils de compilation — CRITIQUE (build Python via pyenv, extensions Python) +# base-devel fournit gcc, make, patch, pkgconf, fakeroot, etc. +#-------------------------------------------------- +echo -e "\n---- Groupe base-devel (compilateur C, make…) ----" +${PAC} base-devel +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "pacman base-devel installation error." + exit 1 +fi +#-------------------------------------------------- +# Dépendances de build pyenv (compilation de CPython) + outils de base +#-------------------------------------------------- +echo -e "\n---- Dépendances pyenv (compilation Python) + outils ----" +${PAC} git wget curl openssl zlib xz tk bzip2 readline sqlite libffi +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "pacman pyenv dependencies installation error." + exit 1 +fi + +#-------------------------------------------------- +# PostgreSQL (+ PostGIS) — Arch n'initialise pas le cluster automatiquement +#-------------------------------------------------- +echo -e "\n---- Install PostgreSQL Server ----" +${PAC} postgresql +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "pacman postgresql installation error." + exit 1 +fi +# Initialisation du cluster (chemin Arch : /var/lib/postgres/data). +if [ ! -f /var/lib/postgres/data/PG_VERSION ]; then + echo -e "\n---- Initialisation du cluster PostgreSQL ----" + sudo -u postgres initdb --locale=C.UTF-8 --encoding=UTF8 \ + -D /var/lib/postgres/data || true +fi +sudo systemctl enable --now postgresql 2>/dev/null || true +# PostGIS : optionnel (géospatial), ne bloque pas. +${PAC} postgis || echo "PostGIS non installé (optionnel)." + +echo -e "\n---- Creating the ERPLibre PostgreSQL User ----" sudo su - postgres -c "createuser -s ${EL_USER}" 2>/dev/null || true -echo -e "\n---- Update NPM ----" -install_package npm +#-------------------------------------------------- +# Dépendances Odoo / ERPLibre (extensions Python, bindings) +#-------------------------------------------------- +echo -e "\n---- Installing arch dependency ----" +# best-effort paquet par paquet : pacman refuse TOUTE la transaction si UN +# seul nom est inconnu (pas de --skip-unavailable). Ces deps ne sont pas +# critiques pour le build Python -> on ne bloque pas sur un nom absent. +for _pkg in libxslt libzip libldap libsasl cmake parallel swig portaudio \ + cups xmlsec freetds libev mariadb-libs shfmt; do + ${PAC} "${_pkg}" || echo " ${_pkg} : non installé (optionnel), on continue." +done +# libldap_r : Odoo/python-ldap cherche parfois libldap_r.so (supprimé des +# versions récentes d'OpenLDAP) -> lien vers libldap.so. +sudo ln -fs /usr/lib/libldap.so /usr/lib/libldap_r.so 2>/dev/null || true -sudo npm install npm@latest -g +#-------------------------------------------------- +# Node.js + npm (rtlcss, less) +#-------------------------------------------------- +echo -e "\n---- Installing nodeJS NPM and rtlcss ----" +${PAC} nodejs npm retVal=$? if [[ $retVal -ne 0 ]]; then - echo "npm install npm lastest installation error." - exit 1 -fi -sudo npm install -g rtlcss -retVal=$? -if [[ $retVal -ne 0 ]]; then - echo "npm install rtlcss installation error." - exit 1 -fi -sudo npm install -g less -retVal=$? -if [[ $retVal -ne 0 ]]; then - echo "npm install less installation error." + echo "pacman nodejs installation error." exit 1 fi +sudo npm install -g rtlcss less || echo "npm rtlcss/less: erreur (optionnel)." echo -e "\n---- Test tool ----" -npm install -retVal=$? -if [[ $retVal -ne 0 ]]; then - echo "npm install prettier + plugin-xml installation error." - exit 1 +npm install || echo "npm install (prettier/plugin-xml): erreur (optionnel)." + +# Pour erplibre_devops. +${PAC} sshpass || echo "sshpass non installé (optionnel)." + +#-------------------------------------------------- +# nginx (optionnel) +#-------------------------------------------------- +if [ "${EL_INSTALL_NGINX}" = "True" ]; then + echo -e "\n---- Installing nginx ----" + ${PAC} nginx || echo "nginx: erreur (optionnel)." fi -# TODO install nginx - -# ERPLibre installation -install_package cmake -install_package parallel -install_package tk -install_package shfmt - -# For erplibre_devops -install_package sshpass +#-------------------------------------------------- +# wkhtmltopdf (optionnel) — uniquement dans l'AUR sur Arch (pas de paquet +# officiel). Sur une image cloud sans helper AUR, on saute proprement. +#-------------------------------------------------- +if [ "${EL_INSTALL_WKHTMLTOPDF}" = "True" ]; then + if ! command -v wkhtmltopdf >/dev/null 2>&1; then + echo "wkhtmltopdf : disponible seulement via l'AUR sur Arch, ignoré" + echo " (installez-le manuellement avec un helper AUR si nécessaire)." + else + echo -e "\n---- Already installed wkhtml ----" + fi +fi +echo -e "\n---- Arch Linux dependency installation done ----" diff --git a/script/install/install_debian_dependency.sh b/script/install/install_debian_dependency.sh index adbc2d5..cc56946 100755 --- a/script/install/install_debian_dependency.sh +++ b/script/install/install_debian_dependency.sh @@ -5,6 +5,11 @@ EL_USER=${USER} #EL_INSTALL_WKHTMLTOPDF="True" +# apt-get qui ATTEND le verrou (jusqu'à 10 min) : sur une image cloud fraîche, +# cloud-init / unattended-upgrades tiennent souvent le verrou apt au 1er boot +# (« Could not get lock » -> échec de l'install). DPkg::Lock::Timeout patiente. +APT_GET="sudo apt-get -o DPkg::Lock::Timeout=600" + ## ### WKHTMLTOPDF download links ## === Ubuntu Focal x64 === (for other distributions please replace these two links, @@ -15,22 +20,30 @@ UBUNTU_VERSION=$(lsb_release -rs) DEBIAN_VERSION=$(lsb_release -cs) OS=$(lsb_release -si) if [[ "${OS}" == "Ubuntu" ]]; then - if [ "25.10" == "${UBUNTU_VERSION}" ] || [ "25.04" == "${UBUNTU_VERSION}" ] || [ "24.04" == "${UBUNTU_VERSION}" ] || [ "24.10" == "${UBUNTU_VERSION}" ] || [ "23.10" == "${UBUNTU_VERSION}" ] || [ "23.04" == "${UBUNTU_VERSION}" ] || [ "22.10" == "${UBUNTU_VERSION}" ] || [ "22.04" == "${UBUNTU_VERSION}" ]; then - WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb - elif [ "20.04" == "${UBUNTU_VERSION}" ]; then + if [ "20.04" == "${UBUNTU_VERSION}" ]; then WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb elif [ "18.04" == "${UBUNTU_VERSION}" ]; then WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.bionic_amd64.deb + else + # 22.04+ (jusqu'à 26.04 et au-delà) : wkhtmltopdf ne publie pas de build + # par version ; le .deb « jammy » est le plus récent et fonctionne. Un + # « else » (au lieu d'énumérer les versions) évite une URL VIDE sur une + # version récente (26.04) -> gdebi appelé sans fichier -> échec. + WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb fi elif [[ "${OS}" == "Linuxmint" ]]; then if [ "22.3" == "${UBUNTU_VERSION}" ]; then WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb fi elif [[ "${OS}" == "Debian" ]]; then - if [ "bookworm" == "${DEBIAN_VERSION}" ]; then - WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_amd64.deb - else + if [ "bullseye" == "${DEBIAN_VERSION}" ]; then WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bullseye_amd64.deb + else + # bookworm (12), trixie (13) et au-delà : wkhtmltopdf ne publie pas de + # build au-delà de « bookworm » -> on prend bookworm (le plus récent). + # Le build « bullseye » (Debian 11) échouait à s'installer sur trixie + # (gdebi : dépendances incompatibles). + WKHTMLTOX_X64=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_amd64.deb fi elif [[ "${OS}" == *"Ubuntu"* ]]; then echo "Your version of Ubuntu is not supported, only support 18.04, 20.04 and 22.04" @@ -55,25 +68,30 @@ echo -e "\n---- Update Server ----" if [ "18.04" == "${UBUNTU_VERSION}" ]; then # add-apt-repository can install add-apt-repository Ubuntu 18.x - sudo apt-get install software-properties-common curl -y + ${APT_GET} install software-properties-common curl -y # universe package is for Ubuntu 18.x sudo add-apt-repository universe # libpng12-0 dependency for wkhtmltopdf sudo add-apt-repository "deb http://mirrors.kernel.org/ubuntu/ xenial main" - sudo apt-get update - sudo apt-get upgrade -y + ${APT_GET} update + ${APT_GET} upgrade -y fi #-------------------------------------------------- # Install PostgreSQL Server #-------------------------------------------------- echo -e "\n---- Install PostgreSQL Server ----" -sudo apt-get install postgresql libpq-dev postgis -y +${APT_GET} install postgresql postgresql-contrib libpq-dev -y retVal=$? if [[ $retVal -ne 0 ]]; then echo "apt-get install postgresql installation error." exit 1 fi +# PostGIS : optionnel (géospatial). Le nom du paquet « postgis » n'existe pas +# sur toutes les versions (Ubuntu 24.04) -> best-effort, ne bloque pas. +${APT_GET} install postgis -y \ + || ${APT_GET} install postgresql-postgis -y \ + || echo "PostGIS non installé (optionnel)." echo -e "\n---- Creating the ERPLibre PostgreSQL User ----" sudo su - postgres -c "createuser -s ${EL_USER}" 2>/dev/null || true @@ -82,20 +100,27 @@ sudo su - postgres -c "createuser -s ${EL_USER}" 2>/dev/null || true # Install Dependencies #-------------------------------------------------- echo -e "\n--- Installing debian dependency --" -sudo apt-get install git build-essential wget libxslt-dev libzip-dev libldap2-dev libsasl2-dev gdebi-core libffi-dev libbz2-dev parallel pysassc swig cmake portaudio19-dev libcups2-dev shfmt xmlsec1 -y +${APT_GET} install git build-essential wget libxslt-dev libzip-dev libldap2-dev libsasl2-dev gdebi-core libffi-dev libbz2-dev parallel pysassc swig cmake portaudio19-dev libcups2-dev xmlsec1 -y retVal=$? if [[ $retVal -ne 0 ]]; then echo "apt-get debian tool installation error." exit 1 fi -sudo apt-get install libmariadbd-dev freetds-dev -y +# shfmt : ABSENT des dépôts Ubuntu < 22.04. Il était dans le lot critique +# ci-dessus -> un seul paquet introuvable faisait échouer TOUT l'apt-get +# (donc pas de build-essential/gcc -> pyenv ne pouvait plus compiler Python). +# C'est un simple formateur shell (dev), non requis pour exécuter ERPLibre : +# on l'installe SÉPARÉMENT et en best-effort (jamais fatal). +${APT_GET} install shfmt -y \ + || echo "shfmt indisponible dans les dépôts (Ubuntu < 22.04 ?) — ignoré." +${APT_GET} install libmariadbd-dev freetds-dev -y retVal=$? if [[ $retVal -ne 0 ]]; then echo "apt-get libmariadb installation error." exit 1 fi if [ "18.04" == "${UBUNTU_VERSION}" ]; then - sudo apt-get install libpng12-0 -y + ${APT_GET} install libpng12-0 -y retVal=$? if [[ $retVal -ne 0 ]]; then echo "apt-get libpng installation error." @@ -103,14 +128,14 @@ if [ "18.04" == "${UBUNTU_VERSION}" ]; then fi fi # Dependencies for pyenv -sudo apt-get install make libssl-dev zlib1g-dev libreadline-dev libsqlite3-dev curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblzma-dev -y +${APT_GET} install make libssl-dev zlib1g-dev libreadline-dev libsqlite3-dev curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblzma-dev -y retVal=$? if [[ $retVal -ne 0 ]]; then echo "apt-get pyenv dependencies installation error." exit 1 fi # Dependencies for selenium -sudo apt-get install libcairo2-dev python3-dev pkg-config libxt-dev libgirepository1.0-dev -y +${APT_GET} install libcairo2-dev python3-dev pkg-config libxt-dev libgirepository1.0-dev -y retVal=$? if [[ $retVal -ne 0 ]]; then echo "apt-get selenium dependencies installation error." @@ -118,8 +143,8 @@ if [[ $retVal -ne 0 ]]; then fi echo -e "\n---- Installing nodeJS NPM and rtlcss for LTR support ----" -sudo apt-get update -sudo apt-get install -y ca-certificates curl gnupg +${APT_GET} update +${APT_GET} install -y ca-certificates curl gnupg sudo mkdir -p /etc/apt/keyrings curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg @@ -132,8 +157,8 @@ else fi echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list -sudo apt-get update -sudo apt-get install nodejs -y +${APT_GET} update +${APT_GET} install nodejs -y sudo npm install npm@latest -g retVal=$? @@ -177,21 +202,36 @@ fi #-------------------------------------------------- # Install Wkhtmltopdf if needed #-------------------------------------------------- -if [ ${EL_INSTALL_WKHTMLTOPDF} = "True" ]; then +if [ "$(uname -m)" != "x86_64" ]; then + # WKHTMLTOX_X64 pointe vers un .deb amd64 : sur toute autre architecture + # (s390x, arm64/aarch64…) gdebi échouerait. On saute proprement plutôt que + # d'avorter tout l'install (wkhtmltopdf est optionnel). + echo "wkhtmltopdf : pas de build pour $(uname -m), ignoré (optionnel)." +elif [ ${EL_INSTALL_WKHTMLTOPDF} = "True" ]; then echo -e "\n---- Installing wkhtml ----" INSTALLED=$(dpkg -s wkhtmltox | grep installed) if [ "" == "${INSTALLED}" ]; then echo -e "\n---- Install wkhtml and place shortcuts on correct place ----" _url=${WKHTMLTOX_X64} - sudo wget ${_url} - sudo gdebi --n $(basename ${_url}) - retVal=$? - if [[ $retVal -ne 0 ]]; then - echo "gdebi install wkhtmltopdf installation error." - exit 1 + if [ -z "${_url}" ]; then + # Aucune URL (version non mappée) : wkhtmltopdf est OPTIONNEL, on saute + # proprement plutôt que d'appeler gdebi sans fichier (« Usage: gdebi »). + echo "wkhtmltopdf : aucune URL pour cette version, ignoré (optionnel)." + else + sudo wget ${_url} + sudo gdebi --n $(basename ${_url}) + retVal=$? + if [[ $retVal -ne 0 ]]; then + # wkhtmltopdf est OPTIONNEL (rapports PDF). NON bloquant : sur Debian + # 13 (trixie) le .deb dépendait de libssl1.1 (absent) et « exit 1 » + # faisait échouer TOUT install_os -> Odoo jamais installé. On avertit + # et on continue (comme Arch qui poursuit sans wkhtmltopdf). + echo "wkhtmltopdf : installation échouée, ignoré (optionnel — pas de PDF)." + else + sudo ln -fs /usr/local/bin/wkhtmltopdf /usr/bin + sudo ln -fs /usr/local/bin/wkhtmltoimage /usr/bin + fi fi - sudo ln -fs /usr/local/bin/wkhtmltopdf /usr/bin - sudo ln -fs /usr/local/bin/wkhtmltoimage /usr/bin else echo -e "\n---- Already installed wkhtml ----" fi diff --git a/script/install/install_dev.sh b/script/install/install_dev.sh index 2220a12..95cc0a3 100755 --- a/script/install/install_dev.sh +++ b/script/install/install_dev.sh @@ -3,11 +3,11 @@ if [[ "${OSTYPE}" == "linux-gnu" ]]; then source /etc/os-release if [[ "${ID}" == "ubuntu" ]]; then - if [[ "${VERSION_ID}" == "18.04" || "${VERSION_ID}" == "20.04" || "${VERSION_ID}" == "22.04" || "${VERSION_ID}" == "22.10" || "${VERSION_ID}" == "23.04" || "${VERSION_ID}" == "23.10" || "${VERSION_ID}" == "24.04" || "${VERSION_ID}" == "25.04" || "${VERSION_ID}" == "25.10" ]]; then + if [[ "${VERSION_ID}" == "18.04" || "${VERSION_ID}" == "20.04" || "${VERSION_ID}" == "22.04" || "${VERSION_ID}" == "22.10" || "${VERSION_ID}" == "23.04" || "${VERSION_ID}" == "23.10" || "${VERSION_ID}" == "24.04" || "${VERSION_ID}" == "25.04" || "${VERSION_ID}" == "25.10" || "${VERSION_ID}" == "26.04" ]]; then echo "\n---- linux-gnu installation process started ----" ./script/install/install_debian_dependency.sh else - echo "Your version is not supported, only support 18.04, 20.04 and 22.04 - 24.04, 25.04, 25.10 : ${VERSION_ID}" + echo "Your version is not supported, only support 18.04, 20.04 and 22.04 - 24.04, 25.04, 25.10, 26.04 : ${VERSION_ID}" fi elif [[ "${ID}" == "linuxmint" ]]; then if [[ "${VERSION_ID}" == "22.3" ]]; then @@ -20,9 +20,12 @@ if [[ "${OSTYPE}" == "linux-gnu" ]]; then ./script/install/install_debian_dependency.sh elif [[ "${ID}" == "arch" ]]; then ./script/install/install_arch_linux.sh + elif [[ "${ID}" == "fedora" || "${ID_LIKE}" == *"fedora"* || "${ID_LIKE}" == *"rhel"* ]]; then + echo "\n---- Fedora installation process started ----" + ./script/install/install_fedora_dependency.sh else ./script/install/install_debian_dependency.sh - echo "Your Linux system is not supported, only support Ubuntu 18.04 or Ubuntu 20.04 or Ubuntu 22.04 - Ubuntu 23.10 - Ubuntu 24.04, Ubuntu 25.04, Ubuntu 25.10 ." + echo "Your Linux system is not supported, only support Ubuntu 18.04 or Ubuntu 20.04 or Ubuntu 22.04 - Ubuntu 23.10 - Ubuntu 24.04, Ubuntu 25.04, Ubuntu 25.10, Debian, Fedora, Arch." fi elif [[ "${OSTYPE}" == "darwin"* ]]; then echo "\n---- Darwin installation process started ----" diff --git a/script/install/install_fedora_dependency.sh b/script/install/install_fedora_dependency.sh new file mode 100755 index 0000000..7fbafa7 --- /dev/null +++ b/script/install/install_fedora_dependency.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash +# © 2021-2026 TechnoLibre (http://www.technolibre.ca) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +# +# Dépendances système ERPLibre pour Fedora (dnf). Équivalent Fedora de +# install_debian_dependency.sh. « --skip-unavailable » tolère un nom de paquet +# absent (dnf5) au lieu d'échouer sur tout le lot. + +. ./env_var.sh + +EL_USER=${USER} + +# dnf résilient : rafraîchit le cache (évite « checksum doesn't match » / +# signature après un cache périmé) et saute les paquets introuvables. +DNF="sudo dnf install -y --refresh --skip-unavailable" + +#-------------------------------------------------- +# Outils de compilation (build Python via pyenv, extensions Python) +#-------------------------------------------------- +echo -e "\n---- Groupe outils de développement ----" +# Groupes par ID (le nom affiché « C Development Tools... » n'est pas matché). +sudo dnf group install -y --skip-unavailable development-tools c-development \ + || sudo dnf install -y gcc gcc-c++ make automake patch + +#-------------------------------------------------- +# PostgreSQL +#-------------------------------------------------- +echo -e "\n---- Install PostgreSQL Server ----" +${DNF} postgresql-server postgresql-contrib libpq-devel +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "dnf install postgresql installation error." + exit 1 +fi +# Initialisation du cluster (Fedora ne le fait pas automatiquement). +if [ ! -f /var/lib/pgsql/data/PG_VERSION ]; then + echo -e "\n---- Initialisation du cluster PostgreSQL ----" + # Nettoie un init partiel et FORCE une locale valide : les images cloud + # Fedora n'ont pas de LANG défini -> « initdb: invalid locale settings ». + sudo rm -rf /var/lib/pgsql/data + sudo PGSETUP_INITDB_OPTIONS="--locale=C.UTF-8 --encoding=UTF8" \ + postgresql-setup --initdb || true +fi +sudo systemctl enable --now postgresql 2>/dev/null || true +# PostGIS : optionnel (géospatial), ne bloque pas. +${DNF} postgis || echo "PostGIS non installé (optionnel)." + +echo -e "\n---- Creating the ERPLibre PostgreSQL User ----" +sudo su - postgres -c "createuser -s ${EL_USER}" 2>/dev/null || true + +#-------------------------------------------------- +# Dépendances de build (extensions Python, Odoo) +#-------------------------------------------------- +echo -e "\n--- Installing fedora dependency --" +# git-daemon : sur Fedora la sous-commande « git daemon » N'EST PAS dans le +# paquet « git » de base (contrairement à Debian/Ubuntu/Arch). ERPLibre sert +# son manifeste via un « git daemon » local (git://127.0.0.1:9418/) pendant +# « repo sync » -> sans ce paquet : « git: 'daemon' is not a git command » +# puis « Connection refused » et l'échec de la synchro du manifeste. +${DNF} \ + git git-daemon wget libxslt-devel libzip-devel openldap-devel \ + cyrus-sasl-devel \ + libffi-devel bzip2-devel parallel swig cmake portaudio-devel \ + cups-devel xmlsec1 xmlsec1-openssl mariadb-connector-c-devel freetds-devel +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "dnf fedora tool installation error." + exit 1 +fi + +# Dépendances de build pour pyenv (compilation de CPython) — CRITIQUE. +echo -e "\n---- Dépendances pyenv (compilation Python) ----" +${DNF} \ + make gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel \ + openssl-devel tk-devel libffi-devel xz-devel patch findutils +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "dnf pyenv dependencies installation error." + exit 1 +fi + +# Dépendances selenium / bindings. +${DNF} \ + cairo-devel python3-devel pkgconf-pkg-config gobject-introspection-devel \ + libXt-devel || echo "Dépendances selenium partielles (optionnel)." + +#-------------------------------------------------- +# Node.js + npm (rtlcss, less) +#-------------------------------------------------- +echo -e "\n---- Installing nodeJS NPM and rtlcss ----" +${DNF} nodejs npm +retVal=$? +if [[ $retVal -ne 0 ]]; then + echo "dnf nodejs installation error." + exit 1 +fi +sudo npm install -g rtlcss less || echo "npm rtlcss/less: erreur (optionnel)." + +echo -e "\n---- Test tool ----" +npm install || echo "npm install (prettier/plugin-xml): erreur (optionnel)." +sudo ln -fs /usr/local/bin/lessc /usr/bin/lessc 2>/dev/null || true + +#-------------------------------------------------- +# nginx (optionnel) +#-------------------------------------------------- +if [ "${EL_INSTALL_NGINX}" = "True" ]; then + echo -e "\n---- Installing nginx ----" + ${DNF} nginx || echo "nginx: erreur (optionnel)." +fi + +#-------------------------------------------------- +# wkhtmltopdf (optionnel) — paquet RPM officiel wkhtmltopdf +#-------------------------------------------------- +if [ "${EL_INSTALL_WKHTMLTOPDF}" = "True" ]; then + if ! command -v wkhtmltopdf >/dev/null 2>&1; then + echo -e "\n---- Installing wkhtml (best-effort) ----" + # wkhtmltopdf ne publie plus de build « fedora-* » ; le RPM AlmaLinux 9 + # (EL9) est compatible Fedora (testé sur F42 : dnf résout les deps). + # Repli AlmaLinux 8 au besoin. + _base="https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3" + sudo dnf install -y "${_base}/wkhtmltox-0.12.6.1-3.almalinux9.x86_64.rpm" \ + || sudo dnf install -y "${_base}/wkhtmltox-0.12.6.1-3.almalinux8.x86_64.rpm" \ + || echo "wkhtmltopdf non installé (optionnel)." + else + echo -e "\n---- Already installed wkhtml ----" + fi +fi + +echo -e "\n---- Fedora dependency installation done ----" diff --git a/script/install/install_locally.sh b/script/install/install_locally.sh index 331701c..350b86a 100755 --- a/script/install/install_locally.sh +++ b/script/install/install_locally.sh @@ -96,6 +96,12 @@ if [[ "${EL_PHASE}" != "setup" ]]; then retVal=$? if [[ $retVal -ne 0 ]]; then echo "Poetry installation error with status ${retVal}" + # « -q » masque la CAUSE. On rejoue en « -vvv » (debug) car c'est + # le SEUL niveau où Poetry affiche la sortie des sous-processus + # (git clone/checkout, build pip) — donc l'erreur réelle d'une + # dépendance VCS/build. Capturé dans le log pour diagnostic. + echo "---- Poetry: rejeu -vvv pour diagnostic ----" + poetry install --no-root -vvv 2>&1 || true exit 1 fi fi diff --git a/script/manifest/update_manifest_local_dev.sh b/script/manifest/update_manifest_local_dev.sh index abdc5c3..122978f 100755 --- a/script/manifest/update_manifest_local_dev.sh +++ b/script/manifest/update_manifest_local_dev.sh @@ -12,9 +12,22 @@ fi #EL_MANIFEST_PROD="./default.xml" #EL_MANIFEST_DEV="./manifest/default.dev.xml" -# Update git-repo +# Update git-repo : local git daemon serving the repo over git://127.0.0.1:9418. +# Kill any leftover daemon from a previous (interrupted) run first: otherwise the +# stale server keeps port 9418, the new daemon fails to bind ("Address already in +# use"), and the cleanup kill below fails on an already-dead PID -> script exit 1. +# Match on the stable arguments, not "git daemon": « git daemon » execs into +# « git-daemon » (hyphen, /usr/lib/git-core/git-daemon), so "git daemon" (space) +# never matches the actual running process. +if pkill -f "daemon --base-path=. --export-all" 2>/dev/null; then + sleep 1 # let the kernel release port 9418 before we rebind +fi + git daemon --base-path=. --export-all --reuseaddr --informative-errors ${DAEMON_VERBOSE} & DAEMON_PID=$! +# Always stop the daemon we started, whatever happens next (success or error), +# without ever failing the script if it is already gone. +trap 'kill "${DAEMON_PID}" 2>/dev/null || true' EXIT if [ -L "$EL_MANIFEST_DEV" ]; then MANIFEST_TARGET=$(readlink -f "$EL_MANIFEST_DEV") @@ -34,4 +47,4 @@ fi .venv.erplibre/bin/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --verify HEAD) -m ${MANIFEST_TARGET} "$@" .venv.erplibre/bin/repo sync -c -j "$JOBS" ${REPO_VERBOSE} -m ${MANIFEST_TARGET} -kill ${DAEMON_PID} +# Daemon cleanup handled by the EXIT trap above (tolerant of an already-dead PID). diff --git a/script/version/update_env_version.py b/script/version/update_env_version.py index ca265b1..def0085 100755 --- a/script/version/update_env_version.py +++ b/script/version/update_env_version.py @@ -14,6 +14,10 @@ import time # erplibre_state is in the same directory; import lazily to avoid hard failure # when the script runs outside the project root (e.g. during bare install). +# Two import styles are needed: when this file is imported as a package module +# the repo root is on sys.path (package import works); when it is executed +# directly as ./script/version/update_env_version.py, sys.path[0] is +# script/version/ and only the sibling import resolves. try: from script.version.erplibre_state import ( get_version_extra, @@ -25,7 +29,18 @@ try: _STATE_AVAILABLE = True except ImportError: - _STATE_AVAILABLE = False + try: + from erplibre_state import ( + get_version_extra, + get_version_installed, + print_state, + set_version_installed, + set_version_switched, + ) + + _STATE_AVAILABLE = True + except ImportError: + _STATE_AVAILABLE = False logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO")) @@ -546,6 +561,61 @@ class Update: self.execute_log.append("Extra modules (CybroOdoo)") return os.system("./script/manifest/update_manifest_local_dev.sh") + def add_extra_to_config_conf(self): + """Append the extra addons (CybroOdoo, ...) to config.conf addons_path. + + generate_config.sh rewrites config.conf from a fixed addons list that + does NOT include the extra modules, so this must run AFTER it (last + writer wins). The paths come from the source-of-truth extra manifest + (projects tagged with the "extra" group). Already-present paths are + skipped, so the call is idempotent.""" + import xml.etree.ElementTree as ET + + ver = self.new_version_odoo # e.g. "18.0" + manifest = os.path.join( + "manifest", f"git_manifest_extra_odoo{ver}.xml" + ) + config_path = "config.conf" + if not os.path.isfile(manifest) or not os.path.isfile(config_path): + _logger.warning( + "Cannot add extra modules to config.conf:" + f" missing {manifest} or {config_path}." + ) + return + home = os.getcwd() + prefix = f"odoo{ver}/addons/" + extra_paths = [] + for project in ET.parse(manifest).getroot().findall("project"): + groups = project.get("groups", "").split(",") + path = project.get("path", "") + if "extra" in groups and path.startswith(prefix): + extra_paths.append(os.path.join(home, path)) + if not extra_paths: + return + + with open(config_path, "r", encoding="utf-8") as f: + lines = f.readlines() + changed = False + for i, line in enumerate(lines): + if not line.startswith("addons_path"): + continue + value = line.rstrip("\n").split("=", 1)[1] if "=" in line else "" + existing = [p.strip() for p in value.split(",") if p.strip()] + missing = [p for p in extra_paths if p not in existing] + if missing: + lines[i] = "addons_path = " + ",".join(existing + missing) + "\n" + changed = True + break + if changed: + with open(config_path, "w", encoding="utf-8") as f: + f.writelines(lines) + _logger.info( + "Added extra addons to config.conf: " + + ", ".join(extra_paths) + ) + else: + _logger.info("Extra addons already present in config.conf.") + def install_system(self): self.execute_log.append(f"System installation") status = os.system("./script/install/install_dev.sh") @@ -779,6 +849,13 @@ def main(): ) os.system("./script/generate_config.sh") + # config.conf : generate_config.sh (ci-dessus) réécrit le fichier à partir + # d'une liste d'addons figée SANS les modules extra ; on ajoute donc les + # chemins extra APRÈS coup (dernier writer). Idempotent, sans effet si + # --with_extra n'est pas demandé. + if update.config.with_extra and exit_code == 0: + update.add_extra_to_config_conf() + return exit_code # TODO ignore this if installation fail