xref: /aosp_15_r20/external/perfetto/tools/download_changed_screenshots.py (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker#
4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker#
8*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker#
10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker
16*6dbdd20aSAndroid Build Coastguard Workerimport argparse
17*6dbdd20aSAndroid Build Coastguard Workerimport base64
18*6dbdd20aSAndroid Build Coastguard Workerimport json
19*6dbdd20aSAndroid Build Coastguard Workerimport os
20*6dbdd20aSAndroid Build Coastguard Workerimport io
21*6dbdd20aSAndroid Build Coastguard Workerimport re
22*6dbdd20aSAndroid Build Coastguard Workerimport zipfile
23*6dbdd20aSAndroid Build Coastguard Workerimport urllib.request
24*6dbdd20aSAndroid Build Coastguard Workerfrom os import path
25*6dbdd20aSAndroid Build Coastguard Worker
26*6dbdd20aSAndroid Build Coastguard WorkerROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Worker
29*6dbdd20aSAndroid Build Coastguard Workerdef get_artifact_url(run, name):
30*6dbdd20aSAndroid Build Coastguard Worker  return f'https://storage.googleapis.com/perfetto-ci-artifacts/{run}/ui-test-artifacts/{name}'
31*6dbdd20aSAndroid Build Coastguard Worker
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Workerdef main():
34*6dbdd20aSAndroid Build Coastguard Worker  os.chdir(ROOT_DIR)
35*6dbdd20aSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
36*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
37*6dbdd20aSAndroid Build Coastguard Worker      'run',
38*6dbdd20aSAndroid Build Coastguard Worker      metavar='RUN',
39*6dbdd20aSAndroid Build Coastguard Worker      help='CI run identifier, e.g. ' +
40*6dbdd20aSAndroid Build Coastguard Worker      '\'20240923144821--cls-3258215-15--ui-clang-x86_64-release\'')
41*6dbdd20aSAndroid Build Coastguard Worker  args = parser.parse_args()
42*6dbdd20aSAndroid Build Coastguard Worker  url = get_artifact_url(args.run, 'index.html')
43*6dbdd20aSAndroid Build Coastguard Worker  with urllib.request.urlopen(url) as resp:
44*6dbdd20aSAndroid Build Coastguard Worker    handle_report(resp.read().decode('utf-8'), args.run)
45*6dbdd20aSAndroid Build Coastguard Worker
46*6dbdd20aSAndroid Build Coastguard Worker
47*6dbdd20aSAndroid Build Coastguard Workerdef sanitize(name):
48*6dbdd20aSAndroid Build Coastguard Worker  return re.sub('[ _]', '-', name)
49*6dbdd20aSAndroid Build Coastguard Worker
50*6dbdd20aSAndroid Build Coastguard Worker
51*6dbdd20aSAndroid Build Coastguard Workerdef handle_report(report: str, run: str):
52*6dbdd20aSAndroid Build Coastguard Worker  m = re.findall(
53*6dbdd20aSAndroid Build Coastguard Worker      r'playwrightReportBase64 = "data:application/zip;base64,([^"]+)"', report)
54*6dbdd20aSAndroid Build Coastguard Worker  bin = base64.b64decode(m[0])
55*6dbdd20aSAndroid Build Coastguard Worker  z = zipfile.ZipFile(io.BytesIO(bin))
56*6dbdd20aSAndroid Build Coastguard Worker  report = json.loads(z.open('report.json').read().decode())
57*6dbdd20aSAndroid Build Coastguard Worker  pngs = {}
58*6dbdd20aSAndroid Build Coastguard Worker  for f in report['files']:
59*6dbdd20aSAndroid Build Coastguard Worker    test_file = f['fileName'].removeprefix('test/')
60*6dbdd20aSAndroid Build Coastguard Worker    for t in f['tests']:
61*6dbdd20aSAndroid Build Coastguard Worker      title = sanitize(t['title'])
62*6dbdd20aSAndroid Build Coastguard Worker      for r in t['results']:
63*6dbdd20aSAndroid Build Coastguard Worker        for a in r['attachments']:
64*6dbdd20aSAndroid Build Coastguard Worker          png_name = sanitize(a['name'])
65*6dbdd20aSAndroid Build Coastguard Worker          if not png_name.endswith('-actual.png'):
66*6dbdd20aSAndroid Build Coastguard Worker            continue
67*6dbdd20aSAndroid Build Coastguard Worker          path = 'test/data/ui-screenshots/%s/%s/%s' % (
68*6dbdd20aSAndroid Build Coastguard Worker              test_file, title, png_name.replace('-actual', ''))
69*6dbdd20aSAndroid Build Coastguard Worker          pngs[path] = a['path']
70*6dbdd20aSAndroid Build Coastguard Worker
71*6dbdd20aSAndroid Build Coastguard Worker  for local_path, remote_path in pngs.items():
72*6dbdd20aSAndroid Build Coastguard Worker    url = get_artifact_url(run, remote_path)
73*6dbdd20aSAndroid Build Coastguard Worker    print(f'Downloading {local_path} from {url}')
74*6dbdd20aSAndroid Build Coastguard Worker    urllib.request.urlretrieve(url, local_path)
75*6dbdd20aSAndroid Build Coastguard Worker
76*6dbdd20aSAndroid Build Coastguard Worker  print('Done. Now run:')
77*6dbdd20aSAndroid Build Coastguard Worker  print('./tools/test_data upload  (or status)')
78*6dbdd20aSAndroid Build Coastguard Worker
79*6dbdd20aSAndroid Build Coastguard Worker
80*6dbdd20aSAndroid Build Coastguard Workerif __name__ == "__main__":
81*6dbdd20aSAndroid Build Coastguard Worker  main()
82