• 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                           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