Skip to content

Commit

Permalink
fix: fallback to github api to find release tag, in case latest git t…
Browse files Browse the repository at this point in the history
…ag has no release
  • Loading branch information
danielbraun89 authored May 24, 2023
1 parent 9ed693f commit 5af5218
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 21 deletions.
32 changes: 24 additions & 8 deletions nanolayer/installers/gh_release/gh_release_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,30 @@ def install(
asked_version=version, repo=repo, release_tag_regex=release_tag_regex
)

# will raise an exception if more or less than a single asset can meet the requirments
resolved_asset = AssetResolver.resolve(
repo=repo,
release_version=release_version,
asset_regex=asset_regex,
arch=arch,
binary_names=binary_names,
)
try:
# will raise an exception if more or less than a single asset can meet the requirments
resolved_asset = AssetResolver.resolve(
repo=repo,
release_version=release_version,
asset_regex=asset_regex,
arch=arch,
binary_names=binary_names,
)
except AssetResolver.NoReleaseError as e:
release_version = ReleaseResolver.resolve(
asked_version=version,
repo=repo,
release_tag_regex=release_tag_regex,
use_github_api=True,
)
# will raise an exception if more or less than a single asset can meet the requirments
resolved_asset = AssetResolver.resolve(
repo=repo,
release_version=release_version,
asset_regex=asset_regex,
arch=arch,
binary_names=binary_names,
)

logger.warning("resolved asset: %s", resolved_asset.name)

Expand Down
16 changes: 13 additions & 3 deletions nanolayer/installers/gh_release/resolvers/asset_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from copy import deepcopy
from enum import Enum
from typing import Any, Dict, List, Optional
from urllib.error import HTTPError

from pydantic import BaseModel, Extra

Expand Down Expand Up @@ -72,6 +73,9 @@ class PlatformType(Enum):
class AssetResolverError(Exception):
pass

class NoReleaseError(Exception):
pass

class ReleaseAsset(BaseModel):
class Config:
extra = Extra.ignore
Expand Down Expand Up @@ -119,9 +123,15 @@ def __call__(self, asset: "AssetResolver.ReleaseAsset") -> bool:

@classmethod
def _get_release_dict(cls, repo: str, tag: str) -> Dict[str, Any]:
response = urllib.request.urlopen(
f"https://api.github.com/repos/{repo}/releases/tags/{tag}"
) # nosec
try:
response = urllib.request.urlopen(
f"https://api.github.com/repos/{repo}/releases/tags/{tag}"
) # nosec
except HTTPError as e:
if e.code == 404:
raise cls.NoReleaseError(
f"no release exists for repo:{repo} and tag: {tag}"
) from e
return json.loads(response.read())

@classmethod
Expand Down
48 changes: 38 additions & 10 deletions nanolayer/installers/gh_release/resolvers/release_resolver.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import json
import re
import urllib
from typing import Any, Dict, List, Optional

import invoke
Expand All @@ -11,6 +13,15 @@ class ReleaseResolverError(Exception):

GIT_VERSION_TAG_REGEX = r"(?:tags\/)([0-9A-Za-z\-\_|.]+)\\?$"

@classmethod
def _filter_tags_by_regex(cls, tags: List[str], regex: str) -> List[str]:
return list(
filter(
lambda match: re.match(regex, match) is not None,
tags,
)
)

@classmethod
def get_version_tags(
cls, repo: str, release_tag_regex: Optional[str] = None
Expand All @@ -27,29 +38,46 @@ def get_version_tags(
stringified_matches = [match[0] for match in matches if len(match) == 1]

if release_tag_regex is not None:
stringified_matches = list(
filter(
lambda match: re.match(release_tag_regex, match) is not None,
stringified_matches,
)
stringified_matches = cls._filter_tags_by_regex(
stringified_matches, release_tag_regex
)
return stringified_matches
return []

@classmethod
def get_latest_stable_version(
def get_latest_git_version_tag(
cls, repo: str, release_tag_regex: Optional[str] = None
) -> List[str]:
) -> str:
all_version_tags = cls.get_version_tags(repo, release_tag_regex)

return natsorted(all_version_tags)[-1]

@classmethod
def get_latest_release_tag(
cls, repo: str, release_tag_regex: Optional[str] = None
) -> str:
response = urllib.request.urlopen(
f"https://api.github.com/repos/{repo}/releases"
) # nosec
release_dicts = json.loads(response.read())
release_tags = [release_dict["tag_name"] for release_dict in release_dicts]
if release_tag_regex is not None:
release_tags = cls._filter_tags_by_regex(release_tags, release_tag_regex)
return natsorted(release_tags)[-1]

@classmethod
def resolve(
cls, asked_version: str, repo: str, release_tag_regex: Optional[str] = None
) -> Dict[str, Any]:
cls,
asked_version: str,
repo: str,
release_tag_regex: Optional[str] = None,
use_github_api: bool = False,
) -> str:
if asked_version == "latest":
tag = cls.get_latest_stable_version(repo, release_tag_regex)
if use_github_api:
return cls.get_latest_release_tag(repo, release_tag_regex)
return cls.get_latest_git_version_tag(repo, release_tag_regex)

else:
versions = cls.get_version_tags(repo, release_tag_regex)
if asked_version in versions:
Expand Down

0 comments on commit 5af5218

Please sign in to comment.