Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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 ""
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
 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)))
Ejemplo n.º 8
0
 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))
Ejemplo n.º 9
0
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])
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
 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)}")
     )
Ejemplo n.º 12
0
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)
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
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