423b9a8ded10b0d4a81d6134c4045d0b7e077eb5

Author
Carlo Sala <carlosalag@protonmail.com>
Committer
Carlo Sala <carlosalag@protonmail.com>
Date

Message

feat(dependencies): add support for semver tags

Diff

This diff is truncated to protect this page.

  1diff --git a/.github/workflows/dependencies/requirements.txt b/.github/workflows/dependencies/requirements.txt
  2index 0ef3e54cac81af4aab7bd39a2f9451de616c135d..7e840a74cc6bfeef0c025b369d1302e6fa954cd6 100644
  3--- a/.github/workflows/dependencies/requirements.txt
  4+++ b/.github/workflows/dependencies/requirements.txt
  5@@ -3,4 +3,5 @@ charset-normalizer==3.3.2
  6 idna==3.7
  7 PyYAML==6.0.1
  8 requests==2.31.0
  9+semver==3.0.2
 10 urllib3==2.2.1
 11diff --git a/.github/workflows/dependencies/updater.py b/.github/workflows/dependencies/updater.py
 12index 9754cdf839419f6cbf6781808c293096f5c5faf5..7e8e92ca9b422062d1c4fdfd3b2a6b54943b24ef 100644
 13--- a/.github/workflows/dependencies/updater.py
 14+++ b/.github/workflows/dependencies/updater.py
 15@@ -1,13 +1,15 @@
 16 import os
 17+import re
 18 import shutil
 19 import subprocess
 20 import sys
 21 import timeit
 22 from copy import deepcopy
 23-from typing import Literal, NotRequired, TypedDict
 24+from typing import Literal, NotRequired, Optional, TypedDict
 25 
 26 import requests
 27 import yaml
 28+from semver import Version
 29 
 30 # Get TMP_DIR variable from environment
 31 TMP_DIR = os.path.join(os.environ.get("TMP_DIR", "/tmp"), "ohmyzsh")
 32@@ -16,6 +18,35 @@ DEPS_YAML_FILE = ".github/dependencies.yml"
 33 # Dry run flag
 34 DRY_RUN = os.environ.get("DRY_RUN", "0") == "1"
 35 
 36+# utils for tag comparison
 37+BASEVERSION = re.compile(
 38+    r"""[vV]?
 39+    (?P<major>(0|[1-9])\d*)
 40+    (\.
 41+    (?P<minor>(0|[1-9])\d*)
 42+    (\.
 43+    (?P<patch>(0|[1-9])\d*)
 44+    )?
 45+    )?
 46+    """,
 47+    re.VERBOSE,
 48+)
 49+
 50+
 51+def coerce(version: str) -> Optional[Version]:
 52+    match = BASEVERSION.search(version)
 53+    if not match:
 54+        return None
 55+
 56+    # BASEVERSION looks for `MAJOR.minor.patch` in the string given
 57+    # it fills with None if any of them is missing (for example `2.1`)
 58+    ver = {
 59+        key: 0 if value is None else value for key, value in match.groupdict().items()
 60+    }
 61+    # Version takes `major`, `minor`, `patch` arguments
 62+    ver = Version(**ver)  # pyright: ignore[reportArgumentType]
 63+    return ver
 64+
 65 
 66 class CodeTimer:
 67     def __init__(self, name=None):
 68@@ -390,6 +421,11 @@ class GitHub:
 69 
 70         # Send a GET request to the GitHub API
 71         response = requests.get(url)
 72+        current_version = coerce(current_tag)
 73+        if current_version is None:
 74+            raise ValueError(
 75+                f"Stored {current_version} from {repo} does not follow semver"
 76+            )
 77 
 78         # If the request was successful
 79         if response.status_code == 200:
 80@@ -401,10 +437,27 @@ class GitHub:
 81                     "has_updates": False,
 82                 }
 83 
 84-            latest_ref = data[-1]
 85+            latest_ref = None
 86+            latest_version: Optional[Version] = None
 87+            for ref in data:
 88+                # we find the tag since GitHub returns it as plain git ref
 89+                tag_version = coerce(ref["ref"].replace("refs/tags/", ""))
 90+                if tag_version is None:
 91+                    # we skip every tag that is not semver-complaint
 92+                    continue
 93+                if latest_version is None or tag_version.compare(latest_version) > 0:
 94+                    # if we have a "greater" semver version, set it as latest
 95+                    latest_version = tag_version
 96+                    latest_ref = ref
 97+
 98+            # raise if no valid semver tag is found
 99+            if latest_ref is None or latest_version is None:
100+                raise ValueError(f"No tags following semver found in {repo}")
101+
102+            # we get the tag since GitHub returns it as plain git ref
103             latest_tag = latest_ref["ref"].replace("refs/tags/", "")
104 
105-            if latest_tag == current_tag:
106+            if latest_version.compare(current_version) <= 0:
107                 return {
108                     "has_updates": False,
109                 }
110@@ -424,9 +477,6 @@ class GitHub:
111 
112     @staticmethod
113     def check_updates(repo, branch, version) -> UpdateStatusFalse | UpdateStatusTrue:
114-        # TODO: add support for semver updating (based on tags)