| #!/usr/bin/env python3 |
| # Copyright 2018 The Chromium Authors |
| # 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', 'luci-milo.cfg'), |
| 'rb') as f: |
| google.protobuf.text_format.Parse(f.read(), project, |
| allow_unknown_field=True) |
| |
| # 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()) |