def get_baseline_task_id(evg_api_config: str, current_task_id: str) -> str: """Get the most recent successful task prior to the current task.""" evg_api = RetryingEvergreenApi.get_api(config_file=evg_api_config) current_task = evg_api.task_by_id(current_task_id) base_version = evg_api.version_by_id( f"{current_task.json['project_identifier'].replace('-', '_')}_{current_task.revision}" ) prior_versions = evg_api.versions_by_project(current_task.project_id, start=base_version.order) for version in prior_versions: baseline_task_candidate = None build = version.build_by_variant(current_task.build_variant) for task in build.get_tasks(): if task.display_name == current_task.display_name: baseline_task_candidate = task break # If previous build doesn't contain the task with the same 'display_name' # assume that this is a new task and there is no baseline task if baseline_task_candidate is None: return "" if baseline_task_candidate.is_success(): return baseline_task_candidate.task_id return ""
def execute(self) -> None: """ Work your magic. :return: None """ if self._ticket: # TODO: SERVER-50693 print("JIRA tickets not yet implemented") return assert self._task_id evg = RetryingEvergreenApi.get_api(use_config_file=True) artifacts = evg.task_by_id(self._task_id).artifacts url = _find_undodb_artifact_url(artifacts) if not url: print( f"Evergreen task '{self._task_id}' does not have an UndoDB recordings archive attached to it" ) return local_file = _download_archive(url) if not local_file: print(f"Failed to download archive from '{url}'") return _extract_archive(local_file) _cleanup(local_file)
def main(argv=None): """Execute Main function to validate commit messages.""" parser = argparse.ArgumentParser( usage="Validate the commit message. " "It validates the latest message when no arguments are provided.") parser.add_argument( "version_id", metavar="version id", help="The id of the version to validate", ) args = parser.parse_args(argv) evg_api = RetryingEvergreenApi.get_api(config_file=EVG_CONFIG_FILE) code_changes = evg_api.patch_by_id(args.version_id).module_code_changes for change in code_changes: for message in change.commit_messages: if any( valid_pattern.match(message) for valid_pattern in VALID_PATTERNS): continue elif any( private_pattern.match(message) for private_pattern in PRIVATE_PATTERNS): error_type = "Found a reference to a private project" else: error_type = "Found a commit without a ticket" if error_type: LOGGER.error(f"{error_type}\n{message}") # pylint: disable=logging-fstring-interpolation return STATUS_ERROR return STATUS_OK
def main(build_variant: str, run_build_variant: str, distro: str, project: str, generate_tasks_file: str, repeat_tests_num: Optional[int], repeat_tests_min: Optional[int], repeat_tests_max: Optional[int], repeat_tests_secs: Optional[int], evg_api_config: str, verbose: bool, task_id: str): """ Run new or changed tests in repeated mode to validate their stability. burn_in_tests detects jstests that are new or changed since the last git command and then runs those tests in a loop to validate their reliability. The `--repeat-*` arguments allow configuration of how burn_in_tests repeats tests. Tests can either be repeated a specified number of times with the `--repeat-tests` option, or they can be repeated for a certain time period with the `--repeat-tests-secs` option. Specifying the `--generate-tasks-file`, burn_in_tests will run generate a configuration file that can then be sent to the Evergreen 'generate.tasks' command to create evergreen tasks to do all the test executions. This is the mode used to run tests in patch builds. NOTE: There is currently a limit of the number of tasks burn_in_tests will attempt to generate in evergreen. The limit is 1000. If you change enough tests that more than 1000 tasks would be generated, burn_in_test will fail. This is to avoid generating more tasks than evergreen can handle. \f :param build_variant: Build variant to query tasks from. :param run_build_variant:Build variant to actually run against. :param distro: Distro to run tests on. :param project: Project to run tests on. :param generate_tasks_file: Create a generate tasks configuration in this file. :param repeat_tests_num: Repeat each test this number of times. :param repeat_tests_min: Repeat each test at least this number of times. :param repeat_tests_max: Once this number of repetitions has been reached, stop repeating. :param repeat_tests_secs: Continue repeating tests for this number of seconds. :param evg_api_config: Location of configuration file to connect to evergreen. :param verbose: Log extra debug information. :param task_id: Id of evergreen task being run in. """ _configure_logging(verbose) repeat_config = RepeatConfig(repeat_tests_secs=repeat_tests_secs, repeat_tests_min=repeat_tests_min, repeat_tests_max=repeat_tests_max, repeat_tests_num=repeat_tests_num) # yapf: disable repos = [Repo(x) for x in DEFAULT_REPO_LOCATIONS if os.path.isdir(x)] evg_conf = parse_evergreen_file(EVERGREEN_FILE) evg_api = RetryingEvergreenApi.get_api(config_file=evg_api_config) generate_config = GenerateConfig(build_variant=build_variant, run_build_variant=run_build_variant, distro=distro, project=project, task_id=task_id) # yapf: disable generate_config.validate(evg_conf) burn_in(task_id, build_variant, generate_config, repeat_config, evg_api, evg_conf, repos, generate_tasks_file)
def get_summary_for_patch(version_id: str) -> str: """ Get the description provided for the given patch build. :param version_id: Version ID of the patch build to query. :return: Description provided for the patch build. """ evg_api = RetryingEvergreenApi.get_api(config_file=EVG_CONFIG_FILE) return evg_api.version_by_id(version_id).message
def get_evergreen_api() -> EvergreenApi: """Return evergreen API.""" # Pickup the first config file found in common locations. for file in EVERGREEN_CONFIG_LOCATIONS: if os.path.isfile(file): evg_api = RetryingEvergreenApi.get_api(config_file=file) return evg_api LOGGER.error("Evergreen config not found in locations.", locations=EVERGREEN_CONFIG_LOCATIONS) sys.exit(1)
def dependencies(binder: inject.Binder) -> None: binder.bind(EvgExpansions, evg_expansions) binder.bind(SuiteSplitConfig, evg_expansions.build_suite_split_config(start_date, end_date)) binder.bind(SplitStrategy, greedy_division) binder.bind(FallbackStrategy, round_robin_fallback) binder.bind(GenTaskOptions, evg_expansions.build_evg_config_gen_options()) binder.bind(EvergreenApi, RetryingEvergreenApi.get_api(config_file=evg_api_config)) binder.bind(EvergreenProjectConfig, parse_evergreen_file(evg_project_config)) binder.bind(GenerationConfiguration, GenerationConfiguration.from_yaml_file()) binder.bind(ResmokeProxyService, ResmokeProxyService(" ".join(resmoke_run_args)))
def dependencies(binder: inject.Binder) -> None: binder.bind(SuiteSplitService, None) binder.bind(GenTaskOptions, evg_expansions.gen_task_options()) binder.bind(EvergreenApi, RetryingEvergreenApi.get_api(config_file=evergreen_config)) binder.bind( GenerationConfiguration, GenerationConfiguration.from_yaml_file(GENERATE_CONFIG_FILE)) binder.bind( ResmokeProxyConfig, ResmokeProxyConfig(resmoke_suite_dir=DEFAULT_TEST_SUITE_DIR))
def get_historic_stats(evg_api_config: str, project_id: str, test_files: List[str], task_name: str, build_variant: str) -> List[TestStats]: """Get historic test stats.""" evg_api = RetryingEvergreenApi.get_api(config_file=evg_api_config) before_date = datetime.today() after_date = before_date - timedelta(days=LOOK_BACK_NUM_DAYS) base_task_name = get_task_name_without_suffix(task_name, build_variant).replace( BURN_IN_PREFIX, "") return evg_api.test_stats_by_project(project_id=project_id, after_date=after_date, before_date=before_date, tests=test_files, tasks=[base_task_name], variants=[build_variant])
def get_evergreen_api(evergreen_config=None): """Return evergreen API.""" config_to_pass = evergreen_config if not config_to_pass: # Pickup the first config file found in common locations. for file in EVERGREEN_CONFIG_LOCATIONS: if os.path.isfile(file): config_to_pass = file break try: evg_api = RetryingEvergreenApi.get_api(config_file=config_to_pass) except Exception as ex: LOGGER.error("Most likely something is wrong with evergreen config file.", config_file=config_to_pass) raise ex else: return evg_api
def dependencies(binder: inject.Binder) -> None: binder.bind( EvergreenApi, RetryingEvergreenApi.get_api( config_file=os.path.expanduser(options.evg_api_config))) binder.bind(TimeoutSettings, TimeoutSettings(start_date=start_date, end_date=end_date)) binder.bind(TimeoutOverrides, timeout_overrides) binder.bind( EvergreenProjectConfig, parse_evergreen_file(os.path.expanduser( options.evg_project_config))) binder.bind( ResmokeProxyService, ResmokeProxyService( run_options=f"--installDir={shlex.quote(options.install_dir)}") )
def main(argv=None): """Execute Main function to validate commit messages.""" parser = argparse.ArgumentParser( usage="Validate the commit message. " "It validates the latest message when no arguments are provided.") parser.add_argument( "version_id", metavar="version id", help="The id of the version to validate", ) parser.add_argument( "--evg-config-file", default=EVG_CONFIG_FILE, help="Path to evergreen configuration file containing auth information." ) args = parser.parse_args(argv) evg_api = RetryingEvergreenApi.get_api( config_file=os.path.expanduser(args.evg_config_file)) return validate_commit_messages(args.version_id, evg_api)
def get_evergreen_version(evg_api: RetryingEvergreenApi, evg_ref: str) -> Optional[Version]: """Return evergreen version by reference (commit_hash or evergreen_version_id).""" from buildscripts.resmokelib import multiversionconstants # Evergreen reference as evergreen_version_id evg_refs = [evg_ref] # Evergreen reference as {project_name}_{commit_hash} evg_refs.extend( f"{proj.replace('-', '_')}_{evg_ref}" for proj in multiversionconstants.EVERGREEN_PROJECTS) for ref in evg_refs: try: evg_version = evg_api.version_by_id(ref) except HTTPError: continue else: LOGGER.debug("Found evergreen version.", evergreen_version=f"{EVERGREEN_HOST}/version/{evg_version.version_id}") return evg_version return None
def main(argv: Optional[List[str]] = None) -> int: """Execute Main function to validate commit messages.""" parser = argparse.ArgumentParser( usage="Validate the commit message. " "It validates the latest message when no arguments are provided.") parser.add_argument( "version_id", metavar="version id", help="The id of the version to validate", ) parser.add_argument( "--evg-config-file", default=EVG_CONFIG_FILE, help="Path to evergreen configuration file containing auth information.", ) args = parser.parse_args(argv) evg_api = RetryingEvergreenApi.get_api(config_file=os.path.expanduser(args.evg_config_file)) jira_auth = JiraAuth() jira_client = JiraClient(JIRA_SERVER, jira_auth) orchestrator = CommitMessageValidationOrchestrator(evg_api, jira_client) return orchestrator.validate_commit_messages(args.version_id)
def get_evergreen_api(evergreen_config=None): """Return evergreen API.""" if evergreen_config: possible_configs = [evergreen_config] else: possible_configs = _find_evergreen_yaml_candidates() if not possible_configs: LOGGER.error("Could not find .evergreen.yml", candidates=possible_configs) raise RuntimeError("Could not find .evergreen.yml") last_ex = None for config in possible_configs: try: return RetryingEvergreenApi.get_api(config_file=config) # except Exception as ex: # pylint: disable=broad-except last_ex = ex continue LOGGER.error( "Could not connect to Evergreen with any .evergreen.yml files available on this system", config_file_candidates=possible_configs) raise last_ex