| #!/usr/bin/env vpython3 | 
 |  | 
 | # Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. | 
 | # | 
 | # Use of this source code is governed by a BSD-style license | 
 | # that can be found in the LICENSE file in the root of the source | 
 | # tree. An additional intellectual property rights grant can be found | 
 | # in the file PATENTS.  All contributing project authors may | 
 | # be found in the AUTHORS file in the root of the source tree. | 
 | """Adds build info to perf results and uploads them. | 
 |  | 
 | The tests don't know which bot executed the tests or at what revision, so we | 
 | need to take their output and enrich it with this information. We load the proto | 
 | from the tests, add the build information as shared diagnostics and then | 
 | upload it to the dashboard. | 
 |  | 
 | This script can't be in recipes, because we can't access the catapult APIs from | 
 | there. It needs to be here source-side. | 
 | """ | 
 |  | 
 | import argparse | 
 | import json | 
 | import os | 
 | import sys | 
 |  | 
 | from pathlib import Path | 
 |  | 
 | # Even if protobuf is not used directly, this allows transitive imports | 
 | # of the protobuf library to use the vpython wheel specified in the root | 
 | # level .vpython (see bugs.webrtc.org/12211 for context). | 
 | import google.protobuf  # pylint: disable=unused-import | 
 |  | 
 |  | 
 | def _ConfigurePythonPath(outdir): | 
 |   # We just yank the python scripts we require into the PYTHONPATH. You could | 
 |   # also imagine a solution where we use for instance | 
 |   # protobuf:py_proto_runtime to copy catapult and protobuf code to out/. | 
 |   # This is the convention in Chromium and WebRTC python scripts. We do need | 
 |   # to build histogram_pb2 however, so that's why we add out/ to sys.path | 
 |   # below. | 
 |   # | 
 |   # It would be better if there was an equivalent to py_binary in GN, but | 
 |   # there's not. | 
 |   script_dir = os.path.dirname(os.path.realpath(__file__)) | 
 |   checkout_root = os.path.abspath(os.path.join(script_dir, os.pardir, | 
 |                                                os.pardir)) | 
 |  | 
 |   sys.path.insert( | 
 |       0, os.path.join(checkout_root, 'third_party', 'catapult', 'tracing')) | 
 |   sys.path.insert( | 
 |       0, os.path.join(checkout_root, 'third_party', 'protobuf', 'python')) | 
 |  | 
 |   # The webrtc_dashboard_upload gn rule will build the protobuf stub for | 
 |   # python, so put it in the path for this script before we attempt to import | 
 |   # it. | 
 |   histogram_proto_path = os.path.join(outdir, 'pyproto', 'tracing', 'tracing', | 
 |                                       'proto') | 
 |   sys.path.insert(0, histogram_proto_path) | 
 |  | 
 |   # Fail early in case the proto hasn't been built. | 
 |   from tracing.proto import histogram_proto | 
 |   if not histogram_proto.HAS_PROTO: | 
 |     print('Could not find histogram_pb2. You need to build the ' | 
 |           'webrtc_dashboard_upload target before invoking this ' | 
 |           'script. Expected to find ' | 
 |           'histogram_pb2.py in %s.' % histogram_proto_path) | 
 |     return 1 | 
 |   return 0 | 
 |  | 
 |  | 
 | def _UploadToDasboard(args): | 
 |   build_properties = json.loads(args.build_properties) | 
 |   exit_code = _ConfigurePythonPath(build_properties['outdir']) | 
 |   if exit_code != 0: | 
 |     return exit_code | 
 |  | 
 |   import catapult_uploader | 
 |  | 
 |   perftest_outputs = [ | 
 |       f.absolute() for f in Path(args.task_output_dir).rglob('perftest-output*') | 
 |       if f.is_file() | 
 |   ] | 
 |   for perftest_output in perftest_outputs: | 
 |     uploader_options = catapult_uploader.UploaderOptions( | 
 |         perf_dashboard_machine_group=( | 
 |             build_properties['perf_dashboard_machine_group']), | 
 |         bot=build_properties['bot'], | 
 |         webrtc_git_hash=build_properties['webrtc_git_hash'], | 
 |         commit_position=build_properties['commit_position'], | 
 |         build_page_url=build_properties['build_page_url'], | 
 |         dashboard_url=build_properties['dashboard_url'], | 
 |         test_suite=args.test_suite, | 
 |         input_results_file=perftest_output, | 
 |     ) | 
 |     exit_code = catapult_uploader.UploadToDashboard(uploader_options) | 
 |     if exit_code != 0: | 
 |       return exit_code | 
 |   return 0 | 
 |  | 
 |  | 
 | def main(): | 
 |   parser = argparse.ArgumentParser() | 
 |   parser.add_argument('--build-properties', help=argparse.SUPPRESS) | 
 |   parser.add_argument('--summary-json', help=argparse.SUPPRESS) | 
 |   parser.add_argument('--task-output-dir', help=argparse.SUPPRESS) | 
 |   parser.add_argument('--test-suite', help=argparse.SUPPRESS) | 
 |   parser.add_argument('-o', '--output-json', help=argparse.SUPPRESS) | 
 |   parser.add_argument('json_files', nargs='*', help=argparse.SUPPRESS) | 
 |   args = parser.parse_args() | 
 |  | 
 |   exit_code = _UploadToDasboard(args) | 
 |   if exit_code != 0: | 
 |     with open(args.output_json, 'w') as f: | 
 |       json.dump({ | 
 |           "global_tags": ["UNRELIABLE_RESULTS"], | 
 |           "missing_shards": [0] | 
 |       }, f) | 
 |     return exit_code | 
 |   return 0 | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |   sys.exit(main()) |