diff options
Diffstat (limited to 'deprecated/generate-waterfall-reports.py')
-rwxr-xr-x | deprecated/generate-waterfall-reports.py | 853 |
1 files changed, 0 insertions, 853 deletions
diff --git a/deprecated/generate-waterfall-reports.py b/deprecated/generate-waterfall-reports.py deleted file mode 100755 index a67cd6ca..00000000 --- a/deprecated/generate-waterfall-reports.py +++ /dev/null @@ -1,853 +0,0 @@ -#!/usr/bin/env python2 -"""Generate summary report for ChromeOS toolchain waterfalls.""" - -# Desired future features (to be added): -# - arguments to allow generating only the main waterfall report, -# or only the rotating builder reports, or only the failures -# report; or the waterfall reports without the failures report. -# - Better way of figuring out which dates/builds to generate -# reports for: probably an argument specifying a date or a date -# range, then use something like the new buildbot utils to -# query the build logs to find the right build numbers for the -# builders for the specified dates. -# - Store/get the json/data files in mobiletc-prebuild's x20 area. -# - Update data in json file to reflect, for each testsuite, which -# tests are not expected to run on which boards; update this -# script to use that data appropriately. -# - Make sure user's prodaccess is up-to-date before trying to use -# this script. -# - Add some nice formatting/highlighting to reports. - -from __future__ import print_function - -import argparse -import getpass -import json -import os -import re -import shutil -import sys -import time - -from cros_utils import command_executer - -# All the test suites whose data we might want for the reports. -TESTS = (('bvt-inline', 'HWTest'), ('bvt-cq', 'HWTest'), ('security', 'HWTest'), - ('kernel_daily_regression', 'HWTest'), ('kernel_daily_benchmarks', - 'HWTest'),) - -# The main waterfall builders, IN THE ORDER IN WHICH WE WANT THEM -# LISTED IN THE REPORT. -WATERFALL_BUILDERS = [ - 'amd64-llvm-next-toolchain', - 'arm-llvm-next-toolchain', - 'arm64-llvm-next-toolchain', -] - -DATA_DIR = '/google/data/rw/users/mo/mobiletc-prebuild/waterfall-report-data/' -ARCHIVE_DIR = '/google/data/rw/users/mo/mobiletc-prebuild/waterfall-reports/' -DOWNLOAD_DIR = '/tmp/waterfall-logs' -MAX_SAVE_RECORDS = 7 -BUILD_DATA_FILE = '%s/build-data.txt' % DATA_DIR -GCC_ROTATING_BUILDER = 'gcc_toolchain' -LLVM_ROTATING_BUILDER = 'llvm_next_toolchain' -ROTATING_BUILDERS = [GCC_ROTATING_BUILDER, LLVM_ROTATING_BUILDER] - -# For int-to-string date conversion. Note, the index of the month in this -# list needs to correspond to the month's integer value. i.e. 'Sep' must -# be as MONTHS[9]. -MONTHS = [ - '', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', - 'Nov', 'Dec' -] - - -def format_date(int_date): - """Convert an integer date to a string date. YYYYMMDD -> YYYY-MMM-DD""" - - if int_date == 0: - return 'today' - - tmp_date = int_date - day = tmp_date % 100 - tmp_date = tmp_date / 100 - month = tmp_date % 100 - year = tmp_date / 100 - - month_str = MONTHS[month] - date_str = '%d-%s-%d' % (year, month_str, day) - return date_str - - -def EmailReport(report_file, report_type, date, email_to): - subject = '%s Waterfall Summary report, %s' % (report_type, date) - sendgmr_path = '/google/data/ro/projects/gws-sre/sendgmr' - command = ('%s --to=%s --subject="%s" --body_file=%s' % - (sendgmr_path, email_to, subject, report_file)) - command_executer.GetCommandExecuter().RunCommand(command) - - -def PruneOldFailures(failure_dict, int_date): - earliest_date = int_date - MAX_SAVE_RECORDS - for suite in failure_dict: - suite_dict = failure_dict[suite] - test_keys_to_remove = [] - for test in suite_dict: - test_dict = suite_dict[test] - msg_keys_to_remove = [] - for msg in test_dict: - fails = test_dict[msg] - i = 0 - while i < len(fails) and fails[i][0] <= earliest_date: - i += 1 - new_fails = fails[i:] - test_dict[msg] = new_fails - if len(new_fails) == 0: - msg_keys_to_remove.append(msg) - - for k in msg_keys_to_remove: - del test_dict[k] - - suite_dict[test] = test_dict - if len(test_dict) == 0: - test_keys_to_remove.append(test) - - for k in test_keys_to_remove: - del suite_dict[k] - - failure_dict[suite] = suite_dict - - -def GetBuildID(build_bot, date): - """Get the build id for a build_bot at a given date.""" - day = '{day:02d}'.format(day=date % 100) - mon = MONTHS[date / 100 % 100] - date_string = mon + ' ' + day - if build_bot in WATERFALL_BUILDERS: - url = 'https://uberchromegw.corp.google.com/i/chromeos/' + \ - 'builders/%s?numbuilds=200' % build_bot - if build_bot in ROTATING_BUILDERS: - url = 'https://uberchromegw.corp.google.com/i/chromiumos.tryserver/' + \ - 'builders/%s?numbuilds=200' % build_bot - command = 'sso_client %s' % url - retval = 1 - retry_time = 3 - while retval and retry_time: - retval, output, _ = \ - command_executer.GetCommandExecuter().RunCommandWOutput(command, \ - print_to_console=False) - retry_time -= 1 - - if retval: - return [] - - out = output.split('\n') - line_num = 0 - build_id = [] - # Parse the output like this - # <td>Dec 14 10:55</td> - # <td class="revision">??</td> - # <td failure</td><td><a href="../builders/gcc_toolchain/builds/109">#109</a> - while line_num < len(out): - if date_string in out[line_num]: - if line_num + 2 < len(out): - build_num_line = out[line_num + 2] - raw_num = re.findall(r'builds/\d+', build_num_line) - # raw_num is ['builds/109'] in the example. - if raw_num: - build_id.append(int(raw_num[0].split('/')[1])) - line_num += 1 - return build_id - - -def GenerateFailuresReport(fail_dict, date): - filename = 'waterfall_report.failures.%s.txt' % date - date_string = format_date(date) - with open(filename, 'w') as out_file: - # Write failure report section. - out_file.write('\n\nSummary of Test Failures as of %s\n\n' % date_string) - - # We want to sort the errors and output them in order of the ones that occur - # most often. So we have to collect the data about all of them, then sort - # it. - error_groups = [] - for suite in fail_dict: - suite_dict = fail_dict[suite] - if suite_dict: - for test in suite_dict: - test_dict = suite_dict[test] - for err_msg in test_dict: - err_list = test_dict[err_msg] - sorted_list = sorted(err_list, key=lambda x: x[0], reverse=True) - err_group = [len(sorted_list), suite, test, err_msg, sorted_list] - error_groups.append(err_group) - - # Sort the errors by the number of errors of each type. Then output them in - # order. - sorted_errors = sorted(error_groups, key=lambda x: x[0], reverse=True) - for i in range(0, len(sorted_errors)): - err_group = sorted_errors[i] - suite = err_group[1] - test = err_group[2] - err_msg = err_group[3] - err_list = err_group[4] - out_file.write('Suite: %s\n' % suite) - out_file.write(' %s (%d failures)\n' % (test, len(err_list))) - out_file.write(' (%s)\n' % err_msg) - for i in range(0, len(err_list)): - err = err_list[i] - out_file.write(' %s, %s, %s\n' % (format_date(err[0]), err[1], - err[2])) - out_file.write('\n') - - print('Report generated in %s.' % filename) - return filename - - -def GenerateWaterfallReport(report_dict, fail_dict, waterfall_type, date, - omit_failures): - """Write out the actual formatted report.""" - - filename = 'waterfall_report.%s_waterfall.%s.txt' % (waterfall_type, date) - - date_string = '' - date_list = report_dict['date'] - num_dates = len(date_list) - i = 0 - for d in date_list: - date_string += d - if i < num_dates - 1: - date_string += ', ' - i += 1 - - if waterfall_type == 'main': - report_list = WATERFALL_BUILDERS - else: - report_list = report_dict.keys() - - with open(filename, 'w') as out_file: - # Write Report Header - out_file.write('\nStatus of %s Waterfall Builds from %s\n\n' % - (waterfall_type, date_string)) - out_file.write(' ' - ' kernel kernel\n') - out_file.write(' Build bvt- bvt-cq ' - ' security daily daily\n') - out_file.write(' status inline ' - ' regression benchmarks\n') - out_file.write(' [P/ F/ DR]* [P/ F /DR]* ' - '[P/ F/ DR]* [P/ F/ DR]* [P/ F/ DR]*\n\n') - - # Write daily waterfall status section. - for i in range(0, len(report_list)): - builder = report_list[i] - if builder == 'date': - continue - - if builder not in report_dict: - out_file.write('Unable to find information for %s.\n\n' % builder) - continue - - build_dict = report_dict[builder] - status = build_dict.get('build_status', 'bad') - inline = build_dict.get('bvt-inline', '[??/ ?? /??]') - cq = build_dict.get('bvt-cq', '[??/ ?? /??]') - inline_color = build_dict.get('bvt-inline-color', '') - cq_color = build_dict.get('bvt-cq-color', '') - if 'x86' not in builder: - security = build_dict.get('security', '[??/ ?? /??]') - security_color = build_dict.get('security-color', '') - if 'gcc' in builder: - regression = build_dict.get('kernel_daily_regression', '[??/ ?? /??]') - bench = build_dict.get('kernel_daily_benchmarks', '[??/ ?? /??]') - regression_color = build_dict.get('kernel_daily_regression-color', '') - bench_color = build_dict.get('kernel_daily_benchmarks-color', '') - out_file.write(' %6s %6s' - ' %6s %6s %6s\n' % - (inline_color, cq_color, security_color, - regression_color, bench_color)) - out_file.write('%25s %3s %s %s %s %s %s\n' % - (builder, status, inline, cq, security, regression, - bench)) - else: - out_file.write(' %6s %6s' - ' %6s\n' % (inline_color, cq_color, - security_color)) - out_file.write('%25s %3s %s %s %s\n' % (builder, status, inline, cq, - security)) - else: - out_file.write(' %6s %6s\n' % - (inline_color, cq_color)) - out_file.write('%25s %3s %s %s\n' % (builder, status, inline, cq)) - if 'build_link' in build_dict: - out_file.write('%s\n\n' % build_dict['build_link']) - - out_file.write('\n\n*P = Number of tests in suite that Passed; F = ' - 'Number of tests in suite that Failed; DR = Number of tests' - ' in suite that Didn\'t Run.\n') - - if omit_failures: - print('Report generated in %s.' % filename) - return filename - - # Write failure report section. - out_file.write('\n\nSummary of Test Failures as of %s\n\n' % date_string) - - # We want to sort the errors and output them in order of the ones that occur - # most often. So we have to collect the data about all of them, then sort - # it. - error_groups = [] - for suite in fail_dict: - suite_dict = fail_dict[suite] - if suite_dict: - for test in suite_dict: - test_dict = suite_dict[test] - for err_msg in test_dict: - err_list = test_dict[err_msg] - sorted_list = sorted(err_list, key=lambda x: x[0], reverse=True) - err_group = [len(sorted_list), suite, test, err_msg, sorted_list] - error_groups.append(err_group) - - # Sort the errors by the number of errors of each type. Then output them in - # order. - sorted_errors = sorted(error_groups, key=lambda x: x[0], reverse=True) - for i in range(0, len(sorted_errors)): - err_group = sorted_errors[i] - suite = err_group[1] - test = err_group[2] - err_msg = err_group[3] - err_list = err_group[4] - out_file.write('Suite: %s\n' % suite) - out_file.write(' %s (%d failures)\n' % (test, len(err_list))) - out_file.write(' (%s)\n' % err_msg) - for i in range(0, len(err_list)): - err = err_list[i] - out_file.write(' %s, %s, %s\n' % (format_date(err[0]), err[1], - err[2])) - out_file.write('\n') - - print('Report generated in %s.' % filename) - return filename - - -def UpdateReport(report_dict, builder, test, report_date, build_link, - test_summary, board, color): - """Update the data in our report dictionary with current test's data.""" - - if 'date' not in report_dict: - report_dict['date'] = [report_date] - elif report_date not in report_dict['date']: - # It is possible that some of the builders started/finished on different - # days, so we allow for multiple dates in the reports. - report_dict['date'].append(report_date) - - build_key = '' - if builder == GCC_ROTATING_BUILDER: - build_key = '%s-gcc-toolchain' % board - elif builder == LLVM_ROTATING_BUILDER: - build_key = '%s-llvm-next-toolchain' % board - else: - build_key = builder - - if build_key not in report_dict.keys(): - build_dict = dict() - else: - build_dict = report_dict[build_key] - - if 'build_link' not in build_dict: - build_dict['build_link'] = build_link - - if 'date' not in build_dict: - build_dict['date'] = report_date - - if 'board' in build_dict and build_dict['board'] != board: - raise RuntimeError( - 'Error: Two different boards (%s,%s) in one build (%s)!' % - (board, build_dict['board'], build_link)) - build_dict['board'] = board - - color_key = '%s-color' % test - build_dict[color_key] = color - - # Check to see if we already have a build status for this build_key - status = '' - if 'build_status' in build_dict.keys(): - # Use current build_status, unless current test failed (see below). - status = build_dict['build_status'] - - if not test_summary: - # Current test data was not available, so something was bad with build. - build_dict['build_status'] = 'bad' - build_dict[test] = '[ no data ]' - else: - build_dict[test] = test_summary - if not status: - # Current test ok; no other data, so assume build was ok. - build_dict['build_status'] = 'ok' - - report_dict[build_key] = build_dict - - -def UpdateBuilds(builds): - """Update the data in our build-data.txt file.""" - - # The build data file records the last build number for which we - # generated a report. When we generate the next report, we read - # this data and increment it to get the new data; when we finish - # generating the reports, we write the updated values into this file. - # NOTE: One side effect of doing this at the end: If the script - # fails in the middle of generating a report, this data does not get - # updated. - with open(BUILD_DATA_FILE, 'w') as fp: - gcc_max = 0 - llvm_max = 0 - for b in builds: - if b[0] == GCC_ROTATING_BUILDER: - gcc_max = max(gcc_max, b[1]) - elif b[0] == LLVM_ROTATING_BUILDER: - llvm_max = max(llvm_max, b[1]) - else: - fp.write('%s,%d\n' % (b[0], b[1])) - if gcc_max > 0: - fp.write('%s,%d\n' % (GCC_ROTATING_BUILDER, gcc_max)) - if llvm_max > 0: - fp.write('%s,%d\n' % (LLVM_ROTATING_BUILDER, llvm_max)) - - -def GetBuilds(date=0): - """Get build id from builds.""" - - # If date is set, get the build id from waterfall. - builds = [] - - if date: - for builder in WATERFALL_BUILDERS + ROTATING_BUILDERS: - build_ids = GetBuildID(builder, date) - for build_id in build_ids: - builds.append((builder, build_id)) - return builds - - # If date is not set, we try to get the most recent builds. - # Read the values of the last builds used to generate a report, and - # increment them appropriately, to get values for generating the - # current report. (See comments in UpdateBuilds). - with open(BUILD_DATA_FILE, 'r') as fp: - lines = fp.readlines() - - for l in lines: - l = l.rstrip() - words = l.split(',') - builder = words[0] - build = int(words[1]) - builds.append((builder, build + 1)) - # NOTE: We are assuming here that there are always 2 daily builds in - # each of the rotating builders. I am not convinced this is a valid - # assumption. - if builder in ROTATING_BUILDERS: - builds.append((builder, build + 2)) - - return builds - - -def RecordFailures(failure_dict, platform, suite, builder, int_date, log_file, - build_num, failed): - """Read and update the stored data about test failures.""" - - # Get the dictionary for this particular test suite from the failures - # dictionary. - suite_dict = failure_dict[suite] - - # Read in the entire log file for this test/build. - with open(log_file, 'r') as in_file: - lines = in_file.readlines() - - # Update the entries in the failure dictionary for each test within this suite - # that failed. - for test in failed: - # Check to see if there is already an entry in the suite dictionary for this - # test; if so use that, otherwise create a new entry. - if test in suite_dict: - test_dict = suite_dict[test] - else: - test_dict = dict() - # Parse the lines from the log file, looking for lines that indicate this - # test failed. - msg = '' - for l in lines: - words = l.split() - if len(words) < 3: - continue - if ((words[0] == test and words[1] == 'ERROR:') or - (words[0] == 'provision' and words[1] == 'FAIL:')): - words = words[2:] - # Get the error message for the failure. - msg = ' '.join(words) - if not msg: - msg = 'Unknown_Error' - - # Look for an existing entry for this error message in the test dictionary. - # If found use that, otherwise create a new entry for this error message. - if msg in test_dict: - error_list = test_dict[msg] - else: - error_list = list() - # Create an entry for this new failure - new_item = [int_date, platform, builder, build_num] - # Add this failure to the error list if it's not already there. - if new_item not in error_list: - error_list.append([int_date, platform, builder, build_num]) - # Sort the error list by date. - error_list.sort(key=lambda x: x[0]) - # Calculate the earliest date to save; delete records for older failures. - earliest_date = int_date - MAX_SAVE_RECORDS - i = 0 - while i < len(error_list) and error_list[i][0] <= earliest_date: - i += 1 - if i > 0: - error_list = error_list[i:] - # Save the error list in the test's dictionary, keyed on error_msg. - test_dict[msg] = error_list - - # Save the updated test dictionary in the test_suite dictionary. - suite_dict[test] = test_dict - - # Save the updated test_suite dictionary in the failure dictionary. - failure_dict[suite] = suite_dict - - -def ParseLogFile(log_file, test_data_dict, failure_dict, test, builder, - build_num, build_link): - """Parse the log file from the given builder, build_num and test. - - Also adds the results for this test to our test results dictionary, - and calls RecordFailures, to update our test failure data. - """ - - print('Parsing file %s' % log_file) - lines = [] - with open(log_file, 'r') as infile: - lines = infile.readlines() - - passed = {} - failed = {} - not_run = {} - date = '' - status = '' - board = '' - num_provision_errors = 0 - build_ok = True - afe_line = '' - - for line in lines: - if line.rstrip() == '<title>404 Not Found</title>': - print('Warning: File for %s (build number %d), %s was not found.' % - (builder, build_num, test)) - build_ok = False - break - if '[ PASSED ]' in line: - test_name = line.split()[0] - if test_name != 'Suite': - passed[test_name] = True - elif '[ FAILED ]' in line: - test_name = line.split()[0] - if test_name == 'provision': - num_provision_errors += 1 - not_run[test_name] = True - elif test_name != 'Suite': - failed[test_name] = True - elif line.startswith('started: '): - date = line.rstrip() - date = date[9:] - date_obj = time.strptime(date, '%a %b %d %H:%M:%S %Y') - int_date = ( - date_obj.tm_year * 10000 + date_obj.tm_mon * 100 + date_obj.tm_mday) - date = time.strftime('%a %b %d %Y', date_obj) - elif not status and line.startswith('status: '): - status = line.rstrip() - words = status.split(':') - status = words[-1] - elif line.find('Suite passed with a warning') != -1: - status = 'WARNING' - elif line.startswith('@@@STEP_LINK@Link to suite@'): - afe_line = line.rstrip() - words = afe_line.split('@') - for w in words: - if w.startswith('http'): - afe_line = w - afe_line = afe_line.replace('&', '&') - elif 'INFO: RunCommand:' in line: - words = line.split() - for i in range(0, len(words) - 1): - if words[i] == '--board': - board = words[i + 1] - - test_dict = test_data_dict[test] - test_list = test_dict['tests'] - - if build_ok: - for t in test_list: - if not t in passed and not t in failed: - not_run[t] = True - - total_pass = len(passed) - total_fail = len(failed) - total_notrun = len(not_run) - - else: - total_pass = 0 - total_fail = 0 - total_notrun = 0 - status = 'Not found.' - if not build_ok: - return [], date, board, 0, ' ' - - build_dict = dict() - build_dict['id'] = build_num - build_dict['builder'] = builder - build_dict['date'] = date - build_dict['build_link'] = build_link - build_dict['total_pass'] = total_pass - build_dict['total_fail'] = total_fail - build_dict['total_not_run'] = total_notrun - build_dict['afe_job_link'] = afe_line - build_dict['provision_errors'] = num_provision_errors - if status.strip() == 'SUCCESS': - build_dict['color'] = 'green ' - elif status.strip() == 'FAILURE': - build_dict['color'] = ' red ' - elif status.strip() == 'WARNING': - build_dict['color'] = 'orange' - else: - build_dict['color'] = ' ' - - # Use YYYYMMDD (integer) as the build record key - if build_ok: - if board in test_dict: - board_dict = test_dict[board] - else: - board_dict = dict() - board_dict[int_date] = build_dict - - # Only keep the last 5 records (based on date) - keys_list = board_dict.keys() - if len(keys_list) > MAX_SAVE_RECORDS: - min_key = min(keys_list) - del board_dict[min_key] - - # Make sure changes get back into the main dictionary - test_dict[board] = board_dict - test_data_dict[test] = test_dict - - if len(failed) > 0: - RecordFailures(failure_dict, board, test, builder, int_date, log_file, - build_num, failed) - - summary_result = '[%2d/ %2d/ %2d]' % (total_pass, total_fail, total_notrun) - - return summary_result, date, board, int_date, build_dict['color'] - - -def DownloadLogFile(builder, buildnum, test, test_family): - - ce = command_executer.GetCommandExecuter() - os.system('mkdir -p %s/%s/%s' % (DOWNLOAD_DIR, builder, test)) - if builder in ROTATING_BUILDERS: - source = ('https://uberchromegw.corp.google.com/i/chromiumos.tryserver' - '/builders/%s/builds/%d/steps/%s%%20%%5B%s%%5D/logs/stdio' % - (builder, buildnum, test_family, test)) - build_link = ('https://uberchromegw.corp.google.com/i/chromiumos.tryserver' - '/builders/%s/builds/%d' % (builder, buildnum)) - else: - source = ('https://uberchromegw.corp.google.com/i/chromeos/builders/%s/' - 'builds/%d/steps/%s%%20%%5B%s%%5D/logs/stdio' % - (builder, buildnum, test_family, test)) - build_link = ('https://uberchromegw.corp.google.com/i/chromeos/builders/%s' - '/builds/%d' % (builder, buildnum)) - - target = '%s/%s/%s/%d' % (DOWNLOAD_DIR, builder, test, buildnum) - if not os.path.isfile(target) or os.path.getsize(target) == 0: - cmd = 'sso_client %s > %s' % (source, target) - status = ce.RunCommand(cmd) - if status != 0: - return '', '' - - return target, build_link - - -# Check for prodaccess. -def CheckProdAccess(): - status, output, _ = command_executer.GetCommandExecuter().RunCommandWOutput( - 'prodcertstatus') - if status != 0: - return False - # Verify that status is not expired - if 'expires' in output: - return True - return False - - -def ValidOptions(parser, options): - too_many_options = False - if options.main: - if options.rotating or options.failures_report: - too_many_options = True - elif options.rotating and options.failures_report: - too_many_options = True - - if too_many_options: - parser.error('Can only specify one of --main, --rotating or' - ' --failures_report.') - - conflicting_failure_options = False - if options.failures_report and options.omit_failures: - conflicting_failure_options = True - parser.error('Cannot specify both --failures_report and --omit_failures.') - - email_ok = True - if options.email and options.email.find('@') == -1: - email_ok = False - parser.error('"%s" is not a valid email address; it must contain "@..."' % - options.email) - - return not too_many_options and not conflicting_failure_options and email_ok - - -def Main(argv): - """Main function for this script.""" - parser = argparse.ArgumentParser() - parser.add_argument( - '--main', - dest='main', - default=False, - action='store_true', - help='Generate report only for main waterfall ' - 'builders.') - parser.add_argument( - '--rotating', - dest='rotating', - default=False, - action='store_true', - help='Generate report only for rotating builders.') - parser.add_argument( - '--failures_report', - dest='failures_report', - default=False, - action='store_true', - help='Only generate the failures section of the report.') - parser.add_argument( - '--omit_failures', - dest='omit_failures', - default=False, - action='store_true', - help='Do not generate the failures section of the report.') - parser.add_argument( - '--no_update', - dest='no_update', - default=False, - action='store_true', - help='Run reports, but do not update the data files.') - parser.add_argument( - '--date', - dest='date', - default=0, - type=int, - help='The date YYYYMMDD of waterfall report.') - parser.add_argument( - '--email', - dest='email', - default='', - help='Email address to use for sending the report.') - - options = parser.parse_args(argv) - - if not ValidOptions(parser, options): - return 1 - - main_only = options.main - rotating_only = options.rotating - failures_report = options.failures_report - omit_failures = options.omit_failures - date = options.date - - test_data_dict = dict() - failure_dict = dict() - - prod_access = CheckProdAccess() - if not prod_access: - print('ERROR: Please run prodaccess first.') - return - - with open('%s/waterfall-test-data.json' % DATA_DIR, 'r') as input_file: - test_data_dict = json.load(input_file) - - with open('%s/test-failure-data.json' % DATA_DIR, 'r') as fp: - failure_dict = json.load(fp) - - builds = GetBuilds(date) - - waterfall_report_dict = dict() - rotating_report_dict = dict() - int_date = 0 - for test_desc in TESTS: - test, test_family = test_desc - for build in builds: - (builder, buildnum) = build - if test.startswith('kernel') and 'llvm' in builder: - continue - if 'x86' in builder and not test.startswith('bvt'): - continue - target, build_link = DownloadLogFile(builder, buildnum, test, test_family) - - if os.path.exists(target): - test_summary, report_date, board, tmp_date, color = ParseLogFile( - target, test_data_dict, failure_dict, test, builder, buildnum, - build_link) - if not test_summary: - continue - - if tmp_date != 0: - int_date = tmp_date - - if builder in ROTATING_BUILDERS: - UpdateReport(rotating_report_dict, builder, test, report_date, - build_link, test_summary, board, color) - else: - UpdateReport(waterfall_report_dict, builder, test, report_date, - build_link, test_summary, board, color) - - PruneOldFailures(failure_dict, int_date) - - if options.email: - email_to = options.email - else: - email_to = getpass.getuser() - - if waterfall_report_dict and not rotating_only and not failures_report: - main_report = GenerateWaterfallReport(waterfall_report_dict, failure_dict, - 'main', int_date, omit_failures) - EmailReport(main_report, 'Main', format_date(int_date), email_to) - shutil.copy(main_report, ARCHIVE_DIR) - if rotating_report_dict and not main_only and not failures_report: - rotating_report = GenerateWaterfallReport( - rotating_report_dict, failure_dict, 'rotating', int_date, omit_failures) - EmailReport(rotating_report, 'Rotating', format_date(int_date), email_to) - shutil.copy(rotating_report, ARCHIVE_DIR) - - if failures_report: - failures_report = GenerateFailuresReport(failure_dict, int_date) - EmailReport(failures_report, 'Failures', format_date(int_date), email_to) - shutil.copy(failures_report, ARCHIVE_DIR) - - if not options.no_update: - with open('%s/waterfall-test-data.json' % DATA_DIR, 'w') as out_file: - json.dump(test_data_dict, out_file, indent=2) - - with open('%s/test-failure-data.json' % DATA_DIR, 'w') as out_file: - json.dump(failure_dict, out_file, indent=2) - - UpdateBuilds(builds) - - -if __name__ == '__main__': - Main(sys.argv[1:]) - sys.exit(0) |