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 get_gitlab_pipeline_from_url, TOKEN_DIR, get_token_from_default_dir) 25 26 27DESCRIPTION_FILE = "export PIGLIT_REPLAY_DESCRIPTION_FILE=.*/install/(.*)$" 28DEVICE_NAME = "export PIGLIT_REPLAY_DEVICE_NAME='(.*)'$" 29 30 31def gather_results( 32 project, 33 pipeline, 34) -> None: 35 """Gather results""" 36 37 target_jobs_regex = re.compile(".*-traces([:].*)?$") 38 39 for job in pipeline.jobs.list(all=True, sort="desc"): 40 if target_jobs_regex.match(job.name) and job.status == "failed": 41 cur_job = project.jobs.get(job.id) 42 # get variables 43 print(f" {job.name}...") 44 log: list[str] = cur_job.trace().decode("unicode_escape", "ignore").splitlines() 45 filename: str = '' 46 dev_name: str = '' 47 for logline in log: 48 desc_file = re.search(DESCRIPTION_FILE, logline) 49 device_name = re.search(DEVICE_NAME, logline) 50 if desc_file: 51 filename = desc_file.group(1) 52 if device_name: 53 dev_name = device_name.group(1) 54 55 if not filename or not dev_name: 56 print(Fore.RED + "Couldn't find device name or YML file in the logs!" + Style.RESET_ALL) 57 return 58 59 print(f" Found {dev_name} and file {filename}") 60 61 # find filename in Mesa source 62 traces_file = glob.glob('./**/' + filename, recursive=True) 63 # write into it 64 with open(traces_file[0], 'r', encoding='utf-8') as target_file: 65 yaml = YAML() 66 yaml.compact(seq_seq=False, seq_map=False) 67 yaml.version = 1,2 68 yaml.width = 2048 # do not break the text fields 69 yaml.default_flow_style = None 70 target = yaml.load(target_file) 71 72 # parse artifact 73 results_json_bz2 = cur_job.artifact("results/results.json.bz2") 74 results_json = bz2.decompress(results_json_bz2).decode("utf-8", errors="replace") 75 results = json.loads(results_json) 76 77 for _, value in results["tests"].items(): 78 if ( 79 not value['images'] or 80 not value['images'][0] or 81 "image_desc" not in value['images'][0] 82 ): 83 continue 84 85 trace: str = value['images'][0]['image_desc'] 86 checksum: str = value['images'][0]['checksum_render'] 87 88 if not checksum: 89 print(Fore.RED + f"{dev_name}: {trace}: checksum is missing! Crash?" + Style.RESET_ALL) 90 continue 91 92 if checksum == "error": 93 print(Fore.RED + f"{dev_name}: {trace}: crashed" + Style.RESET_ALL) 94 continue 95 96 if target['traces'][trace][dev_name].get('checksum') == checksum: 97 continue 98 99 if "label" in target['traces'][trace][dev_name]: 100 print( 101 f"{dev_name}: {trace}: please verify that label " 102 f"{Fore.BLUE}{target['traces'][trace][dev_name]['label']}{Style.RESET_ALL} " 103 "is still valid" 104 ) 105 106 print(Fore.GREEN + f'{dev_name}: {trace}: checksum updated' + Style.RESET_ALL) 107 target['traces'][trace][dev_name]['checksum'] = checksum 108 109 with open(traces_file[0], 'w', encoding='utf-8') as target_file: 110 yaml.dump(target, target_file) 111 112 113 114def parse_args() -> None: 115 """Parse args""" 116 parser = argparse.ArgumentParser( 117 description="Tool to generate patch from checksums ", 118 epilog="Example: update_traces_checksum.py --rev $(git rev-parse HEAD) " 119 ) 120 parser.add_argument( 121 "--rev", metavar="revision", help="repository git revision", 122 ) 123 parser.add_argument( 124 "--token", 125 metavar="token", 126 type=str, 127 default=get_token_from_default_dir(), 128 help="Use the provided GitLab token or token file, " 129 f"otherwise it's read from {TOKEN_DIR / 'gitlab-token'}", 130 ) 131 parser.add_argument( 132 "--pipeline-url", 133 metavar="pipeline_url", 134 help="specify a pipeline url", 135 ) 136 return parser.parse_args() 137 138 139if __name__ == "__main__": 140 try: 141 args = parse_args() 142 143 token = read_token(args.token) 144 145 gl = gitlab.Gitlab(url="https://gitlab.freedesktop.org", private_token=token) 146 147 cur_project = get_gitlab_project(gl, "mesa") 148 149 if args.pipeline_url: 150 pipe, cur_project = get_gitlab_pipeline_from_url(gl, args.pipeline_url) 151 REV = pipe.sha 152 else: 153 if not args.rev: 154 print('error: the following arguments are required: --rev') 155 sys.exit(1) 156 print(f"Revision: {args.rev}") 157 (pipe, cur_project) = wait_for_pipeline([cur_project], args.rev) 158 print(f"Pipeline: {pipe.web_url}") 159 gather_results(cur_project, pipe) 160 161 sys.exit() 162 except KeyboardInterrupt: 163 sys.exit(1) 164