• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env vpython3
2
3# Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
4#
5# Use of this source code is governed by a BSD-style license
6# that can be found in the LICENSE file in the root of the source
7# tree. An additional intellectual property rights grant can be found
8# in the file PATENTS.  All contributing project authors may
9# be found in the AUTHORS file in the root of the source tree.
10"""Adds build info to perf results and uploads them.
11
12The tests don't know which bot executed the tests or at what revision, so we
13need to take their output and enrich it with this information. We load the proto
14from the tests, add the build information as shared diagnostics and then
15upload it to the dashboard.
16
17This script can't be in recipes, because we can't access the catapult APIs from
18there. It needs to be here source-side.
19"""
20
21import argparse
22import json
23import os
24import sys
25
26from pathlib import Path
27
28# Even if protobuf is not used directly, this allows transitive imports
29# of the protobuf library to use the vpython wheel specified in the root
30# level .vpython (see bugs.webrtc.org/12211 for context).
31import google.protobuf  # pylint: disable=unused-import
32
33
34def _ConfigurePythonPath(outdir):
35  # We just yank the python scripts we require into the PYTHONPATH. You could
36  # also imagine a solution where we use for instance
37  # protobuf:py_proto_runtime to copy catapult and protobuf code to out/.
38  # This is the convention in Chromium and WebRTC python scripts. We do need
39  # to build histogram_pb2 however, so that's why we add out/ to sys.path
40  # below.
41  #
42  # It would be better if there was an equivalent to py_binary in GN, but
43  # there's not.
44  script_dir = os.path.dirname(os.path.realpath(__file__))
45  checkout_root = os.path.abspath(os.path.join(script_dir, os.pardir,
46                                               os.pardir))
47
48  sys.path.insert(
49      0, os.path.join(checkout_root, 'third_party', 'catapult', 'tracing'))
50  sys.path.insert(
51      0, os.path.join(checkout_root, 'third_party', 'protobuf', 'python'))
52
53  # The webrtc_dashboard_upload gn rule will build the protobuf stub for
54  # python, so put it in the path for this script before we attempt to import
55  # it.
56  histogram_proto_path = os.path.join(outdir, 'pyproto', 'tracing', 'tracing',
57                                      'proto')
58  sys.path.insert(0, histogram_proto_path)
59
60  # Fail early in case the proto hasn't been built.
61  from tracing.proto import histogram_proto
62  if not histogram_proto.HAS_PROTO:
63    print('Could not find histogram_pb2. You need to build the '
64          'webrtc_dashboard_upload target before invoking this '
65          'script. Expected to find '
66          'histogram_pb2.py in %s.' % histogram_proto_path)
67    return 1
68  return 0
69
70
71def _UploadToDasboard(args):
72  build_properties = json.loads(args.build_properties)
73  exit_code = _ConfigurePythonPath(build_properties['outdir'])
74  if exit_code != 0:
75    return exit_code
76
77  import catapult_uploader
78
79  perftest_outputs = [
80      f.absolute() for f in Path(args.task_output_dir).rglob('perftest-output*')
81      if f.is_file()
82  ]
83  for perftest_output in perftest_outputs:
84    uploader_options = catapult_uploader.UploaderOptions(
85        perf_dashboard_machine_group=(
86            build_properties['perf_dashboard_machine_group']),
87        bot=build_properties['bot'],
88        webrtc_git_hash=build_properties['webrtc_git_hash'],
89        commit_position=build_properties['commit_position'],
90        build_page_url=build_properties['build_page_url'],
91        dashboard_url=build_properties['dashboard_url'],
92        test_suite=args.test_suite,
93        input_results_file=perftest_output,
94    )
95    exit_code = catapult_uploader.UploadToDashboard(uploader_options)
96    if exit_code != 0:
97      return exit_code
98  return 0
99
100
101def main():
102  parser = argparse.ArgumentParser()
103  parser.add_argument('--build-properties', help=argparse.SUPPRESS)
104  parser.add_argument('--summary-json', help=argparse.SUPPRESS)
105  parser.add_argument('--task-output-dir', help=argparse.SUPPRESS)
106  parser.add_argument('--test-suite', help=argparse.SUPPRESS)
107  parser.add_argument('-o', '--output-json', help=argparse.SUPPRESS)
108  parser.add_argument('json_files', nargs='*', help=argparse.SUPPRESS)
109  args = parser.parse_args()
110
111  exit_code = _UploadToDasboard(args)
112  if exit_code != 0:
113    with open(args.output_json, 'w') as f:
114      json.dump({
115          "global_tags": ["UNRELIABLE_RESULTS"],
116          "missing_shards": [0]
117      }, f)
118    return exit_code
119  return 0
120
121
122if __name__ == '__main__':
123  sys.exit(main())
124