1#!/usr/bin/env python3 2# Copyright © 2022 Collabora Ltd. 3# Authors: 4# David Heidelberg <david.heidelberg@collabora.com> 5# 6# For the dependencies, see the requirements.txt 7# SPDX-License-Identifier: MIT 8 9""" 10Helper script to update traces checksums 11""" 12 13import argparse 14import bz2 15import glob 16import re 17import json 18import sys 19from ruamel.yaml import YAML 20 21import gitlab 22from colorama import Fore, Style 23from gitlab_common import get_gitlab_project, read_token, wait_for_pipeline 24 25 26DESCRIPTION_FILE = "export PIGLIT_REPLAY_DESCRIPTION_FILE='.*/install/(.*)'$" 27DEVICE_NAME = "export PIGLIT_REPLAY_DEVICE_NAME='(.*)'$" 28 29 30def gather_results( 31 project, 32 pipeline, 33) -> None: 34 """Gather results""" 35 36 target_jobs_regex = re.compile(".*-traces([:].*)?$") 37 38 for job in pipeline.jobs.list(all=True, sort="desc"): 39 if target_jobs_regex.match(job.name) and job.status == "failed": 40 cur_job = project.jobs.get(job.id) 41 # get variables 42 print(f" {job.name}...") 43 log: list[str] = cur_job.trace().decode("unicode_escape").splitlines() 44 filename: str = '' 45 dev_name: str = '' 46 for logline in log: 47 desc_file = re.search(DESCRIPTION_FILE, logline) 48 device_name = re.search(DEVICE_NAME, logline) 49 if desc_file: 50 filename = desc_file.group(1) 51 if device_name: 52 dev_name = device_name.group(1) 53 54 if not filename or not dev_name: 55 print(Fore.RED + "Couldn't find device name or YML file in the logs!" + Style.RESET_ALL) 56 return 57 58 print(f" Found {dev_name} and file {filename}") 59 60 # find filename in Mesa source 61 traces_file = glob.glob('./**/' + filename, recursive=True) 62 # write into it 63 with open(traces_file[0], 'r', encoding='utf-8') as target_file: 64 yaml = YAML() 65 yaml.compact(seq_seq=False, seq_map=False) 66 yaml.version = 1,2 67 yaml.width = 2048 # do not break the text fields 68 yaml.default_flow_style = None 69 target = yaml.load(target_file) 70 71 # parse artifact 72 results_json_bz2 = cur_job.artifact(path="results/results.json.bz2", streamed=False) 73 results_json = bz2.decompress(results_json_bz2).decode("utf-8", errors="replace") 74 results = json.loads(results_json) 75 76 for _, value in results["tests"].items(): 77 if ( 78 not value['images'] or 79 not value['images'][0] or 80 "image_desc" not in value['images'][0] 81 ): 82 continue 83 84 trace: str = value['images'][0]['image_desc'] 85 checksum: str = value['images'][0]['checksum_render'] 86 87 if not checksum: 88 print(Fore.RED + f"{dev_name}: {trace}: checksum is missing! Crash?" + Style.RESET_ALL) 89 continue 90 91 if checksum == "error": 92 print(Fore.RED + f"{dev_name}: {trace}: crashed" + Style.RESET_ALL) 93 continue 94 95 if target['traces'][trace][dev_name].get('checksum') == checksum: 96 continue 97 98 if "label" in target['traces'][trace][dev_name]: 99 print(f'{dev_name}: {trace}: please verify that label {Fore.BLUE}{target["traces"][trace][dev_name]["label"]}{Style.RESET_ALL} is still valid') 100 101 print(Fore.GREEN + f'{dev_name}: {trace}: checksum updated' + Style.RESET_ALL) 102 target['traces'][trace][dev_name]['checksum'] = checksum 103 104 with open(traces_file[0], 'w', encoding='utf-8') as target_file: 105 yaml.dump(target, target_file) 106 107 108 109def parse_args() -> None: 110 """Parse args""" 111 parser = argparse.ArgumentParser( 112 description="Tool to generate patch from checksums ", 113 epilog="Example: update_traces_checksum.py --rev $(git rev-parse HEAD) " 114 ) 115 parser.add_argument( 116 "--rev", metavar="revision", help="repository git revision", required=True 117 ) 118 parser.add_argument( 119 "--token", 120 metavar="token", 121 help="force GitLab token, otherwise it's read from ~/.config/gitlab-token", 122 ) 123 return parser.parse_args() 124 125 126if __name__ == "__main__": 127 try: 128 args = parse_args() 129 130 token = read_token(args.token) 131 132 gl = gitlab.Gitlab(url="https://gitlab.freedesktop.org", private_token=token) 133 134 cur_project = get_gitlab_project(gl, "mesa") 135 136 print(f"Revision: {args.rev}") 137 (pipe, cur_project) = wait_for_pipeline([cur_project], args.rev) 138 print(f"Pipeline: {pipe.web_url}") 139 gather_results(cur_project, pipe) 140 141 sys.exit() 142 except KeyboardInterrupt: 143 sys.exit(1) 144