1#!/usr/bin/env python
2# Copyright 2016 gRPC authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""Runs selected gRPC test/build tasks."""
16
17from __future__ import print_function
18
19import argparse
20import multiprocessing
21import sys
22
23import artifacts.artifact_targets as artifact_targets
24import artifacts.distribtest_targets as distribtest_targets
25import artifacts.package_targets as package_targets
26import python_utils.jobset as jobset
27import python_utils.report_utils as report_utils
28
29_TARGETS = []
30_TARGETS += artifact_targets.targets()
31_TARGETS += distribtest_targets.targets()
32_TARGETS += package_targets.targets()
33
34
35def _create_build_map():
36    """Maps task names and labels to list of tasks to be built."""
37    target_build_map = dict([(target.name, [target]) for target in _TARGETS])
38    if len(_TARGETS) > len(target_build_map.keys()):
39        raise Exception('Target names need to be unique')
40
41    label_build_map = {}
42    label_build_map['all'] = [t for t in _TARGETS]  # to build all targets
43    for target in _TARGETS:
44        for label in target.labels:
45            if label in label_build_map:
46                label_build_map[label].append(target)
47            else:
48                label_build_map[label] = [target]
49
50    if set(target_build_map.keys()).intersection(label_build_map.keys()):
51        raise Exception('Target names need to be distinct from label names')
52    return dict(target_build_map.items() + label_build_map.items())
53
54
55_BUILD_MAP = _create_build_map()
56
57argp = argparse.ArgumentParser(description='Runs build/test targets.')
58argp.add_argument(
59    '-b',
60    '--build',
61    choices=sorted(_BUILD_MAP.keys()),
62    nargs='+',
63    default=['all'],
64    help='Target name or target label to build.')
65argp.add_argument(
66    '-f',
67    '--filter',
68    choices=sorted(_BUILD_MAP.keys()),
69    nargs='+',
70    default=[],
71    help='Filter targets to build with AND semantics.')
72argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
73argp.add_argument(
74    '-t', '--travis', default=False, action='store_const', const=True)
75
76args = argp.parse_args()
77
78# Figure out which targets to build
79targets = []
80for label in args.build:
81    targets += _BUILD_MAP[label]
82
83# Among targets selected by -b, filter out those that don't match the filter
84targets = [t for t in targets if all(f in t.labels for f in args.filter)]
85targets = sorted(set(targets))
86
87# Execute pre-build phase
88prebuild_jobs = []
89for target in targets:
90    prebuild_jobs += target.pre_build_jobspecs()
91if prebuild_jobs:
92    num_failures, _ = jobset.run(
93        prebuild_jobs, newline_on_success=True, maxjobs=args.jobs)
94    if num_failures != 0:
95        jobset.message('FAILED', 'Pre-build phase failed.', do_newline=True)
96        sys.exit(1)
97
98build_jobs = []
99for target in targets:
100    build_jobs.append(target.build_jobspec())
101if not build_jobs:
102    print('Nothing to build.')
103    sys.exit(1)
104
105jobset.message('START', 'Building targets.', do_newline=True)
106num_failures, resultset = jobset.run(
107    build_jobs, newline_on_success=True, maxjobs=args.jobs)
108report_utils.render_junit_xml_report(
109    resultset, 'report_taskrunner_sponge_log.xml', suite_name='tasks')
110if num_failures == 0:
111    jobset.message(
112        'SUCCESS', 'All targets built successfully.', do_newline=True)
113else:
114    jobset.message('FAILED', 'Failed to build targets.', do_newline=True)
115    sys.exit(1)
116