• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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