1#!/usr/bin/env python3 2# Copyright © 2022 Collabora Ltd. 3# Authors: 4# David Heidelberg <[email protected]> 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, get_gitlab_pipeline_from_url 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", "ignore").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("results/results.json.bz2") 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", 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 parser.add_argument( 124 "--pipeline-url", 125 metavar="pipeline_url", 126 help="specify a pipeline url", 127 ) 128 return parser.parse_args() 129 130 131if __name__ == "__main__": 132 try: 133 args = parse_args() 134 135 token = read_token(args.token) 136 137 gl = gitlab.Gitlab(url="https://gitlab.freedesktop.org", private_token=token) 138 139 cur_project = get_gitlab_project(gl, "mesa") 140 141 if args.pipeline_url: 142 pipe, cur_project = get_gitlab_pipeline_from_url(gl, args.pipeline_url) 143 REV = pipe.sha 144 else: 145 if not args.rev: 146 print('error: the following arguments are required: --rev') 147 sys.exit(1) 148 print(f"Revision: {args.rev}") 149 (pipe, cur_project) = wait_for_pipeline([cur_project], args.rev) 150 print(f"Pipeline: {pipe.web_url}") 151 gather_results(cur_project, pipe) 152 153 sys.exit() 154 except KeyboardInterrupt: 155 sys.exit(1) 156