#!/usr/bin/python3 # Copyright (C) 2025 Red Hat, Inc. # SPDX-License-Identifier: LGPL-2.1-or-later import argparse import json import logging import sys from operator import attrgetter import mwclient.errors # type: ignore[import-untyped] from wikitcms.wiki import ResTuple, Wiki # type: ignore[import-untyped] logger = logging.getLogger(__name__) logging.basicConfig(stream=sys.stdout, level=logging.INFO) # Printed on successful report; CI looks for this in the log to verify the job succeeded. REPORT_SUCCESS_MARKER = "Compose test report submitted successfully." class LoginError(Exception): """Raised when cannot log in to wiki to submit results.""" pass class WikiReport: def __init__(self, report_path, staging): self.report_path = report_path self.report = self.parse_json_report() self.compose_id = self.report["metadata"]["compose"] self.wiki_hostname = "stg.fedoraproject.org" if staging else "fedoraproject.org" def get_passed_testcases(self): passed_testcases = set() testmap = json.load(open("./test/fedora-wiki/wiki-testmap.json", "r")) for testcase in self.report["tests"]: # Skip testcases that don't have an openqa test associated with them # Check testmap urls for the testcases # testmap is a list of dictionaries, each with a "testname" and "fedora-wiki-testcase" and section key # If the testname in the testmap matches the openqa_test in the report, we can use the fedora-wiki-testcase # and section to report the result to the wiki def find_test(testname): for section in testmap: for test in section["tests"]: if test["testname"] == testname: return {"section": section["section"], **test} return None fedora_testcase = find_test(testcase["test_name"]) if fedora_testcase is None: logger.warning("test %s not in testmap, skipping", testcase["test_name"]) continue fedora_wiki_testcase = fedora_testcase["fedora-wiki-testcase"] section = fedora_testcase["section"] if testcase["status"] == "pass": passed_testcases.add( ResTuple( bot=True, cid=self.compose_id, dist="Fedora", env=fedora_testcase['environment'] if 'environment' in fedora_testcase else f"{testcase['arch']} {testcase['firmware']}", user="anaconda-bot", section=section, status="pass", testcase=fedora_wiki_testcase, testtype="Installation", ) ) return sorted(passed_testcases, key=attrgetter('testcase')) def parse_json_report(self): with open(self.report_path, "r") as f: return json.load(f) def login(self, wiki): if not wiki.logged_in: # This seems to occasionally throw bogus WrongPass errors try: wiki.login() except mwclient.errors.LoginError: wiki.login() if not wiki.logged_in: logger.error("could not log in to wiki") raise LoginError def upload_report(self, wiki, passed_testcases): # Submit the results (insuffs, dupes) = wiki.report_validation_results(passed_testcases) for dupe in dupes: tmpl = "already reported result for test %s, env %s! Will not report dupe." logger.info(tmpl, dupe.testcase, dupe.env) logger.debug("full ResTuple: %s", dupe) for insuff in insuffs: tmpl = "insufficient data for test %s, env %s! Will not report." logger.info(tmpl, insuff.testcase, insuff.env) logger.debug("full ResTuple: %s", insuff) return [] def run(self): wiki = Wiki(self.wiki_hostname) passed_testcases = self.get_passed_testcases() logger.info("passed testcases: %s", passed_testcases) self.login(wiki) self.upload_report(wiki, passed_testcases) if __name__ == "__main__": parser = argparse.ArgumentParser(description="Report test results to the Fedora wiki") parser.add_argument("report", help="Path to the JSON report file") parser.add_argument("--staging", action="store_true", help="Operate on the staging wiki (for testing)") args = parser.parse_args() WikiReport(args.report, staging=args.staging).run() print(REPORT_SUCCESS_MARKER)