17 from email
.utils
import formatdate
18 from pathlib
import Path
20 from urllib
import parse
22 import dump_trace_images
24 TRACES_DB_PATH
= "./traces-db/"
25 RESULTS_PATH
= "./results/"
26 MINIO_HOST
= "minio-packet.freedesktop.org"
28 def replay(trace_path
, device_name
):
29 success
= dump_trace_images
.dump_from_trace(trace_path
, [], device_name
)
32 print("[check_image] Trace %s couldn't be replayed. See above logs for more information." % (str(trace_path
)))
33 return None, None, None
35 base_path
= trace_path
.parent
36 file_name
= trace_path
.name
37 files
= glob
.glob(str(base_path
/ "test" / device_name
/ (file_name
+ "-*" + ".png")))
40 files
= glob
.glob(str(base_path
/ "test" / device_name
/ (file_name
+ ".log")))
43 return hashlib
.md5(Image
.open(image_file
).tobytes()).hexdigest(), image_file
, log_file
45 def gitlab_ensure_trace(project_url
, trace
):
46 trace_path
= TRACES_DB_PATH
+ trace
['path']
47 if project_url
is None:
48 if not os
.path
.exists(trace_path
):
49 print("{} missing".format(trace_path
))
53 os
.makedirs(os
.path
.dirname(trace_path
), exist_ok
=True)
55 if os
.path
.exists(trace_path
):
58 print("[check_image] Downloading trace %s" % (trace
['path']), end
=" ", flush
=True)
59 download_time
= time
.time()
60 r
= requests
.get(project_url
+ trace
['path'])
61 open(trace_path
, "wb").write(r
.content
)
62 print("took %ds." % (time
.time() - download_time
), flush
=True)
64 def sign_with_hmac(key
, message
):
65 key
= key
.encode("UTF-8")
66 message
= message
.encode("UTF-8")
68 signature
= hmac
.new(key
, message
, hashlib
.sha1
).digest()
70 return base64
.encodebytes(signature
).strip().decode()
72 def upload_to_minio(file_name
, resource
, content_type
):
73 with
open('.minio_credentials', 'r') as f
:
74 credentials
= json
.load(f
)[MINIO_HOST
]
75 minio_key
= credentials
["AccessKeyId"]
76 minio_secret
= credentials
["SecretAccessKey"]
77 minio_token
= credentials
["SessionToken"]
79 date
= formatdate(timeval
=None, localtime
=False, usegmt
=True)
80 url
= 'https://%s%s' % (MINIO_HOST
, resource
)
81 to_sign
= "PUT\n\n%s\n%s\nx-amz-security-token:%s\n%s" % (content_type
, date
, minio_token
, resource
)
82 signature
= sign_with_hmac(minio_secret
, to_sign
)
84 with
open(file_name
, 'rb') as data
:
85 headers
= {'Host': MINIO_HOST
,
87 'Content-Type': content_type
,
88 'Authorization': 'AWS %s:%s' % (minio_key
, signature
),
89 'x-amz-security-token': minio_token
}
90 print("Uploading artifact to %s" % url
);
91 r
= requests
.put(url
, headers
=headers
, data
=data
)
92 if r
.status_code
>= 400:
96 def upload_artifact(file_name
, key
, content_type
):
97 resource
= '/artifacts/%s/%s/%s/%s' % (os
.environ
['CI_PROJECT_PATH'],
98 os
.environ
['CI_PIPELINE_ID'],
99 os
.environ
['CI_JOB_ID'],
101 upload_to_minio(file_name
, resource
, content_type
)
103 def ensure_reference_image(file_name
, checksum
):
104 resource
= '/mesa-tracie-results/%s/%s.png' % (os
.environ
['CI_PROJECT_PATH'], checksum
)
105 url
= 'https://%s%s' % (MINIO_HOST
, resource
)
106 r
= requests
.head(url
, allow_redirects
=True)
107 if r
.status_code
== 200:
109 upload_to_minio(file_name
, resource
, 'image/png')
111 def gitlab_check_trace(project_url
, device_name
, trace
, expectation
):
112 gitlab_ensure_trace(project_url
, trace
)
115 result
[trace
['path']] = {}
116 result
[trace
['path']]['expected'] = expectation
['checksum']
118 trace_path
= Path(TRACES_DB_PATH
+ trace
['path'])
119 checksum
, image_file
, log_file
= replay(trace_path
, device_name
)
121 result
[trace
['path']]['actual'] = 'error'
123 elif checksum
== expectation
['checksum']:
124 print("[check_image] Images match for %s" % (trace
['path']))
127 print("[check_image] Images differ for %s (expected: %s, actual: %s)" %
128 (trace
['path'], expectation
['checksum'], checksum
))
129 print("[check_image] For more information see "
130 "https://gitlab.freedesktop.org/mesa/mesa/blob/master/.gitlab-ci/tracie/README.md")
133 trace_dir
= os
.path
.split(trace
['path'])[0]
134 dir_in_results
= os
.path
.join(trace_dir
, "test", device_name
)
135 results_path
= os
.path
.join(RESULTS_PATH
, dir_in_results
)
136 os
.makedirs(results_path
, exist_ok
=True)
137 shutil
.move(log_file
, os
.path
.join(results_path
, os
.path
.split(log_file
)[1]))
138 if os
.environ
.get('TRACIE_UPLOAD_TO_MINIO', '0') == '1':
140 if os
.environ
['CI_PROJECT_PATH'] == 'mesa/mesa':
141 ensure_reference_image(image_file
, checksum
)
143 upload_artifact(image_file
, 'traces/%s.png' % checksum
, 'image/png')
144 if not ok
or os
.environ
.get('TRACIE_STORE_IMAGES', '0') == '1':
145 image_name
= os
.path
.split(image_file
)[1]
146 shutil
.move(image_file
, os
.path
.join(results_path
, image_name
))
147 result
[trace
['path']]['image'] = os
.path
.join(dir_in_results
, image_name
)
149 result
[trace
['path']]['actual'] = checksum
153 def run(filename
, device_name
):
155 with
open(filename
, 'r') as f
:
156 y
= yaml
.safe_load(f
)
159 project_url
= y
["traces-db"]["download-url"]
163 traces
= y
['traces'] or []
167 for expectation
in trace
['expectations']:
168 if expectation
['device'] == device_name
:
169 ok
, result
= gitlab_check_trace(project_url
,
172 all_ok
= all_ok
and ok
173 results
.update(result
)
175 os
.makedirs(RESULTS_PATH
, exist_ok
=True)
176 with
open(os
.path
.join(RESULTS_PATH
, 'results.yml'), 'w') as f
:
177 yaml
.safe_dump(results
, f
, default_flow_style
=False)
178 if os
.environ
.get('TRACIE_UPLOAD_TO_MINIO', '0') == '1':
179 upload_artifact(os
.path
.join(RESULTS_PATH
, 'results.yml'), 'traces/results.yml', 'text/yaml')
184 parser
= argparse
.ArgumentParser()
185 parser
.add_argument('--file', required
=True,
186 help='the name of the traces.yml file listing traces and their checksums for each device')
187 parser
.add_argument('--device-name', required
=True,
188 help="the name of the graphics device used to replay traces")
190 args
= parser
.parse_args(args
)
191 return run(args
.file, args
.device_name
)
193 if __name__
== "__main__":
194 all_ok
= main(sys
.argv
[1:])
195 sys
.exit(0 if all_ok
else 1)