commit: e9e19ac01de5a76413932f5d0cde4536026dc4ca Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> AuthorDate: Sat Aug 23 07:05:02 2025 +0000 Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> CommitDate: Sat Aug 23 07:05:02 2025 +0000 URL: https://gitweb.gentoo.org/proj/pkgcore/pkgcore.git/commit/?id=e9e19ac0
examples: add new script for closing destabled arch bugs Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org> examples/destable_arch_bugs.py | 114 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/examples/destable_arch_bugs.py b/examples/destable_arch_bugs.py new file mode 100755 index 00000000..124f1a84 --- /dev/null +++ b/examples/destable_arch_bugs.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 + +"""Go over all open stabilization bugs for that arch, and drop the arch.""" + +import json +import sys +import urllib.request as urllib +from typing import TypedDict +from urllib.parse import urlencode + +from pkgcore.util import commandline + + +argparser = commandline.ArgumentParser(version=False, description=__doc__) +argparser.add_argument( + "--api-key", + metavar="KEY", + required=True, + help="Bugzilla API key", + docs=""" + The Bugzilla API key to use for authentication. Used mainly to overcome + rate limiting done by bugzilla server. This tool doesn't perform any + bug editing, just fetching info for the bug. + """, +) +argparser.add_argument( + "--arch", + metavar="ARCH", + required=True, + help="The arch to check for", + docs=""" + The arch to check for. This tool will look for all open stabilization + bugs with that arch in the CC field, and remove it. If that was the last + arch in the CC field, the bug will be closed as well. + """, +) + + +class BugInfo(TypedDict): + id: int + cc: list[str] + + [email protected]_final_check +def check_args(parser, namespace): + repo = namespace.domain.ebuild_repos + namespace.known_arches = frozenset().union(*(pkg.known_arches for pkg in repo)) + + if namespace.arch not in namespace.known_arches: + parser.error(f"unknown arch: {namespace.arch}") + + +def fetch_bugs(arch: str, api_key: str) -> tuple[BugInfo, ...]: + params = urlencode( + ( + ("Bugzilla_api_key", api_key), + ("component", "Stabilization"), + ("include_fields", "id,cc"), + ("bug_status", "UNCONFIRMED"), + ("bug_status", "CONFIRMED"), + ("bug_status", "IN_PROGRESS"), + ("cc", f"{arch}@gentoo.org"), + ) + ) + with urllib.urlopen( + "https://bugs.gentoo.org/rest/bug?" + params, timeout=30 + ) as response: + return tuple(json.loads(response.read().decode("utf-8")).get("bugs", [])) + + +def update_bug(arch: str, api_key: str, bug_id: int, to_close: bool): + req = { + "Bugzilla_api_key": api_key, + "ids": [bug_id], + "cc": {"remove": [f"{arch}@gentoo.org"]}, + } + + comment = f"Arch {arch} is destabled, removing." + if to_close: + req["status"] = "RESOLVED" + req["resolution"] = "FIXED" + comment += "\n\nNo remaining arches, closing the bug." + else: + req["status"] = "IN_PROGRESS" + req["comment"] = {"body": comment} + + data = json.dumps(req).encode("utf-8") + url = f"https://bugs.gentoo.org/rest/bug/{bug_id}" + request = urllib.Request(url, data=data, method="PUT") + request.add_header("Content-Type", "application/json") + with urllib.urlopen(request, timeout=30) as response: + return json.loads(response.read().decode("utf-8")) + + [email protected]_main_func +def main(options, out, err): + for bug in fetch_bugs(options.arch, options.api_key): + cc = frozenset(bug["cc"]) + cc_names = frozenset( + x.split("@", 1)[0] for x in cc if x.endswith("@gentoo.org") or "@" not in x + ) + bug_arches = cc_names.intersection(options.known_arches) + + update_bug( + arch=options.arch, + api_key=options.api_key, + bug_id=bug["id"], + to_close=len(bug_arches) == 1, + ) + + +if __name__ == "__main__": + tool = commandline.Tool(argparser) + sys.exit(tool())
