#80 Add a new endpoint collecting the bodhi updates info for a package
Merged 4 years ago by pingou. Opened 4 years ago by pingou.

file modified
+106
@@ -9,6 +9,7 @@ 

  """

  

  from __future__ import unicode_literals, print_function

+ import collections

  import datetime

  import logging

  
@@ -232,3 +233,108 @@ 

      output = {"point_of_contact": repo.user.user}

  

      return flask.jsonify(output)

+ 

+ 

+ @DISTGIT_NS.route("/bodhi_updates/<namespace>/<repo>", 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 = """<table class="table table-bordered table-striped">

+ <tr><th scope="col">Release</th><th scope="col">Stable version</th><th scope="col">Version in testing</th></tr>

+ """

+         for release in sorted(releases, reverse=True):

+             row = "<tr><td scope='row' class='text-align-left'>{release}</td><td>{stable}</td><td>{testing}</td></tr>"

+             stable = ""

+             if updates.get(release, {}).get("stable"):

+                 stable = "<a href='https://koji.fedoraproject.org/koji/search?" \

+                 "terms={0}&type=build&match=glob'>{0}</a>".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 = "<a href='https://koji.fedoraproject.org/koji/search?" \

+                         "terms={0}&type=build&match=glob'>{0}</a>".format(build)

+             testing = ""

+             if updates.get(release, {}).get("testing"):

+                 testing = "<a href='https://koji.fedoraproject.org/koji/search?" \

+                 "terms={0}&type=build&match=glob'>{0}</a>".format(

+                     updates[release].get("testing"))

+             row = row.format(

+                 release=releases[release],

+                 stable=stable,

+                 testing=testing,

+             )

+             html_output += row

+         html_output += "</table>"

+         return html_output

+     else:

+         return flask.jsonify({"releases": releases, "updates": updates})

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 pingou@pingoured.fr

wfm for rpms/*

for the rest of namespaces, we're explicitly giving a 400 error and excluding results for it on output parsing from bodhi.

Should we allow (now or later) using this endpoint with {flatpak,modular} namespaces and return their respective results? Dunno if it fits the UX idea behind this PR.

We'll need to figure how this work for modules and flatpaks for sure but I figured baby steps, do RPMs first figure the other after.

thanks for the review and input :)

Pull-Request has been merged by pingou

4 years ago
Metadata