From 84e16c67288889cfbb3b91278d19f376e965664b Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Oct 10 2019 10:43:00 +0000 Subject: Add a new endpoint collecting the bodhi updates info for a package This endpoint returns either a JSON blob or a html table containing all the releases found in either bodhi or mdapi for the active releases (pending and stable) retrieved from bodhi. This endpoint currently only support the `rpms` namespace so it strips out all the flatpaks, containers and modular releases of Fedora. Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure_distgit/plugin.py b/pagure_distgit/plugin.py index 9665ec7..f79df44 100644 --- a/pagure_distgit/plugin.py +++ b/pagure_distgit/plugin.py @@ -9,6 +9,7 @@ """ from __future__ import unicode_literals, print_function +import collections import datetime import logging @@ -232,3 +233,108 @@ def take_orphan_endpoint(namespace, repo): output = {"point_of_contact": repo.user.user} return flask.jsonify(output) + + +@DISTGIT_NS.route("/bodhi_updates//", methods=["GET"]) +@api_method +def bodhi_updates_endpoint(namespace, repo): + """ Retrieves the current updates in bodhi for the specified package. + """ + if namespace not in ["rpms"]: + raise pagure.exceptions.APIError( + 400, error_code=APIERROR.EINVALIDREQ, errors=["Namespace not supported"]) + + _log.info("Received request for the bodhi updates of: %s/%s", namespace, repo) + + repo = _get_repo(repo, namespace=namespace) + html = pagure.utils.is_true(flask.request.args.get("html", False)) + + bodhi_base_url = "https://bodhi.fedoraproject.org/" + + # Retrieves the active releases from bodhi + releases_url = "%s/releases/" % bodhi_base_url + releases = {} + page = 1 + pages = 1 + while True: + url = "%s?page=%s" % (releases_url, page) + _log.info("Calling bodhi at: %s", url) + req = requests.get(url) + if not req.ok: + raise pagure.exceptions.APIError( + 400, error_code=APIERROR.EINVALIDREQ, errors=["Could not call bodhi"]) + + data = req.json() + for release in data.get("releases", []): + if any(word in release["long_name"] for word in ["Flatpaks", "Containers", "Modular"]): + continue + if release["state"] in ["pending", "current"]: + releases[release["name"]] = release["long_name"] + + pages = data["pages"] + page = data["page"] + if page == pages: + break + page += 1 + + # Retrieves the updates of that package in bodhi + update_url = "%s/updates?packages=%s" % (bodhi_base_url.rstrip("/"), repo.name) + updates = collections.defaultdict(dict) + + _log.info("Calling bodhi at: %s", update_url) + req = requests.get(update_url) + if not req.ok: + raise pagure.exceptions.APIError( + 400, error_code=APIERROR.EINVALIDREQ, errors=["Could not call bodhi"]) + + data = req.json() + for update in data["updates"]: + if update["release"]["name"] not in releases: + continue + name = update["title"] + for build in update["builds"]: + if repo.name in build["nvr"]: + name = build["nvr"] + break + + if not updates[update["release"]["name"]].get(update["status"]): + updates[update["release"]["name"]][update["status"]] = name + + if html: + html_output = """ + +""" + for release in sorted(releases, reverse=True): + row = "" + stable = "" + if updates.get(release, {}).get("stable"): + stable = "{0}".format( + updates[release].get("stable")) + else: + # This makes things a little slower and is only needed up until all releases will have gone + # through bodhi all the time (ie: up until about F31 is eol). + mdapi_url = "https://mdapi.fedoraproject.org/%s/srcpkg/%s" % (release.lower(), repo.name) + _log.info("Calling mdapi at: %s", mdapi_url) + req = requests.get(mdapi_url) + if req.ok: + _log.info("mdapi returned ok") + data = req.json() + build = "%s-%s-%s" % (data["basename"], data["version"], data["release"]) + stable = "{0}".format(build) + testing = "" + if updates.get(release, {}).get("testing"): + testing = "{0}".format( + updates[release].get("testing")) + row = row.format( + release=releases[release], + stable=stable, + testing=testing, + ) + html_output += row + html_output += "
ReleaseStable versionVersion in testing
{release}{stable}{testing}
" + return html_output + else: + return flask.jsonify({"releases": releases, "updates": updates})