瀏覽代碼

feat(api): add version comparison logic (#8902)

-LAN- 6 月之前
父節點
當前提交
3af65b2f45
共有 2 個文件被更改,包括 83 次插入4 次删除
  1. 45 4
      api/controllers/console/version.py
  2. 38 0
      api/tests/unit_tests/controllers/test_compare_versions.py

+ 45 - 4
api/controllers/console/version.py

@@ -38,11 +38,52 @@ class VersionApi(Resource):
             return result
 
         content = json.loads(response.content)
-        result["version"] = content["version"]
-        result["release_date"] = content["releaseDate"]
-        result["release_notes"] = content["releaseNotes"]
-        result["can_auto_update"] = content["canAutoUpdate"]
+        if _has_new_version(latest_version=content["version"], current_version=f"{args.get('current_version')}"):
+            result["version"] = content["version"]
+            result["release_date"] = content["releaseDate"]
+            result["release_notes"] = content["releaseNotes"]
+            result["can_auto_update"] = content["canAutoUpdate"]
         return result
 
 
+def _has_new_version(*, latest_version: str, current_version: str) -> bool:
+    def parse_version(version: str) -> tuple:
+        # Split version into parts and pre-release suffix if any
+        parts = version.split("-")
+        version_parts = parts[0].split(".")
+        pre_release = parts[1] if len(parts) > 1 else None
+
+        # Validate version format
+        if len(version_parts) != 3:
+            raise ValueError(f"Invalid version format: {version}")
+
+        try:
+            # Convert version parts to integers
+            major, minor, patch = map(int, version_parts)
+            return (major, minor, patch, pre_release)
+        except ValueError:
+            raise ValueError(f"Invalid version format: {version}")
+
+    latest = parse_version(latest_version)
+    current = parse_version(current_version)
+
+    # Compare major, minor, and patch versions
+    for latest_part, current_part in zip(latest[:3], current[:3]):
+        if latest_part > current_part:
+            return True
+        elif latest_part < current_part:
+            return False
+
+    # If versions are equal, check pre-release suffixes
+    if latest[3] is None and current[3] is not None:
+        return True
+    elif latest[3] is not None and current[3] is None:
+        return False
+    elif latest[3] is not None and current[3] is not None:
+        # Simple string comparison for pre-release versions
+        return latest[3] > current[3]
+
+    return False
+
+
 api.add_resource(VersionApi, "/version")

+ 38 - 0
api/tests/unit_tests/controllers/test_compare_versions.py

@@ -0,0 +1,38 @@
+import pytest
+
+from controllers.console.version import _has_new_version
+
+
+@pytest.mark.parametrize(
+    ("latest_version", "current_version", "expected"),
+    [
+        ("1.0.1", "1.0.0", True),
+        ("1.1.0", "1.0.0", True),
+        ("2.0.0", "1.9.9", True),
+        ("1.0.0", "1.0.0", False),
+        ("1.0.0", "1.0.1", False),
+        ("1.0.0", "2.0.0", False),
+        ("1.0.1", "1.0.0-beta", True),
+        ("1.0.0", "1.0.0-alpha", True),
+        ("1.0.0-beta", "1.0.0-alpha", True),
+        ("1.0.0", "1.0.0-rc1", True),
+        ("1.0.0", "0.9.9", True),
+        ("1.0.0", "1.0.0-dev", True),
+    ],
+)
+def test_has_new_version(latest_version, current_version, expected):
+    assert _has_new_version(latest_version=latest_version, current_version=current_version) == expected
+
+
+def test_has_new_version_invalid_input():
+    with pytest.raises(ValueError):
+        _has_new_version(latest_version="1.0", current_version="1.0.0")
+
+    with pytest.raises(ValueError):
+        _has_new_version(latest_version="1.0.0", current_version="1.0")
+
+    with pytest.raises(ValueError):
+        _has_new_version(latest_version="invalid", current_version="1.0.0")
+
+    with pytest.raises(ValueError):
+        _has_new_version(latest_version="1.0.0", current_version="invalid")