423b9a8ded10b0d4a81d6134c4045d0b7e077eb5
- Author
- Carlo Sala <carlosalag@protonmail.com>
- Committer
- Carlo Sala <carlosalag@protonmail.com>
- Date
Message
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)