diff --git a/nix_update/version/github.py b/nix_update/version/github.py index 1e6a6d7..e76a04e 100644 --- a/nix_update/version/github.py +++ b/nix_update/version/github.py @@ -1,23 +1,20 @@ +import json import re import urllib.request import xml.etree.ElementTree as ET -from urllib.parse import ParseResult, unquote, urlparse -from xml.etree.ElementTree import Element +from urllib.parse import ParseResult, urlparse -from ..errors import VersionError from ..utils import info from .version import Version -def version_from_entry(entry: Element) -> Version: - if entry is None: - raise VersionError("No release found") - link = entry.find("{http://www.w3.org/2005/Atom}link") - assert link is not None - href = link.attrib["href"] - url = urlparse(href) - # TODO: set pre-release flag - return Version(unquote(url.path.split("/")[-1])) +def version_from_entry(entry: dict) -> Version: + href = entry["html_url"] + assert href is not None + prerelease = entry["prerelease"] + draft = entry["draft"] + version = entry["tag_name"] + return Version(version, prerelease=prerelease or draft) def fetch_github_versions(url: ParseResult) -> list[Version]: @@ -27,11 +24,19 @@ def fetch_github_versions(url: ParseResult) -> list[Version]: owner, repo = parts[1], parts[2] repo = re.sub(r"\.git$", "", repo) # TODO fallback to tags? - feed_url = f"https://github.com/{owner}/{repo}/releases.atom" - info(f"fetch {feed_url}") - resp = urllib.request.urlopen(feed_url) - tree = ET.fromstring(resp.read()) - releases = tree.findall(".//{http://www.w3.org/2005/Atom}entry") + # https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#list-releases + releases_url = f"https://api.github.com/repos/{owner}/{repo}/releases?per_page=100" + info(f"fetch {releases_url}") + req = urllib.request.Request( + releases_url, + headers={ + "Accept": "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28", + }, + ) + resp = urllib.request.urlopen(req) + releases = json.loads(resp.read()) + return [version_from_entry(x) for x in releases]