#!/usr/bin/env python import argparse import datetime import decimal import json import logging import os import requests from collections import OrderedDict def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('-r', '--result-file', dest='result_file', required=True, default='./result.json', help='Specify test result file.') parser.add_argument('-a', '--attachment', dest='attachment', action='append', help='Specify attachment file.') parser.add_argument('-t', '--team', dest='team', required=True, help='Team identifier. Defaults to "erp"') parser.add_argument('-p', '--project', dest='project', help='Project identifier. Defaults to the name of the Linux distribution.') parser.add_argument('-b', '--build', dest='build', required=True, help='Build identifier.') parser.add_argument('-e', '--test-env', dest='test_env', help='Environment identifier. Defaults to board name.') parser.add_argument('-u', '--url', dest='url', default='https://qa-reports.linaro.org', help='Dashboard URL. Defaults to https://qa-reports.linaro.org.') parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=True, help='Set log level.') args = parser.parse_args() return args def squad_result(results): squad_tests = OrderedDict() squad_metrics = OrderedDict() for result in results: for metric in result['metrics']: key = '%s/%s' % (result['name'], metric['test_case_id']) if not metric['measurement']: # Collect pass/fail test results. squad_tests[key] = metric['result'] else: # Collect performance test results. try: measurement = decimal.Decimal(metric['measurement']) squad_metrics[key] = float(measurement) except decimal.InvalidOperation: logger.info('Invalid measurement: %s' % metric['measurement']) logger.info('Skipped adding: %s' % metric) assert squad_tests or squad_metrics, 'No valid result found!' return (squad_tests, squad_metrics) def squad_metadata(results): test_plan = list(set(i['test_plan'] for i in results)) test_version = list(set(i['version'] for i in results)) assert len(test_plan) == 1, 'More then one test plan found!' assert len(test_version) == 1, 'More then one test version found!' squad_metadata = OrderedDict() test_plan = test_plan[0] test_plan_name = os.path.splitext(os.path.basename(test_plan))[0] squad_metadata['job_id'] = '{}_{}'.format(test_plan_name, datetime.datetime.utcnow().isoformat()) squad_metadata['test_plan'] = test_plan squad_metadata['test_version'] = test_version[0] for key, value in results[-1]['environment'].items(): if key != 'packages': squad_metadata[key] = value return squad_metadata def main(): auth_token = os.environ.get("SQUAD_AUTH_TOKEN") assert auth_token, "SQUAD_AUTH_TOKEN not provided in environment" with open(args.result_file, 'r') as f: results = json.load(f) metadata = squad_metadata(results) tests, metrics = squad_result(results) files = [('metadata', json.dumps(metadata)), ('tests', json.dumps(tests)), ('metrics', json.dumps(metrics)), ('attachment', open(args.result_file, 'rb'))] if args.attachment is not None: for item in args.attachment: if os.path.exists(item): logger.info('Adding {} to attachment list...'.format(item)) files.append(tuple(['attachment', open(item, 'rb')])) else: logger.info('Attachment %s Not found' % args.attachment) logger.info('Skipped uploading %s' % args.attachment) logger.debug('Data to post: %s' % files) project = args.project or metadata['linux_distribution'] test_env = args.test_env or metadata['board_name'] url = '{}/api/submit/{}/{}/{}/{}'.format(args.url, args.team, project, args.build, test_env) logger.info('Posting to {}'.format(url)) headers = {'Auth-Token': auth_token} r = requests.post(url, headers=headers, files=files) print(r.text) if __name__ == "__main__": args = parse_args() logger = logging.getLogger('post-to-squad') logger.setLevel(logging.INFO) if args.verbose: logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) logger.addHandler(ch) main()