feat(dependencies): add support for semver tags

This commit is contained in:
Carlo Sala 2024-05-09 19:20:11 +02:00
parent a258eb4547
commit 423b9a8ded
2 changed files with 57 additions and 6 deletions

View File

@ -3,4 +3,5 @@ charset-normalizer==3.3.2
idna==3.7 idna==3.7
PyYAML==6.0.1 PyYAML==6.0.1
requests==2.31.0 requests==2.31.0
semver==3.0.2
urllib3==2.2.1 urllib3==2.2.1

View File

@ -1,13 +1,15 @@
import os import os
import re
import shutil import shutil
import subprocess import subprocess
import sys import sys
import timeit import timeit
from copy import deepcopy from copy import deepcopy
from typing import Literal, NotRequired, TypedDict from typing import Literal, NotRequired, Optional, TypedDict
import requests import requests
import yaml import yaml
from semver import Version
# Get TMP_DIR variable from environment # Get TMP_DIR variable from environment
TMP_DIR = os.path.join(os.environ.get("TMP_DIR", "/tmp"), "ohmyzsh") TMP_DIR = os.path.join(os.environ.get("TMP_DIR", "/tmp"), "ohmyzsh")
@ -16,6 +18,35 @@ DEPS_YAML_FILE = ".github/dependencies.yml"
# Dry run flag # Dry run flag
DRY_RUN = os.environ.get("DRY_RUN", "0") == "1" DRY_RUN = os.environ.get("DRY_RUN", "0") == "1"
# utils for tag comparison
BASEVERSION = re.compile(
r"""[vV]?
(?P<major>(0|[1-9])\d*)
(\.
(?P<minor>(0|[1-9])\d*)
(\.
(?P<patch>(0|[1-9])\d*)
)?
)?
""",
re.VERBOSE,
)
def coerce(version: str) -> Optional[Version]:
match = BASEVERSION.search(version)
if not match:
return None
# BASEVERSION looks for `MAJOR.minor.patch` in the string given
# it fills with None if any of them is missing (for example `2.1`)
ver = {
key: 0 if value is None else value for key, value in match.groupdict().items()
}
# Version takes `major`, `minor`, `patch` arguments
ver = Version(**ver) # pyright: ignore[reportArgumentType]
return ver
class CodeTimer: class CodeTimer:
def __init__(self, name=None): def __init__(self, name=None):
@ -390,6 +421,11 @@ class GitHub:
# Send a GET request to the GitHub API # Send a GET request to the GitHub API
response = requests.get(url) response = requests.get(url)
current_version = coerce(current_tag)
if current_version is None:
raise ValueError(
f"Stored {current_version} from {repo} does not follow semver"
)
# If the request was successful # If the request was successful
if response.status_code == 200: if response.status_code == 200:
@ -401,10 +437,27 @@ class GitHub:
"has_updates": False, "has_updates": False,
} }
latest_ref = data[-1] latest_ref = None
latest_version: Optional[Version] = None
for ref in data:
# we find the tag since GitHub returns it as plain git ref
tag_version = coerce(ref["ref"].replace("refs/tags/", ""))
if tag_version is None:
# we skip every tag that is not semver-complaint
continue
if latest_version is None or tag_version.compare(latest_version) > 0:
# if we have a "greater" semver version, set it as latest
latest_version = tag_version
latest_ref = ref
# raise if no valid semver tag is found
if latest_ref is None or latest_version is None:
raise ValueError(f"No tags following semver found in {repo}")
# we get the tag since GitHub returns it as plain git ref
latest_tag = latest_ref["ref"].replace("refs/tags/", "") latest_tag = latest_ref["ref"].replace("refs/tags/", "")
if latest_tag == current_tag: if latest_version.compare(current_version) <= 0:
return { return {
"has_updates": False, "has_updates": False,
} }
@ -424,9 +477,6 @@ class GitHub:
@staticmethod @staticmethod
def check_updates(repo, branch, version) -> UpdateStatusFalse | UpdateStatusTrue: def check_updates(repo, branch, version) -> UpdateStatusFalse | UpdateStatusTrue:
# TODO: add support for semver updating (based on tags)
# Check if upstream github repo has a new version
# GitHub API URL for comparing two commits
url = f"https://api.github.com/repos/{repo}/compare/{version}...{branch}" url = f"https://api.github.com/repos/{repo}/compare/{version}...{branch}"
# Send a GET request to the GitHub API # Send a GET request to the GitHub API