def get_failing_jobs(build_info): failing_jobs = [] for job in build_info["jobs"]: if "state" in job and job["state"] == "failed": command = job["command"] if not command: bazelci.eprint("'command' field not found in the job: " + str(job)) continue # Skip if the job is not a runner job if command.find("bazelci.py runner") == -1: continue # Get rid of the incompatible flags in the command line because we are going to test them individually command_without_incompatible_flags = " ".join([ i for i in command.split(" ") if not i.startswith("--incompatible_flag") ]) # Recover the task name from job command flags = get_flags_from_command(command) task = flags.get("task") if not task: raise BuildkiteException( "The following command has no --task argument: %s." % command) # Fetch the original job config to retrieve the platform name. job_config = bazelci.load_config( http_url=flags.get("http_config"), file_config=flags.get("file_config")) # The config can either contain a "tasks" dict (new format) or a "platforms" dict (legacy format). all_tasks = job_config.get("tasks", job_config.get("platforms")) if not all_tasks: raise BuildkiteException( "Malformed configuration: No 'tasks' or 'platforms' entry found." ) task_config = all_tasks.get(task) if not task_config: raise BuildkiteException( "Configuration does not contain an entry for task '%s'" % task) # Shortcut: Users can skip the "platform" field if its value equals the task name. platform = task_config.get("platform") or task failing_jobs.append({ "name": job["name"], "command": command_without_incompatible_flags.split("\n"), "platform": platform, }) return failing_jobs
def get_failing_jobs(build_info): failing_jobs = [] for job in build_info["jobs"]: if "state" in job and job["state"] == "failed": command = job["command"] # Skip if the job is not a runner job if command.find("bazelci.py runner") == -1: continue # Get rid of the incompatible flags in the command line because we are going to test them individually command_without_incompatible_flags = " ".join([ i for i in command.split(" ") if not i.startswith("--incompatible_flag") ]) # Recover the platform name from job command platform = None for s in command.split(" "): if s.startswith("--platform="): platform = s[len("--platform="):] if not platform: raise BuildkiteException( "Cannot recongnize platform from job command: %s" % command) failing_jobs.append({ "name": job["name"], "command": command_without_incompatible_flags.split("\n"), "platform": platform, }) return failing_jobs
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) try: 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 BuildkiteException("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 BuildkiteException( "Project name '%s' not recognized, available projects are %s" % (project_name, str((DOWNSTREAM_PROJECTS.keys()))) ) if platform_name not in PLATFORMS: raise BuildkiteException( "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(args.project_name, args.platform_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, platform_name=args.platform_name, git_repo_location=git_repo_location, bazel_commit=args.good_bazel_commit, needs_clean=args.needs_clean, ): raise BuildkiteException( "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 except BuildkiteException as e: bazelci.eprint(str(e)) return 1 return 0