summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuildscripts/evergreen_generate_resmoke_tasks.py162
-rw-r--r--buildscripts/tests/test_evergreen_generate_resmoke_tasks.py26
-rw-r--r--etc/pip/components/resmoke.req2
-rw-r--r--etc/pip/constraints.txt8
4 files changed, 140 insertions, 58 deletions
diff --git a/buildscripts/evergreen_generate_resmoke_tasks.py b/buildscripts/evergreen_generate_resmoke_tasks.py
index 35a72dbc74d..729c81ecfe9 100755
--- a/buildscripts/evergreen_generate_resmoke_tasks.py
+++ b/buildscripts/evergreen_generate_resmoke_tasks.py
@@ -60,6 +60,10 @@ ConfigOptions = namedtuple("ConfigOptions", [
"variant",
"use_large_distro",
"large_distro_name",
+ "use_multiversion",
+ "is_patch",
+ "depends_on",
+ "requires",
])
@@ -73,6 +77,13 @@ def enable_logging():
)
+def split_if_exists(str_to_split):
+ """Split the given string on ',' if it is not None."""
+ if str_to_split:
+ return str_to_split.split(',')
+ return None
+
+
def get_config_options(cmd_line_options, config_file):
"""
Get the configuration to use for generated tests.
@@ -83,6 +94,7 @@ def get_config_options(cmd_line_options, config_file):
:param config_file: config file to use.
:return: ConfigOptions to use.
"""
+ # pylint: disable=too-many-locals
config_file_data = read_config.read_config_file(config_file)
fallback_num_sub_suites = read_config.get_config_value(
@@ -108,10 +120,18 @@ def get_config_options(cmd_line_options, config_file):
config_file_data, default=False)
large_distro_name = read_config.get_config_value("large_distro_name", cmd_line_options,
config_file_data)
+ use_multiversion = read_config.get_config_value("use_multiversion", cmd_line_options,
+ config_file_data)
+ is_patch = read_config.get_config_value("is_patch", cmd_line_options, config_file_data)
+ depends_on = split_if_exists(
+ read_config.get_config_value("depends_on", cmd_line_options, config_file_data))
+ requires = split_if_exists(
+ read_config.get_config_value("requires", cmd_line_options, config_file_data))
return ConfigOptions(fallback_num_sub_suites, max_sub_suites, project, resmoke_args,
resmoke_jobs_max, target_resmoke_time, run_multiple_jobs, suite, task,
- variant, use_large_distro, large_distro_name)
+ variant, use_large_distro, large_distro_name, use_multiversion, is_patch,
+ depends_on, requires)
def divide_remaining_tests_among_suites(remaining_tests_runtimes, suites):
@@ -173,6 +193,9 @@ def generate_subsuite_file(source_suite_name, target_suite_name, roots=None, exc
out.write(HEADER_TEMPLATE.format(file=__file__, suite_file=source_file))
if roots:
suite_config['selector']['roots'] = roots
+
+ if 'exclude_files' in suite_config['selector']:
+ del suite_config['selector']['exclude_files']
if excludes:
suite_config['selector']['exclude_files'] = excludes
out.write(yaml.dump(suite_config, default_flow_style=False, Dumper=yaml.SafeDumper))
@@ -197,35 +220,38 @@ def prepare_directory_for_suite(directory):
os.makedirs(directory)
-def generate_evg_config(suites, options):
- """Generate evergreen configuration for the given suites."""
- evg_config = Configuration()
-
- task_names = []
- task_specs = []
+class EvergreenConfigGenerator(object):
+ """Generate evergreen configurations."""
- def generate_task(sub_suite_name, sub_task_name, max_test_runtime=None,
- expected_suite_runtime=None):
- """Generate evergreen config for a resmoke task."""
- task_names.append(sub_task_name)
- spec = TaskSpec(sub_task_name)
- if options.use_large_distro:
- spec.distro(options.large_distro_name)
- task_specs.append(spec)
- task = evg_config.task(sub_task_name)
+ def __init__(self, suites, options):
+ """Create new EvergreenConfigGenerator object."""
+ self.suites = suites
+ self.options = options
+ self.evg_config = Configuration()
+ self.task_specs = []
+ self.task_names = []
+
+ def _set_task_distro(self, task_spec):
+ if self.options.use_large_distro and self.options.large_distro_name:
+ task_spec.distro(self.options.large_distro_name)
+
+ def _get_run_tests_vars(self, suite_file):
+ variables = {
+ "resmoke_args": "--suites={0}.yml {1}".format(suite_file, self.options.resmoke_args),
+ "run_multiple_jobs": self.options.run_multiple_jobs,
+ "task": self.options.task,
+ }
- target_suite_file = os.path.join(CONFIG_DIR, sub_suite_name)
+ if self.options.resmoke_jobs_max:
+ variables["resmoke_jobs_max"] = self.options.resmoke_jobs_max
- run_tests_vars = {
- "resmoke_args": "--suites={0}.yml {1}".format(target_suite_file, options.resmoke_args),
- "run_multiple_jobs": options.run_multiple_jobs,
- "task": options.task,
- }
+ if self.options.use_multiversion:
+ variables["task_path_suffix"] = self.options.use_multiversion
- if options.resmoke_jobs_max:
- run_tests_vars["resmoke_jobs_max"] = options.resmoke_jobs_max
+ return variables
- commands = []
+ @staticmethod
+ def _add_timeout_command(commands, max_test_runtime, expected_suite_runtime):
if max_test_runtime or expected_suite_runtime:
cmd_timeout = CmdTimeoutUpdate()
if max_test_runtime:
@@ -234,26 +260,69 @@ def generate_evg_config(suites, options):
cmd_timeout.exec_timeout(int(math.ceil(expected_suite_runtime * 3)))
commands.append(cmd_timeout.validate().resolve())
- commands += [
- CommandDefinition().function("do setup"),
- CommandDefinition().function("run generated tests").vars(run_tests_vars)
- ]
- task.dependency(TaskDependency("compile")).commands(commands)
+ def _add_dependencies(self, task):
+ task.dependency(TaskDependency("compile"))
+ if not self.options.is_patch:
+ # Don't worry about task dependencies in patch builds, only mainline.
+ if self.options.depends_on:
+ for dep in self.options.depends_on:
+ task.dependency(TaskDependency(dep))
+ if self.options.requires:
+ for dep in self.options.requires:
+ task.requires(TaskDependency(dep))
+
+ return task
+
+ def _generate_task(self, sub_suite_name, sub_task_name, max_test_runtime=None,
+ expected_suite_runtime=None):
+ """Generate evergreen config for a resmoke task."""
+ spec = TaskSpec(sub_task_name)
+ self._set_task_distro(spec)
+ self.task_specs.append(spec)
+
+ self.task_names.append(sub_task_name)
+ task = self.evg_config.task(sub_task_name)
- for idx, suite in enumerate(suites):
- sub_task_name = taskname.name_generated_task(options.task, idx, len(suites),
- options.variant)
- generate_task(suite.name, sub_task_name, suite.max_runtime, suite.get_runtime())
+ target_suite_file = os.path.join(CONFIG_DIR, sub_suite_name)
+ run_tests_vars = self._get_run_tests_vars(target_suite_file)
+
+ commands = []
+ self._add_timeout_command(commands, max_test_runtime, expected_suite_runtime)
+ commands.append(CommandDefinition().function("do setup"))
+ if self.options.use_multiversion:
+ commands.append(CommandDefinition().function("do multiversion setup"))
+ commands.append(CommandDefinition().function("run generated tests").vars(run_tests_vars))
+
+ self._add_dependencies(task).commands(commands)
+
+ def _generate_all_tasks(self):
+ for idx, suite in enumerate(self.suites):
+ sub_task_name = taskname.name_generated_task(self.options.task, idx, len(self.suites),
+ self.options.variant)
+ self._generate_task(suite.name, sub_task_name, suite.max_runtime, suite.get_runtime())
+
+ # Add the misc suite
+ misc_suite_name = "{0}_misc".format(self.options.suite)
+ self._generate_task(misc_suite_name, "{0}_misc_{1}".format(self.options.task,
+ self.options.variant))
+
+ def _generate_display_task(self):
+ dt = DisplayTaskDefinition(self.options.task)\
+ .execution_tasks(self.task_names) \
+ .execution_task("{0}_gen".format(self.options.task))
+ return dt
- # Add the misc suite
- misc_suite_name = "{0}_misc".format(options.suite)
- generate_task(misc_suite_name, "{0}_misc_{1}".format(options.task, options.variant))
+ def _generate_variant(self):
+ self._generate_all_tasks()
- dt = DisplayTaskDefinition(options.task).execution_tasks(task_names) \
- .execution_task("{0}_gen".format(options.task))
- evg_config.variant(options.variant).tasks(task_specs).display_task(dt)
+ self.evg_config.variant(self.options.variant)\
+ .tasks(self.task_specs)\
+ .display_task(self._generate_display_task())
- return evg_config
+ def generate_config(self):
+ """Generate evergreen configuration."""
+ self._generate_variant()
+ return self.evg_config
class TestStats(object):
@@ -386,8 +455,15 @@ class Main(object):
help="Build variant being run against.")
parser.add_argument("--use-large-distro", dest="use_large_distro",
help="Should subtasks use large distros.")
- parser.add_argument("--large_distro_name", dest="large_distro_name",
+ parser.add_argument("--large-distro-name", dest="large_distro_name",
help="Name of large distro.")
+ parser.add_argument("--use-multiversion", dest="use_multiversion",
+ help="Task path suffix for multiversion generated tasks.")
+ parser.add_argument("--is-patch", dest="is_patch", help="Is this part of a patch build.")
+ parser.add_argument("--depends-on", dest="depends_on",
+ help="Generate depends on for these tasks.")
+ parser.add_argument("--requires", dest="requires",
+ help="Generate requires for these tasks.")
parser.add_argument("--verbose", dest="verbose", action="store_true", default=False,
help="Enable verbose logging.")
@@ -451,7 +527,7 @@ class Main(object):
def write_evergreen_configuration(self, suites, task):
"""Generate the evergreen configuration for the new suite and write it to disk."""
- evg_config = generate_evg_config(suites, self.config_options)
+ evg_config = EvergreenConfigGenerator(suites, self.config_options).generate_config()
with open(os.path.join(CONFIG_DIR, task + ".json"), "w") as file_handle:
file_handle.write(evg_config.to_json())
diff --git a/buildscripts/tests/test_evergreen_generate_resmoke_tasks.py b/buildscripts/tests/test_evergreen_generate_resmoke_tasks.py
index dd4db4f34a9..ccf33ca66e6 100644
--- a/buildscripts/tests/test_evergreen_generate_resmoke_tasks.py
+++ b/buildscripts/tests/test_evergreen_generate_resmoke_tasks.py
@@ -262,7 +262,7 @@ class PrepareDirectoryForSuite(unittest.TestCase):
mock_os.makedirs.assert_called_once_with('tmp')
-class GenerateEvgConfigTest(unittest.TestCase):
+class EvergreenConfigGeneratorTest(unittest.TestCase):
@staticmethod
def generate_mock_suites(count):
suites = []
@@ -284,6 +284,8 @@ class GenerateEvgConfigTest(unittest.TestCase):
options.suite = "suite"
options.task = "suite"
options.use_large_distro = None
+ options.use_multiversion = False
+ options.is_patch = True
return options
@@ -291,7 +293,7 @@ class GenerateEvgConfigTest(unittest.TestCase):
options = self.generate_mock_options()
suites = self.generate_mock_suites(3)
- config = grt.generate_evg_config(suites, options).to_map()
+ config = grt.EvergreenConfigGenerator(suites, options).generate_config().to_map()
self.assertEqual(len(config["tasks"]), len(suites) + 1)
command1 = config["tasks"][0]["commands"][2]
@@ -304,7 +306,7 @@ class GenerateEvgConfigTest(unittest.TestCase):
options.task = "task"
suites = self.generate_mock_suites(3)
- config = grt.generate_evg_config(suites, options).to_map()
+ config = grt.EvergreenConfigGenerator(suites, options).generate_config().to_map()
self.assertEqual(len(config["tasks"]), len(suites) + 1)
display_task = config["buildvariants"][0]["display_tasks"][0]
@@ -325,7 +327,7 @@ class GenerateEvgConfigTest(unittest.TestCase):
suites = self.generate_mock_suites(3)
- config = grt.generate_evg_config(suites, options).to_map()
+ config = grt.EvergreenConfigGenerator(suites, options).generate_config().to_map()
self.assertEqual(len(config["tasks"]), len(suites) + 1)
self.assertEqual(options.large_distro_name,
@@ -333,6 +335,13 @@ class GenerateEvgConfigTest(unittest.TestCase):
class MainTest(unittest.TestCase):
+ @staticmethod
+ def get_mock_options():
+ options = Mock()
+ options.target_resmoke_time = 10
+ options.fallback_num_sub_suites = 2
+ return options
+
def test_calculate_suites(self):
evg = Mock()
evg.test_stats.return_value = [{
@@ -341,8 +350,7 @@ class MainTest(unittest.TestCase):
main = grt.Main(evg)
main.options = Mock()
- main.config_options = grt.ConfigOptions(2, 15, "project", "", 1, 10, True, "task", "suite",
- "variant", False, "")
+ main.config_options = self.get_mock_options()
with patch('os.path.exists') as exists_mock:
exists_mock.return_value = True
@@ -362,8 +370,7 @@ class MainTest(unittest.TestCase):
main = grt.Main(evg)
main.options = Mock()
main.options.execution_time_minutes = 10
- main.config_options = grt.ConfigOptions(2, 15, "project", "", 1, 30, True, "task", "suite",
- "variant", False, "")
+ main.config_options = self.get_mock_options()
main.list_tests = Mock(return_value=["test{}.js".format(i) for i in range(100)])
suites = main.calculate_suites(_DATE, _DATE)
@@ -381,8 +388,7 @@ class MainTest(unittest.TestCase):
main = grt.Main(evg)
main.options = Mock()
main.options.execution_time_minutes = 10
- main.config_options = grt.ConfigOptions(2, 15, "project", "", 1, 30, True, "task", "suite",
- "variant", False, "")
+ main.config_options = self.get_mock_options()
main.list_tests = Mock(return_value=["test{}.js".format(i) for i in range(100)])
with self.assertRaises(requests.HTTPError):
diff --git a/etc/pip/components/resmoke.req b/etc/pip/components/resmoke.req
index 8417ea6b721..f9bd3ae9adc 100644
--- a/etc/pip/components/resmoke.req
+++ b/etc/pip/components/resmoke.req
@@ -1,4 +1,4 @@
mock; python_version < "3"
PyKMIP == 0.4.0; python_version < "3" # It's now 0.8.0. We're far enough back to have API conflicts.
jinja2
-shrub.py \ No newline at end of file
+shrub.py == 0.2.0 \ No newline at end of file
diff --git a/etc/pip/constraints.txt b/etc/pip/constraints.txt
index 86d48613080..db5f2a5bd97 100644
--- a/etc/pip/constraints.txt
+++ b/etc/pip/constraints.txt
@@ -7,8 +7,8 @@
# Common requirements
asn1crypto==0.24.0
astroid==1.6.5
-boto3==1.9.65
-botocore==1.12.65
+boto3==1.9.69
+botocore==1.12.69
certifi==2018.11.29
cffi==1.11.5
chardet==3.0.4
@@ -39,7 +39,7 @@ requests-oauth==0.4.1
requests-oauthlib==1.0.0
requests-toolbelt==0.8.0
s3transfer==0.1.13
-shrub.py==0.1.0
+shrub.py==0.2.0
six==1.12.0
snowballstemmer==1.2.1
typing==3.6.6
@@ -62,7 +62,7 @@ singledispatch==3.4.0.3; python_version < "3"
# Python3 requirements
mypy==0.580; python_version > "3"
-typed-ast==1.1.0; python_version > "3"
+typed-ast==1.1.1; python_version > "3"
# Platform-specific components
pypiwin32==219; sys_platform == "win32" and python_version < "3"