def print_disabled_projects_info_box_step():
    info_text = ["Downstream testing is disabled for the following projects :sadpanda:"]
    for project, config in DOWNSTREAM_PROJECTS.items():
        disabled_reason = config.get("disabled_reason", None)
        if disabled_reason:
            info_text.append("* **%s**: %s" % (project, disabled_reason))

    if len(info_text) == 1:
        return None
    return create_step(
        label=":sadpanda:",
        commands=[
            'buildkite-agent annotate --append --style=info "\n' + "\n".join(info_text) + '\n"'
        ],
    )
Example #2
0
def main(
    configs,
    project_name,
    http_config,
    file_config,
    git_repository,
    monitor_flaky_tests,
    use_but,
    incompatible_flags,
):
    platform_configs = configs.get("platforms", None)
    if not platform_configs:
        raise Exception(
            "{0} pipeline configuration is empty.".format(project_name))

    pipeline_steps = []

    if configs.get("buildifier"):
        pipeline_steps.append(
            create_docker_step("Buildifier",
                               image=f"gcr.io/{CLOUD_PROJECT}/buildifier"))

    # In Bazel Downstream Project pipelines, git_repository and project_name must be specified,
    # and we should test the project at the last green commit.
    git_commit = None
    if (use_but or incompatible_flags) and git_repository and project_name:
        git_commit = get_last_green_commit(
            git_repository, DOWNSTREAM_PROJECTS[project_name]["pipeline_slug"])
    for platform in platform_configs:
        step = runner_step(
            platform,
            project_name,
            http_config,
            file_config,
            git_repository,
            git_commit,
            monitor_flaky_tests,
            use_but,
            incompatible_flags,
        )
        pipeline_steps.append(step)

    pipeline_slug = os.getenv("BUILDKITE_PIPELINE_SLUG")
    all_downstream_pipeline_slugs = []
    for _, config in DOWNSTREAM_PROJECTS.items():
        all_downstream_pipeline_slugs.append(config["pipeline_slug"])
    # We don't need to update last green commit in the following cases:
    #   1. This job is a github pull request
    #   2. This job uses a custom built Bazel binary (In Bazel Downstream Projects pipeline)
    #   3. This job doesn't run on master branch (Could be a custom build launched manually)
    #   4. We don't intend to run the same job in downstream with Bazel@HEAD (eg. google-bazel-presubmit)
    #   5. We are testing incompatible flags
    if not (is_pull_request() or use_but
            or os.getenv("BUILDKITE_BRANCH") != "master" or pipeline_slug
            not in all_downstream_pipeline_slugs or incompatible_flags):
        pipeline_steps.append("wait")

        # If all builds succeed, update the last green commit of this project
        pipeline_steps.append(
            create_step(
                label="Try Update Last Green Commit",
                commands=[
                    fetch_bazelcipy_command(),
                    python_binary() +
                    " bazelci.py try_update_last_green_commit",
                ],
            ))

    print(yaml.dump({"steps": pipeline_steps}))
