#!/usr/bin/env python # Copyright 2018 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Checks that the main console and subconsole configs are consistent.""" import collections import difflib import os import sys THIS_DIR = os.path.dirname(os.path.abspath(__file__)) SRC_ROOT = os.path.join(THIS_DIR, '..', '..') sys.path.insert(1, os.path.join( SRC_ROOT, "third_party", "protobuf", "python")) import google.protobuf.text_format import project_pb2 def compare_builders(name, main_builders, sub_builders): # Checks that the builders on a subwaterfall on the main waterfall # are consistent with the builders on that subwaterfall's main page. # For example, checks that the builders on the "chromium.win" section # are the same as on the dedicated standalone chromium.win waterfall. def to_list(builders, category_prefix=''): desc_list = [] for builder in builders: desc_list.append('name: ' + ', '.join(builder.name)) # A bot with "chromium.win|foo|bar" on the main waterfall should have # a category of "foo|bar" on the "chromium.win" subwaterfall. category = builder.category if category_prefix: if category: category = category_prefix + '|' + category else: category = category_prefix desc_list.append('category: ' + category) desc_list.append('short_name: ' + builder.short_name) return desc_list main_desc = to_list(main_builders) sub_desc = to_list(sub_builders, name) if main_desc != sub_desc: print ('bot lists different between main waterfall ' + 'and stand-alone %s waterfall:' % name) print '\n'.join(difflib.unified_diff(main_desc, sub_desc, fromfile='main', tofile=name, lineterm='')) print return False return True def main(): project = project_pb2.Project() with open(os.path.join(THIS_DIR, 'generated', 'luci-milo.cfg'), 'rb') as f: google.protobuf.text_format.Parse(f.read(), project) # Maps subwaterfall name to list of builders on that subwaterfall # on the main waterfall. subwaterfalls = collections.defaultdict(list) for console in project.consoles: if console.id == 'main': # Chromium main waterfall console. for builder in console.builders: subwaterfall = builder.category.split('|', 1)[0] subwaterfalls[subwaterfall].append(builder) # subwaterfalls contains the waterfalls referenced by the main console # Check that every referenced subwaterfall has its own console, unless it's # explicitly excluded below. excluded_names = [ # This is the chrome console in src-internal. 'chrome', ] all_console_names = [console.id for console in project.consoles] referenced_names = set(subwaterfalls.keys()) missing_names = referenced_names - set(all_console_names + excluded_names) if missing_names: print 'Missing subwaterfall console for', missing_names return 1 # Check that the bots on a subwaterfall match the corresponding bots on the # main waterfall all_good = True for console in project.consoles: if console.id in subwaterfalls: if not compare_builders(console.id, subwaterfalls[console.id], console.builders): all_good = False return 0 if all_good else 1 if __name__ == '__main__': sys.exit(main())