#!/usr/bin/python """ This script queries PDC for all the packages in Fedora, it then go through each of them and determines if they are inactive on all branches or not. If they are, it will then query dist-git to find out which ones have maintainers in addition to `orphan` listed there. """ import collections import logging import sys import time import requests from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry _log = logging.getLogger(__name__) pdc_active_branches = "https://pdc.fedoraproject.org/extras/active_branches.json" distgit_api_base_url = "https://src.fedoraproject.org/api/0/" pdc_namespace_to_dist_git = { "rpm": "rpms", "container": "container", "flatpak": "flatpaks", "module": "modules", } def retry_session(): session = requests.Session() retry = Retry( total=5, read=5, connect=5, backoff_factor=0.3, status_forcelist=(500, 502, 504), ) adapter = HTTPAdapter(max_retries=retry) session.mount("http://", adapter) session.mount("https://", adapter) return session def main(): """ Queries PDC to find packages retired on all branches. From there queries dist-git to find if they still have maintainers. """ _log.info("Querying PDC") session = retry_session() branch_info = session.get(pdc_active_branches).json() fully_retired = collections.defaultdict(list) for namespace in sorted(branch_info): _log.info("Processing: %s", namespace) for package in sorted(branch_info[namespace]): _log.info(" %s/%s", namespace, package) if True not in [el[1] for el in branch_info[namespace][package]]: fully_retired[namespace].append(package) for namespace in fully_retired: _log.info( "%s full retired packages found in %s", len(fully_retired[namespace]), namespace, ) for namespace in fully_retired: _log.info("Processing: %s", namespace) for package in fully_retired[namespace]: _log.info(" %s/%s", namespace, package) ns = pdc_namespace_to_dist_git[namespace] url = f"{distgit_api_base_url}{ns}/{package}" cnt = 0 while 1: try: data = session.get(url).json() break except Exception: if cnt == 4: raise cnt += 1 time.sleep(30) packagers = set() for lvl in data["access_users"]: packagers.update([u for u in data["access_users"][lvl]]) if "orphan" in packagers: packagers.remove("orphan") else: print( f"{ns}/{package} is retired but does not list 'orphan' in its users" ) groups = set() for lvl in data["access_groups"]: groups.update([u for u in data["access_groups"][lvl]]) if packagers or groups: string = f"{ns}/{package} is retired and has the following:" if packagers: string += f" 'maintainers': {(', ').join(packagers)}" if groups: string += f" 'groups': @{(', @').join(groups)}" print(string) if __name__ == "__main__": logging.basicConfig( stream=sys.stderr, format="%(message)s", level=logging.INFO, ) main()