def main(configs, http_config, file_config, test_incompatible_flags, test_disabled_projects):
    if not configs:
        raise Exception("Bazel downstream pipeline configuration is empty.")

    if set(configs) != set(PLATFORMS):
        raise Exception(
            "Bazel downstream pipeline needs to build Bazel on all supported platforms (has=%s vs. want=%s)."
            % (sorted(set(configs)), sorted(set(PLATFORMS)))
        )

    pipeline_steps = []

    info_box_step = print_disabled_projects_info_box_step()
    if info_box_step is not None:
        pipeline_steps.append(info_box_step)

    if not test_incompatible_flags:
        for platform in configs:
            pipeline_steps.append(
                bazel_build_step(platform, "Bazel", http_config, file_config, build_only=True)
            )

        pipeline_steps.append("wait")

    incompatible_flags = None
    if test_incompatible_flags:
        incompatible_flags_map = fetch_incompatible_flags()
        info_box_step = print_incompatible_flags_info_box_step(incompatible_flags_map)
        if info_box_step is not None:
            pipeline_steps.append(info_box_step)
        incompatible_flags = list(incompatible_flags_map.keys())

    for project, config in DOWNSTREAM_PROJECTS.items():
        disabled_reason = config.get("disabled_reason", None)
        # If test_disabled_projects is true, we add configs for disabled projects.
        # If test_disabled_projects is false, we add configs for not disbaled projects.
        if (test_disabled_projects and disabled_reason) or (
            not test_disabled_projects and not disabled_reason
        ):
            pipeline_steps.append(
                upload_project_pipeline_step(
                    project_name=project,
                    git_repository=config["git_repository"],
                    http_config=config.get("http_config", None),
                    file_config=config.get("file_config", None),
                    incompatible_flags=incompatible_flags,
                )
            )

    if test_incompatible_flags:
        pipeline_steps.append({"wait": "~", "continue_on_failure": "true"})
        current_build_number = os.environ.get("BUILDKITE_BUILD_NUMBER", None)
        if not current_build_number:
            raise Exception("Not running inside Buildkite")
        pipeline_steps.append(
            create_step(
                label="Test failing jobs with incompatible flag separately",
                commands=[
                    fetch_bazelcipy_command(),
                    fetch_incompatible_flag_verbose_failures_command(),
                    python_binary()
                    + " incompatible_flag_verbose_failures.py --build_number=%s | buildkite-agent pipeline upload"
                    % current_build_number,
                ],
            )
        )

    print(yaml.dump({"steps": pipeline_steps}))
def main(argv=None):
    if argv is None:
        argv = sys.argv[1:]

    parser = argparse.ArgumentParser(description="Bazel Culprit Finder Script")

    subparsers = parser.add_subparsers(dest="subparsers_name")

    subparsers.add_parser("culprit_finder")

    runner = subparsers.add_parser("runner")
    runner.add_argument("--project_name", type=str)
    runner.add_argument("--platform_name", type=str)
    runner.add_argument("--good_bazel_commit", type=str)
    runner.add_argument("--bad_bazel_commit", type=str)
    runner.add_argument("--needs_clean", type=bool, nargs="?", const=True)

    args = parser.parse_args(argv)

    if args.subparsers_name == "culprit_finder":
        try:
            project_name = os.environ["PROJECT_NAME"]
            platform_name = os.environ["PLATFORM_NAME"]
            good_bazel_commit = os.environ["GOOD_BAZEL_COMMIT"]
            bad_bazel_commit = os.environ["BAD_BAZEL_COMMIT"]
        except KeyError as e:
            raise Exception("Environment variable %s must be set" % str(e))

        needs_clean = False
        if "NEEDS_CLEAN" in os.environ:
            needs_clean = True

        if project_name not in DOWNSTREAM_PROJECTS:
            raise Exception(
                "Project name '%s' not recognized, available projects are %s"
                % (project_name, str((DOWNSTREAM_PROJECTS.keys())))
            )

        if platform_name not in PLATFORMS:
            raise Exception(
                "Platform name '%s' not recognized, available platforms are %s"
                % (platform_name, str((PLATFORMS.keys())))
            )
        print_culprit_finder_pipeline(
            project_name=project_name,
            platform_name=platform_name,
            good_bazel_commit=good_bazel_commit,
            bad_bazel_commit=bad_bazel_commit,
            needs_clean=needs_clean,
        )
    elif args.subparsers_name == "runner":
        git_repo_location = clone_git_repository_for_project(args.project_name, args.platform_name)
        print_collapsed_group("Check good bazel commit " + args.good_bazel_commit)
        if not test_with_bazel_at_commit(
            project_name=args.project_name,
            platform_name=args.platform_name,
            git_repo_location=git_repo_location,
            bazel_commit=args.good_bazel_commit,
            needs_clean=args.needs_clean,
        ):
            raise Exception(
                "Given good commit (%s) is not actually good, abort bisecting."
                % args.good_bazel_commit
            )
        start_bisecting(
            project_name=args.project_name,
            platform_name=args.platform_name,
            git_repo_location=git_repo_location,
            commits_list=get_bazel_commits_between(args.good_bazel_commit, args.bad_bazel_commit),
            needs_clean=args.needs_clean,
        )
    else:
        parser.print_help()
        return 2

    return 0