summaryrefslogtreecommitdiff
path: root/buildscripts/evergreen_generate_resmoke_tasks.py
diff options
context:
space:
mode:
Diffstat (limited to 'buildscripts/evergreen_generate_resmoke_tasks.py')
-rwxr-xr-xbuildscripts/evergreen_generate_resmoke_tasks.py54
1 files changed, 15 insertions, 39 deletions
diff --git a/buildscripts/evergreen_generate_resmoke_tasks.py b/buildscripts/evergreen_generate_resmoke_tasks.py
index 230de932764..9e66986cbf5 100755
--- a/buildscripts/evergreen_generate_resmoke_tasks.py
+++ b/buildscripts/evergreen_generate_resmoke_tasks.py
@@ -6,7 +6,6 @@ Analyze the evergreen history for tests run under the given task and create new
to attempt to keep the task runtime under a specified amount.
"""
-import datetime
from datetime import timedelta
import logging
import math
@@ -15,10 +14,9 @@ import re
import sys
from collections import defaultdict
from distutils.util import strtobool # pylint: disable=no-name-in-module
-from typing import Set
+from typing import Set, List
import click
-import requests
import structlog
import yaml
@@ -30,7 +28,7 @@ from shrub.task import TaskDependency
from shrub.variant import DisplayTaskDefinition
from shrub.variant import TaskSpec
-from evergreen.api import EvergreenApi, RetryingEvergreenApi
+from evergreen.api import RetryingEvergreenApi
# Get relative imports to work when the package is not installed on the PYTHONPATH.
if __name__ == "__main__" and __package__ is None:
@@ -41,6 +39,7 @@ import buildscripts.util.read_config as read_config # pylint: disable=wrong-imp
import buildscripts.util.taskname as taskname # pylint: disable=wrong-import-position
import buildscripts.util.testname as testname # pylint: disable=wrong-import-position
from buildscripts.util.fileops import read_yaml_file # pylint: disable=wrong-import-position
+from buildscripts.util.teststats import get_stats_from_s3, HistoricalTestInformation # pylint: disable=wrong-import-position
LOGGER = structlog.getLogger(__name__)
@@ -50,7 +49,6 @@ AVG_SETUP_TIME = int(timedelta(minutes=5).total_seconds())
EVG_CONFIG_FILE = "./.evergreen.yml"
GENERATE_CONFIG_FILE = "etc/generate_subtasks_config.yml"
MIN_TIMEOUT_SECONDS = int(timedelta(minutes=5).total_seconds())
-LOOKBACK_DURATION_DAYS = 14
GEN_SUFFIX = "_gen"
HEADER_TEMPLATE = """# DO NOT EDIT THIS FILE. All manual edits will be lost.
@@ -584,7 +582,7 @@ def normalize_test_name(test_name):
class TestStats(object):
"""Represent the test statistics for the task that is being analyzed."""
- def __init__(self, evg_test_stats_results):
+ def __init__(self, evg_test_stats_results: List[HistoricalTestInformation]) -> None:
"""Initialize the TestStats with raw results from the Evergreen API."""
# Mapping from test_file to {"num_run": X, "duration": Y} for tests
self._runtime_by_test = defaultdict(dict)
@@ -595,9 +593,9 @@ class TestStats(object):
for doc in evg_test_stats_results:
self._add_stats(doc)
- def _add_stats(self, test_stats):
+ def _add_stats(self, test_stats: HistoricalTestInformation) -> None:
"""Add the statistics found in a document returned by the Evergreen test_stats/ endpoint."""
- test_file = testname.normalize_test_file(test_stats.test_file)
+ test_file = testname.normalize_test_file(test_stats.test_name)
duration = test_stats.avg_duration_pass
num_run = test_stats.num_pass
is_hook = testname.is_resmoke_hook(test_file)
@@ -701,36 +699,17 @@ class GenerateSubSuites(object):
self.generate_options = generate_config
self.test_list = []
- def calculate_suites(self, start_date, end_date):
+ def calculate_suites(self) -> List[Suite]:
"""Divide tests into suites based on statistics for the provided period."""
- try:
- evg_stats = self.get_evg_stats(self.config_options.project, start_date, end_date,
- self.config_options.task, self.config_options.variant)
- if not evg_stats:
- # This is probably a new suite, since there is no test history, just use the
- # fallback values.
- return self.calculate_fallback_suites()
+ evg_stats = get_stats_from_s3(self.config_options.project, self.config_options.task,
+ self.config_options.variant)
+
+ if evg_stats:
target_execution_time_secs = self.config_options.target_resmoke_time * 60
return self.calculate_suites_from_evg_stats(evg_stats, target_execution_time_secs)
- except requests.HTTPError as err:
- if err.response.status_code == requests.codes.SERVICE_UNAVAILABLE:
- # Evergreen may return a 503 when the service is degraded.
- # We fall back to splitting the tests into a fixed number of suites.
- LOGGER.warning("Received 503 from Evergreen, "
- "dividing the tests evenly among suites")
- return self.calculate_fallback_suites()
- else:
- raise
-
- def get_evg_stats(self, project, start_date, end_date, task, variant):
- """Collect test execution statistics data from Evergreen."""
- # pylint: disable=too-many-arguments
-
- days = (end_date - start_date).days
- return self.evergreen_api.test_stats_by_project(
- project, after_date=start_date.strftime("%Y-%m-%d"),
- before_date=end_date.strftime("%Y-%m-%d"), tasks=[task], variants=[variant],
- group_by="test", group_num_days=days)
+
+ # Since there is no test history this is probably a new suite, just use the fallback values.
+ return self.calculate_fallback_suites()
def calculate_suites_from_evg_stats(self, data, execution_time_secs):
"""Divide tests into suites that can be run in less than the specified execution time."""
@@ -778,12 +757,9 @@ class GenerateSubSuites(object):
LOGGER.info("Not generating configuration due to previous successful generation.")
return
- end_date = datetime.datetime.utcnow().replace(microsecond=0)
- start_date = end_date - datetime.timedelta(days=LOOKBACK_DURATION_DAYS)
-
prepare_directory_for_suite(CONFIG_DIR)
- suites = self.calculate_suites(start_date, end_date)
+ suites = self.calculate_suites()
LOGGER.debug("Creating suites", num_suites=len(suites), task=self.config_options.task)