From 6e62dbe808b0ae5adf00ae6d7fbf1ffedfdcc938 Mon Sep 17 00:00:00 2001 From: zoic21 <1536036+zoic21@users.noreply.github.com> Date: Mon, 15 Jun 2026 09:24:01 +0000 Subject: [PATCH 1/2] feat(update): check core branch validity and alert if missing Add update::getCoreBranchList() by extracting the inline branch/tag fetching logic from administration.php, and update::isCoreBranchValid() to verify the configured core branch (or tag) still exists on the repository. Custom providers, well-known stable branches and an unreachable remote list all return true to avoid false positives. Alert the user through both channels when the branch is gone: - a health check item in jeedom::health() - a message in the notification center from update::checkUpdate() Closes #3166 --- core/class/jeedom.class.php | 12 +++++++ core/class/update.class.php | 66 ++++++++++++++++++++++++++++++++++ desktop/php/administration.php | 20 +---------- 3 files changed, 79 insertions(+), 19 deletions(-) diff --git a/core/class/jeedom.class.php b/core/class/jeedom.class.php index 4fbe7170e3..c34a156be3 100644 --- a/core/class/jeedom.class.php +++ b/core/class/jeedom.class.php @@ -191,6 +191,18 @@ public static function health() { 'key' => 'uptodate' ); + if (config::byKey('core::repo::provider') == 'default') { + $branch = config::byKey('core::branch', 'core', 'master'); + $state = update::isCoreBranchValid(); + $return[] = array( + 'name' => __('Branche du core', __FILE__), + 'state' => $state, + 'result' => ($state) ? $branch : $branch . ' (' . __('introuvable', __FILE__) . ')', + 'comment' => ($state) ? '' : __("La branche configurée pour le core n'existe plus sur le dépôt. Allez dans Réglages -> Système -> Mises à jour / Réinitialisation pour sélectionner une branche valide.", __FILE__), + 'key' => 'core::branch' + ); + } + $state = (config::byKey('enableCron', 'core', 1, true) != 0) ? true : false; $return[] = array( 'name' => __('Cron actif', __FILE__), diff --git a/core/class/update.class.php b/core/class/update.class.php index ffbde4fb6f..757c6bd2e1 100644 --- a/core/class/update.class.php +++ b/core/class/update.class.php @@ -493,6 +493,67 @@ public static function getLastAvailableVersion() { return null; } + /** + * Retourne la liste des branches et tags disponibles pour le core sur le dépôt par défaut. + * Résultat mis en cache 24h (clé core::branch::default::list). + * @param bool $_refresh force le rafraichissement du cache + * @return array tableau contenant les clés 'branchs' et 'tags' + */ + public static function getCoreBranchList($_refresh = false) { + $lists = ($_refresh) ? array() : cache::byKey('core::branch::default::list')->getValue(array()); + if (!isset($lists['branchs']) || !is_array($lists['branchs'])) { + $request_http = new com_http('https://api.github.com/repos/jeedom/core/branches'); + $request_http->setHeader(array('User-agent: jeedom')); + try { + $lists['branchs'] = json_decode($request_http->exec(10, 1), true); + } catch (\Exception $e) { + } + cache::set('core::branch::default::list', $lists, 86400); + } + if (!isset($lists['tags']) || !is_array($lists['tags'])) { + $request_http = new com_http('https://api.github.com/repos/jeedom/core/tags'); + $request_http->setHeader(array('User-agent: jeedom')); + try { + $lists['tags'] = json_decode($request_http->exec(10, 1), true); + } catch (\Exception $e) { + } + cache::set('core::branch::default::list', $lists, 86400); + } + return $lists; + } + + /** + * Vérifie que la branche (ou le tag) configurée pour le core existe toujours sur le dépôt. + * Retourne true si la validité ne peut être déterminée (fournisseur custom, branche stable, ou liste distante indisponible). + * @return bool + */ + public static function isCoreBranchValid() { + if (config::byKey('core::repo::provider') != 'default') { + return true; + } + $branch = config::byKey('core::branch', 'core', 'master'); + if (in_array($branch, array('master', 'release', 'stable'))) { + return true; + } + $lists = self::getCoreBranchList(); + if (strpos($branch, 'tag::') === 0) { + $name = substr($branch, strlen('tag::')); + $remoteList = (isset($lists['tags']) && is_array($lists['tags'])) ? $lists['tags'] : array(); + } else { + $name = $branch; + $remoteList = (isset($lists['branchs']) && is_array($lists['branchs'])) ? $lists['branchs'] : array(); + } + if (count($remoteList) == 0) { + return true; + } + foreach ($remoteList as $item) { + if (is_array($item) && isset($item['name']) && $item['name'] == $name) { + return true; + } + } + return false; + } + public function checkUpdate() { if ($this->getConfiguration('doNotUpdate') == 1 && $this->getType() != 'core') { log::add(__CLASS__, 'alert', __('Vérification des mises à jour, mise à jour et réinstallation désactivées sur', __FILE__) . ' ' . $this->getLogicalId()); @@ -503,6 +564,11 @@ public function checkUpdate() { return; } if (config::byKey('core::repo::provider') == 'default') { + if (self::isCoreBranchValid()) { + message::removeAll('core', 'core::branch::invalid'); + } else { + message::add('core', __("La branche configurée pour le core n'existe plus sur le dépôt. Allez dans Réglages -> Système -> Mises à jour / Réinitialisation pour sélectionner une branche valide.", __FILE__), '', 'core::branch::invalid'); + } $this->setRemoteVersion(self::getLastAvailableVersion()); } else { $class = 'repo_' . config::byKey('core::repo::provider'); diff --git a/desktop/php/administration.php b/desktop/php/administration.php index f226834255..7b16039abb 100644 --- a/desktop/php/administration.php +++ b/desktop/php/administration.php @@ -1822,25 +1822,7 @@ getValue(array()); - if (!isset($lists['branchs']) || !is_array($lists['branchs'])) { - $request_http = new com_http('https://api.github.com/repos/jeedom/core/branches'); - $request_http->setHeader(array('User-agent: jeedom')); - try { - $lists['branchs'] = json_decode($request_http->exec(10, 1), true); - } catch (\Exception $e) { - } - cache::set('core::branch::default::list', $lists, 86400); - } - if (!isset($lists['tags']) || !is_array($lists['tags'])) { - $request_http = new com_http('https://api.github.com/repos/jeedom/core/tags'); - $request_http->setHeader(array('User-agent: jeedom')); - try { - $lists['tags'] = json_decode($request_http->exec(10, 1), true); - } catch (\Exception $e) { - } - cache::set('core::branch::default::list', $lists, 86400); - } + $lists = update::getCoreBranchList(); if (isset($lists['branchs']) && is_array($lists['branchs'])) { echo ''; foreach ($lists['branchs'] as $branch) { From 5649430ee0f8c63d54a1c09c9910568091f462ed Mon Sep 17 00:00:00 2001 From: zoic21 <1536036+zoic21@users.noreply.github.com> Date: Mon, 15 Jun 2026 11:37:27 +0000 Subject: [PATCH 2/2] refactor(update): address review on core branch validity check - translate the new PHPDoc blocks to English and fix their format - type-hint getCoreBranchList(bool $_refresh) - drop the master/release/stable special case and validate every branch against the remote list ('stable' was not a real branch anyway) - deduplicate the user message via update::getCoreBranchInvalidMessage(), reused by jeedom::health() and update::checkUpdate() - fix the message: point to Settings -> System -> Mises a jour/Market - rename the health key core::branch -> coreBranch for consistency --- core/class/jeedom.class.php | 4 ++-- core/class/update.class.php | 31 ++++++++++++++++++++----------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/core/class/jeedom.class.php b/core/class/jeedom.class.php index c34a156be3..8ea439baf5 100644 --- a/core/class/jeedom.class.php +++ b/core/class/jeedom.class.php @@ -198,8 +198,8 @@ public static function health() { 'name' => __('Branche du core', __FILE__), 'state' => $state, 'result' => ($state) ? $branch : $branch . ' (' . __('introuvable', __FILE__) . ')', - 'comment' => ($state) ? '' : __("La branche configurée pour le core n'existe plus sur le dépôt. Allez dans Réglages -> Système -> Mises à jour / Réinitialisation pour sélectionner une branche valide.", __FILE__), - 'key' => 'core::branch' + 'comment' => ($state) ? '' : update::getCoreBranchInvalidMessage(), + 'key' => 'coreBranch' ); } diff --git a/core/class/update.class.php b/core/class/update.class.php index 757c6bd2e1..cf182fcb88 100644 --- a/core/class/update.class.php +++ b/core/class/update.class.php @@ -494,12 +494,13 @@ public static function getLastAvailableVersion() { } /** - * Retourne la liste des branches et tags disponibles pour le core sur le dépôt par défaut. - * Résultat mis en cache 24h (clé core::branch::default::list). - * @param bool $_refresh force le rafraichissement du cache - * @return array tableau contenant les clés 'branchs' et 'tags' + * Get the list of branches and tags available for the core on the default repository. + * The result is cached for 24h (key core::branch::default::list). + * + * @param bool $_refresh Force a refresh of the cache + * @return array Array containing the 'branchs' and 'tags' keys */ - public static function getCoreBranchList($_refresh = false) { + public static function getCoreBranchList(bool $_refresh = false) { $lists = ($_refresh) ? array() : cache::byKey('core::branch::default::list')->getValue(array()); if (!isset($lists['branchs']) || !is_array($lists['branchs'])) { $request_http = new com_http('https://api.github.com/repos/jeedom/core/branches'); @@ -523,8 +524,10 @@ public static function getCoreBranchList($_refresh = false) { } /** - * Vérifie que la branche (ou le tag) configurée pour le core existe toujours sur le dépôt. - * Retourne true si la validité ne peut être déterminée (fournisseur custom, branche stable, ou liste distante indisponible). + * Check that the branch (or tag) configured for the core still exists on the repository. + * Returns true when validity cannot be determined (custom provider or remote list + * unavailable) to avoid false positives. + * * @return bool */ public static function isCoreBranchValid() { @@ -532,9 +535,6 @@ public static function isCoreBranchValid() { return true; } $branch = config::byKey('core::branch', 'core', 'master'); - if (in_array($branch, array('master', 'release', 'stable'))) { - return true; - } $lists = self::getCoreBranchList(); if (strpos($branch, 'tag::') === 0) { $name = substr($branch, strlen('tag::')); @@ -554,6 +554,15 @@ public static function isCoreBranchValid() { return false; } + /** + * User-facing message shown when the configured core branch no longer exists on the repository. + * + * @return string + */ + public static function getCoreBranchInvalidMessage() { + return __("La branche configurée pour le core n'existe plus sur le dépôt. Allez dans Réglages -> Système -> Mises à jour/Market pour sélectionner une branche valide.", __FILE__); + } + public function checkUpdate() { if ($this->getConfiguration('doNotUpdate') == 1 && $this->getType() != 'core') { log::add(__CLASS__, 'alert', __('Vérification des mises à jour, mise à jour et réinstallation désactivées sur', __FILE__) . ' ' . $this->getLogicalId()); @@ -567,7 +576,7 @@ public function checkUpdate() { if (self::isCoreBranchValid()) { message::removeAll('core', 'core::branch::invalid'); } else { - message::add('core', __("La branche configurée pour le core n'existe plus sur le dépôt. Allez dans Réglages -> Système -> Mises à jour / Réinitialisation pour sélectionner une branche valide.", __FILE__), '', 'core::branch::invalid'); + message::add('core', self::getCoreBranchInvalidMessage(), '', 'core::branch::invalid'); } $this->setRemoteVersion(self::getLastAvailableVersion()); } else {