Jeremy Leconte | 4fc9bd9 | 2022-03-18 10:21:07 +0100 | [diff] [blame^] | 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 | |
| 12 | The tests don't know which bot executed the tests or at what revision, so we |
| 13 | need to take their output and enrich it with this information. We load the proto |
| 14 | from the tests, add the build information as shared diagnostics and then |
| 15 | upload it to the dashboard. |
| 16 | |
| 17 | This script can't be in recipes, because we can't access the catapult APIs from |
| 18 | there. It needs to be here source-side. |
| 19 | """ |
| 20 | |
| 21 | import argparse |
| 22 | import json |
| 23 | import os |
| 24 | import sys |
| 25 | |
| 26 | from 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). |
| 31 | import google.protobuf # pylint: disable=unused-import |
| 32 | |
| 33 | |
| 34 | def _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 | |
| 71 | def _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 | |
| 101 | def 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 | |
| 122 | if __name__ == '__main__': |
| 123 | sys.exit(main()) |