Source code for yambs.github
"""
A module for working with GitHub releases.
"""
# built-in
import os
from typing import Any, Dict
from urllib.parse import ParseResult
# third-party
import requests
from vcorelib.dict.codec import BasicDictCodec as _BasicDictCodec
# internal
from yambs.schemas import YambsDictCodec as _YambsDictCodec
GIHTUB_HEADERS = {
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
}
ReleaseData = Dict[str, Any]
[docs]
class Github(_YambsDictCodec, _BasicDictCodec):
"""GitHub repository information."""
[docs]
def github_url(
netloc_prefix: str = "",
scheme: str = "https",
path: str = "",
params: str = "",
query: str = "",
fragment: str = "",
) -> ParseResult:
"""See: https://docs.python.org/3/library/urllib.parse.html."""
netloc = "github.com"
if netloc_prefix:
netloc = f"{netloc_prefix}." + netloc
return ParseResult(
scheme=scheme,
netloc=netloc,
path=path,
params=params,
query=query,
fragment=fragment,
)
DEFAULT_RELEASE = "latest"
[docs]
def repo_release_api_url(
owner: str, repo: str, version: str = DEFAULT_RELEASE
) -> str:
"""Get a URL string for a repository's latest release."""
version_str = version if version == DEFAULT_RELEASE else f"tags/{version}"
return github_url(
netloc_prefix="api",
path=f"repos/{owner}/{repo}/releases/{version_str}",
).geturl()
[docs]
def check_api_token() -> None:
"""Check for a GitHub API token set via the environment."""
if "Authorization" not in GIHTUB_HEADERS:
if "GITHUB_API_TOKEN" in os.environ:
GIHTUB_HEADERS["Authorization"] = (
f"Bearer {os.environ['GITHUB_API_TOKEN']}"
)
[docs]
def release_data(
owner: str,
repo: str,
*args,
version: str = DEFAULT_RELEASE,
timeout: float = None,
**kwargs,
) -> ReleaseData:
"""Get latest-release data."""
check_api_token()
result: ReleaseData = {}
# codecov was bugging out.
tries = kwargs.get("tries", 5)
while not validate_release(result) and tries:
result = requests.get(
repo_release_api_url(owner, repo, version=version),
*args,
timeout=timeout,
headers=GIHTUB_HEADERS,
**kwargs,
).json()
tries -= 1
assert validate_release(result), result
return result
[docs]
def validate_release(data: ReleaseData) -> bool:
"""Ensure that GitHub release data actually contains data."""
return all(x in data for x in ["name", "html_url", "assets"])