From b5c3cd8cb82e3f4a14bdace326e1603c1375a661 Mon Sep 17 00:00:00 2001 From: Etienne Trimaille Date: Mon, 19 Aug 2024 13:50:56 +0200 Subject: [PATCH] Take care of Feature Freeze versions on the LWC side --- lizmap/definitions/definitions.py | 1 + lizmap/server_lwc.py | 42 +++++++++++++++--- lizmap/test/data/version_info_19082024.json | 25 +++++++++++ lizmap/test/test_definitions.py | 5 ++- lizmap/test/test_pyplugin_installer.py | 9 +++- lizmap/test/test_version_info.py | 49 +++++++++++++++++++++ 6 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 lizmap/test/data/version_info_19082024.json diff --git a/lizmap/definitions/definitions.py b/lizmap/definitions/definitions.py index 8bf5d831..198e8f13 100755 --- a/lizmap/definitions/definitions.py +++ b/lizmap/definitions/definitions.py @@ -97,6 +97,7 @@ def find_from_metadata(cls, metadata: dict): class ReleaseStatus(Enum): Unknown = 'Unknown' Retired = 'Retired' + SecurityBugfixOnly = 'security_bugfix_only' Stable = 'Stable' ReleaseCandidate = 'ReleaseCandidate' Dev = 'Dev' diff --git a/lizmap/server_lwc.py b/lizmap/server_lwc.py index e097a4fc..a7d475ee 100755 --- a/lizmap/server_lwc.py +++ b/lizmap/server_lwc.py @@ -10,7 +10,7 @@ from enum import Enum from functools import partial from pathlib import Path -from typing import List, Optional, Tuple +from typing import List, Optional, Tuple, Union from qgis.core import ( Qgis, @@ -84,6 +84,14 @@ class Color(Enum): MAX_DAYS = 7 +def is_numeric(v: Union[str, int]) -> bool: + try: + int(v) + return True + except ValueError: + return False + + class ServerManager: """ Fetch the Lizmap server version for a list of server. """ @@ -913,7 +921,13 @@ def _messages_for_version( # But the online JSON public release might have nothing (because no public tag has been made) latest_release_version = json_version.get('latest_release_version') if latest_release_version: - latest_bugfix = int(latest_release_version.split('.')[2]) + bugfix = latest_release_version.split('.')[2] + if is_numeric(bugfix): + latest_bugfix = int(bugfix) + else: + # It will be a string :( + # Like 0-rc.4 + latest_bugfix = bugfix else: # So let's assume it's 0 latest_bugfix = 0 @@ -925,10 +939,14 @@ def _messages_for_version( # Upgrade because the branch is not maintained anymore messages.append(tr('Version {version} not maintained anymore').format(version=branch)) level = Qgis.Critical + elif status == ReleaseStatus.SecurityBugfixOnly: + # Upgrade because the branch is not maintained anymore + messages.append(tr('Version {version} not maintained anymore, only for security bugfix only').format(version=branch)) # Remember a version can be 3.4.2-pre + # Or 3.8.0-rc.4 items_bugfix = split_version[2].split('-') - is_pre_package = len(items_bugfix) > 1 + is_pre_package = len(items_bugfix) > 1 and len(split_version) == 3 bugfix = int(items_bugfix[0]) if json_version['latest_release_version'] != full_version or is_pre_package: @@ -938,7 +956,19 @@ def _messages_for_version( # We continue # return level, messages - if bugfix > latest_bugfix: + if not is_numeric(latest_bugfix): + from pyplugin_installer.version_compare import ( + compareVersions, + ) + if compareVersions(lizmap_version, json_version['latest_release_version']) == 2: + # Like comparing 3.8.0-rc.4 and 3.8.0-rc.3 + messages.append( + tr( + 'Not latest bugfix release, {version} is available' + ).format(version=json_version['latest_release_version'])) + level = Qgis.Warning + + if is_numeric(latest_bugfix) and bugfix > latest_bugfix: # Congratulations :) if lizmap_cloud and not is_dev: messages.append('👍') @@ -946,7 +976,7 @@ def _messages_for_version( messages.append(tr('Higher than a public release') + ' 👍') level = Qgis.Success - elif bugfix < latest_bugfix or is_pre_package: + elif is_numeric(latest_bugfix) and bugfix < latest_bugfix or is_pre_package: # The user is not running the latest bugfix release on the maintained branch if bugfix + 2 < latest_bugfix: @@ -958,7 +988,7 @@ def _messages_for_version( # People upgrading to a major version but keeping a .0 version have skills to upgrade to # a .1 version messages.append(tr("Running a .0 version, upgrade to the latest bugfix release")) - elif bugfix != 0 and status in (ReleaseStatus.Stable, ReleaseStatus.Retired): + elif bugfix != 0 and status in (ReleaseStatus.ReleaseCandidate, ReleaseStatus.Stable, ReleaseStatus.SecurityBugfixOnly, ReleaseStatus.Retired): # Even if the branch is retired, we encourage people upgrading to the latest messages.append( tr( diff --git a/lizmap/test/data/version_info_19082024.json b/lizmap/test/data/version_info_19082024.json new file mode 100644 index 00000000..6a7238d1 --- /dev/null +++ b/lizmap/test/data/version_info_19082024.json @@ -0,0 +1,25 @@ +[ + { + "branch": "3.8", + "changelog": {}, + "first_release_date": "2024-03-21", + "latest_release_date": "2024-08-19", + "latest_release_version": "3.8.0-rc.4", + "qgis_max_version_recommended": 39900, + "qgis_min_version_recommended": 32800, + "status": "feature_freeze" + }, + { + "branch": "3.6", + "changelog": { + "en": "https://www.3liz.com/en/news/lizmap-web-client-3-6.html", + "fr": "https://www.3liz.com/news/lizmap-web-client-3-6.html" + }, + "first_release_date": "2022-12-09", + "latest_release_date": "2024-07-04", + "latest_release_version": "3.6.14", + "qgis_max_version_recommended": 39900, + "qgis_min_version_recommended": 31000, + "status": "security_bugfix_only" + } +] diff --git a/lizmap/test/test_definitions.py b/lizmap/test/test_definitions.py index f3293e9d..5424807a 100644 --- a/lizmap/test/test_definitions.py +++ b/lizmap/test/test_definitions.py @@ -43,5 +43,6 @@ def test_version_comparaison(self): def test_release_status(self): """ Test to retrieve release status. """ - self.assertEqual(ReleaseStatus.find('feature_freeze'), ReleaseStatus.ReleaseCandidate) - self.assertEqual(ReleaseStatus.find('stable'), ReleaseStatus.Stable) + self.assertEqual(ReleaseStatus.SecurityBugfixOnly, ReleaseStatus.find('security_bugfix_only')) + self.assertEqual(ReleaseStatus.ReleaseCandidate, ReleaseStatus.find('feature_freeze')) + self.assertEqual(ReleaseStatus.Stable, ReleaseStatus.find('stable')) diff --git a/lizmap/test/test_pyplugin_installer.py b/lizmap/test/test_pyplugin_installer.py index fd7529b4..3e2c06d4 100644 --- a/lizmap/test/test_pyplugin_installer.py +++ b/lizmap/test/test_pyplugin_installer.py @@ -4,7 +4,7 @@ import unittest -from pyplugin_installer.version_compare import compareVersions +from pyplugin_installer.version_compare import chopString, compareVersions """ For testing the core PyPlugin installer 'API'. @@ -26,3 +26,10 @@ def test_version_compare(self): # Ok, weird self.assertEqual(1, compareVersions("master", "1.0.0")) self.assertEqual(2, compareVersions("1.0.0", "master")) + + def test_chop_strings(self): + """ Test chop strings. """ + self.assertListEqual(['1', '0', '0'], chopString("1.0.0")) + self.assertListEqual(['1', '0', '0', 'pre'], chopString("1.0.0-pre")) + self.assertListEqual(['1', '0', '0', 'rc', '4'], chopString("1.0.0-rc.4")) + self.assertListEqual(['1', '0', '0', 'rc', '4', '1'], chopString("1.0.0-rc.4.1")) diff --git a/lizmap/test/test_version_info.py b/lizmap/test/test_version_info.py index 722a068c..eef019c0 100644 --- a/lizmap/test/test_version_info.py +++ b/lizmap/test/test_version_info.py @@ -21,6 +21,7 @@ def test_split_lizmap_version(self): self.assertTupleEqual(ServerManager.split_lizmap_version("3.5.2"), (3, 5, 2)) self.assertTupleEqual(ServerManager.split_lizmap_version("3.5.2-pre"), (3, 5, 2, 'pre')) self.assertTupleEqual(ServerManager.split_lizmap_version("3.5.2-pre.5204"), (3, 5, 2, 'pre', 5204)) + self.assertTupleEqual(ServerManager.split_lizmap_version("3.8.0-rc.4"), (3, 8, 0, 'rc', 4)) def test_version_info_lizmap_status(self): """ Test version info according to LWC version. @@ -293,3 +294,51 @@ def test_version_info_qgis_server_status(self): True, ) ) + + def test_version_info_lwc_rc(self): + """ Test LWC version with RC.""" + qgis_desktop = (3, 34) + + # Test file with + # 3.8.0-rc.4 latest RC + json_path = Path(plugin_test_data_path('version_info_19082024.json')) + + self.assertEqual( + ServerManager._messages_for_version('3.8.0-rc.4', '', 'bob_is_admin', json_path, qgis_desktop), + ( + Qgis.Success, + [ + 'A dev version, warrior ! 👍', + ], + True, + ) + ) + + self.assertEqual( + ServerManager._messages_for_version('3.8.0-rc.3', '', 'bob_is_admin', json_path, qgis_desktop), + ( + Qgis.Warning, + [ + 'A dev version, warrior ! 👍', + 'Not latest bugfix release, 3.8.0-rc.4 is available', + ], + True, + ) + ) + + def test_version_info_lwc_security_bugfix(self): + """ Test LWC version with security bugfix.""" + qgis_desktop = (3, 34) + + # Test file with + # 3.6.14 security bugfix only + json_path = Path(plugin_test_data_path('version_info_19082024.json')) + + self.assertEqual( + ServerManager._messages_for_version('3.6.14', '', 'bob_is_admin', json_path, qgis_desktop), + ( + Qgis.Warning, + ['Version 3.6 not maintained anymore, only for security bugfix only'], + True, + ) + )