Chase Qi | f2329eb | 2017-06-07 18:58:38 +0800 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | import argparse |
| 4 | import datetime |
| 5 | import decimal |
| 6 | import json |
| 7 | import logging |
| 8 | import os |
| 9 | import requests |
| 10 | from collections import OrderedDict |
| 11 | |
| 12 | |
| 13 | def parse_args(): |
| 14 | parser = argparse.ArgumentParser() |
| 15 | parser.add_argument('-r', '--result-file', dest='result_file', |
| 16 | required=True, default='./result.json', |
| 17 | help='Specify test result file.') |
| 18 | parser.add_argument('-a', '--attachment', dest='attachment', |
| 19 | action='append', help='Specify attachment file.') |
| 20 | parser.add_argument('-t', '--team', dest='team', required=True, |
| 21 | help='Team identifier. Defaults to "erp"') |
| 22 | parser.add_argument('-p', '--project', dest='project', |
| 23 | help='Project identifier. Defaults to the name of the Linux distribution.') |
| 24 | parser.add_argument('-b', '--build', dest='build', required=True, |
| 25 | help='Build identifier.') |
| 26 | parser.add_argument('-e', '--test-env', dest='test_env', |
| 27 | help='Environment identifier. Defaults to board name.') |
| 28 | parser.add_argument('-u', '--url', dest='url', |
| 29 | default='https://qa-reports.linaro.org', |
| 30 | help='Dashboard URL. Defaults to https://qa-reports.linaro.org.') |
| 31 | parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', |
| 32 | default=True, help='Set log level.') |
| 33 | |
| 34 | args = parser.parse_args() |
| 35 | return args |
| 36 | |
| 37 | |
| 38 | def squad_result(results): |
| 39 | squad_tests = OrderedDict() |
| 40 | squad_metrics = OrderedDict() |
| 41 | for result in results: |
| 42 | for metric in result['metrics']: |
| 43 | key = '%s/%s' % (result['name'], metric['test_case_id']) |
| 44 | if not metric['measurement']: |
| 45 | # Collect pass/fail test results. |
| 46 | squad_tests[key] = metric['result'] |
| 47 | else: |
| 48 | # Collect performance test results. |
| 49 | try: |
| 50 | measurement = decimal.Decimal(metric['measurement']) |
| 51 | squad_metrics[key] = float(measurement) |
| 52 | except decimal.InvalidOperation: |
| 53 | logger.info('Invalid measurement: %s' % metric['measurement']) |
| 54 | logger.info('Skipped adding: %s' % metric) |
| 55 | assert squad_tests or squad_metrics, 'No valid result found!' |
| 56 | return (squad_tests, squad_metrics) |
| 57 | |
| 58 | |
| 59 | def squad_metadata(results): |
| 60 | test_plan = list(set(i['test_plan'] for i in results)) |
| 61 | test_version = list(set(i['version'] for i in results)) |
| 62 | |
| 63 | assert len(test_plan) == 1, 'More then one test plan found!' |
| 64 | assert len(test_version) == 1, 'More then one test version found!' |
| 65 | |
| 66 | squad_metadata = OrderedDict() |
| 67 | test_plan = test_plan[0] |
| 68 | test_plan_name = os.path.splitext(os.path.basename(test_plan))[0] |
| 69 | squad_metadata['job_id'] = '{}_{}'.format(test_plan_name, datetime.datetime.utcnow().isoformat()) |
| 70 | squad_metadata['test_plan'] = test_plan |
| 71 | squad_metadata['test_version'] = test_version[0] |
| 72 | for key, value in results[-1]['environment'].items(): |
| 73 | if key != 'packages': |
| 74 | squad_metadata[key] = value |
| 75 | return squad_metadata |
| 76 | |
| 77 | |
| 78 | def main(): |
| 79 | auth_token = os.environ.get("SQUAD_AUTH_TOKEN") |
| 80 | assert auth_token, "SQUAD_AUTH_TOKEN not provided in environment" |
| 81 | |
| 82 | with open(args.result_file, 'r') as f: |
| 83 | results = json.load(f) |
| 84 | metadata = squad_metadata(results) |
| 85 | tests, metrics = squad_result(results) |
| 86 | |
| 87 | files = [('metadata', json.dumps(metadata)), |
| 88 | ('tests', json.dumps(tests)), |
| 89 | ('metrics', json.dumps(metrics)), |
| 90 | ('attachment', open(args.result_file, 'rb'))] |
| 91 | if args.attachment is not None: |
| 92 | for item in args.attachment: |
| 93 | if os.path.exists(item): |
| 94 | logger.info('Adding {} to attachment list...'.format(item)) |
| 95 | files.append(tuple(['attachment', open(item, 'rb')])) |
| 96 | else: |
| 97 | logger.info('Attachment %s Not found' % args.attachment) |
| 98 | logger.info('Skipped uploading %s' % args.attachment) |
| 99 | logger.debug('Data to post: %s' % files) |
| 100 | |
| 101 | project = args.project or metadata['linux_distribution'] |
| 102 | test_env = args.test_env or metadata['board_name'] |
| 103 | url = '{}/api/submit/{}/{}/{}/{}'.format(args.url, args.team, project, args.build, test_env) |
| 104 | logger.info('Posting to {}'.format(url)) |
| 105 | |
| 106 | headers = {'Auth-Token': auth_token} |
| 107 | r = requests.post(url, headers=headers, files=files) |
| 108 | print(r.text) |
| 109 | |
Milosz Wasilewski | 6015206 | 2020-03-02 18:53:29 +0000 | [diff] [blame] | 110 | |
Chase Qi | f2329eb | 2017-06-07 18:58:38 +0800 | [diff] [blame] | 111 | if __name__ == "__main__": |
| 112 | args = parse_args() |
| 113 | |
| 114 | logger = logging.getLogger('post-to-squad') |
| 115 | logger.setLevel(logging.INFO) |
| 116 | if args.verbose: |
| 117 | logger.setLevel(logging.DEBUG) |
| 118 | ch = logging.StreamHandler() |
| 119 | ch.setLevel(logging.DEBUG) |
| 120 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') |
| 121 | ch.setFormatter(formatter) |
| 122 | logger.addHandler(ch) |
| 123 | |
| 124 | main() |