def main()

in buildkite/culprit_finder.py [0:0]


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("--task_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)
    runner.add_argument("--repeat_times", type=int, default=1)

    args = parser.parse_args(argv)
    if args.subparsers_name == "culprit_finder":
        try:
            project_name = os.environ["PROJECT_NAME"]

            # For old config file, we can still set PLATFORM_NAME as task name.
            task = os.environ.get("PLATFORM_NAME") or os.environ.get("TASK_NAME")
            if task:
                tasks = [task]
            elif os.environ.get("TASK_NAME_LIST"):
                tasks = os.environ.get("TASK_NAME_LIST").split(",")
            else:
                tasks = get_tasks(project_name)

            good_bazel_commit = os.environ.get("GOOD_BAZEL_COMMIT")
            if not good_bazel_commit:
                # If GOOD_BAZEL_COMMIT is not set, use recorded last bazel green commit for downstream project
                last_green_commit_url = bazelci.bazelci_last_green_downstream_commit_url()
                good_bazel_commit = bazelci.get_last_green_commit(last_green_commit_url)

            bad_bazel_commit = os.environ.get("BAD_BAZEL_COMMIT")
            if not bad_bazel_commit:
                # If BAD_BAZEL_COMMIT is not set, use HEAD commit.
                bad_bazel_commit = (
                    subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("utf-8").strip()
                )
        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

        repeat_times = 1
        if "REPEAT_TIMES" in os.environ:
            repeat_times = int(os.environ["REPEAT_TIMES"])

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

        print_culprit_finder_pipeline(
            project_name=project_name,
            tasks=tasks,
            good_bazel_commit=good_bazel_commit,
            bad_bazel_commit=bad_bazel_commit,
            needs_clean=needs_clean,
            repeat_times=repeat_times,
        )
    elif args.subparsers_name == "runner":
        repo_location = clone_git_repository(args.project_name, args.task_name)
        bazelci.print_collapsed_group("Check good bazel commit " + args.good_bazel_commit)
        if not test_with_bazel_at_commit(
            project_name=args.project_name,
            task_name=args.task_name,
            repo_location=repo_location,
            bazel_commit=args.good_bazel_commit,
            needs_clean=args.needs_clean,
            repeat_times=args.repeat_times,
        ):
            raise Exception(
                "Given good commit (%s) is not actually good, abort bisecting."
                % args.good_bazel_commit
            )
        start_bisecting(
            project_name=args.project_name,
            task_name=args.task_name,
            repo_location=repo_location,
            commits_list=get_bazel_commits_between(args.good_bazel_commit, args.bad_bazel_commit),
            needs_clean=args.needs_clean,
            repeat_times=args.repeat_times,
        )
    else:
        parser.print_help()
        return 2
    return 0