aboutsummaryrefslogtreecommitdiff
path: root/llvm_tools/auto_llvm_bisection.py
diff options
context:
space:
mode:
Diffstat (limited to 'llvm_tools/auto_llvm_bisection.py')
-rwxr-xr-xllvm_tools/auto_llvm_bisection.py276
1 files changed, 149 insertions, 127 deletions
diff --git a/llvm_tools/auto_llvm_bisection.py b/llvm_tools/auto_llvm_bisection.py
index 7e8fb1dd..3640abae 100755
--- a/llvm_tools/auto_llvm_bisection.py
+++ b/llvm_tools/auto_llvm_bisection.py
@@ -1,12 +1,11 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
-# Copyright 2019 The Chromium OS Authors. All rights reserved.
+# Copyright 2019 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Performs bisection on LLVM based off a .JSON file."""
-from __future__ import print_function
import enum
import json
@@ -17,10 +16,11 @@ import time
import traceback
import chroot
-from llvm_bisection import BisectionExitStatus
import llvm_bisection
+from llvm_bisection import BisectionExitStatus
import update_tryjob_status
+
# Used to re-try for 'llvm_bisection.py' to attempt to launch more tryjobs.
BISECTION_RETRY_TIME_SECS = 10 * 60
@@ -42,145 +42,167 @@ POLLING_LIMIT_SECS = 18 * 60 * 60
class BuilderStatus(enum.Enum):
- """Actual values given via 'cros buildresult'."""
+ """Actual values given via 'cros buildresult'."""
- PASS = 'pass'
- FAIL = 'fail'
- RUNNING = 'running'
+ PASS = "pass"
+ FAIL = "fail"
+ RUNNING = "running"
builder_status_mapping = {
BuilderStatus.PASS.value: update_tryjob_status.TryjobStatus.GOOD.value,
BuilderStatus.FAIL.value: update_tryjob_status.TryjobStatus.BAD.value,
- BuilderStatus.RUNNING.value: update_tryjob_status.TryjobStatus.PENDING.value
+ BuilderStatus.RUNNING.value: update_tryjob_status.TryjobStatus.PENDING.value,
}
def GetBuildResult(chroot_path, buildbucket_id):
- """Returns the conversion of the result of 'cros buildresult'."""
-
- # Calls 'cros buildresult' to get the status of the tryjob.
- try:
- tryjob_json = subprocess.check_output(
- [
- 'cros_sdk', '--', 'cros', 'buildresult', '--buildbucket-id',
- str(buildbucket_id), '--report', 'json'
- ],
- cwd=chroot_path,
- stderr=subprocess.STDOUT,
- encoding='UTF-8',
- )
- except subprocess.CalledProcessError as err:
- if 'No build found. Perhaps not started' not in err.output:
- raise
- return None
-
- tryjob_content = json.loads(tryjob_json)
-
- build_result = str(tryjob_content['%d' % buildbucket_id]['status'])
-
- # The string returned by 'cros buildresult' might not be in the mapping.
- if build_result not in builder_status_mapping:
- raise ValueError('"cros buildresult" return value is invalid: %s' %
- build_result)
-
- return builder_status_mapping[build_result]
+ """Returns the conversion of the result of 'cros buildresult'."""
+
+ # Calls 'cros buildresult' to get the status of the tryjob.
+ try:
+ tryjob_json = subprocess.check_output(
+ [
+ "cros_sdk",
+ "--",
+ "cros",
+ "buildresult",
+ "--buildbucket-id",
+ str(buildbucket_id),
+ "--report",
+ "json",
+ ],
+ cwd=chroot_path,
+ stderr=subprocess.STDOUT,
+ encoding="UTF-8",
+ )
+ except subprocess.CalledProcessError as err:
+ if "No build found. Perhaps not started" not in err.output:
+ raise
+ return None
+
+ tryjob_content = json.loads(tryjob_json)
+
+ build_result = str(tryjob_content["%d" % buildbucket_id]["status"])
+
+ # The string returned by 'cros buildresult' might not be in the mapping.
+ if build_result not in builder_status_mapping:
+ raise ValueError(
+ '"cros buildresult" return value is invalid: %s' % build_result
+ )
+
+ return builder_status_mapping[build_result]
def main():
- """Bisects LLVM using the result of `cros buildresult` of each tryjob.
-
- Raises:
- AssertionError: The script was run inside the chroot.
- """
+ """Bisects LLVM using the result of `cros buildresult` of each tryjob.
- chroot.VerifyOutsideChroot()
+ Raises:
+ AssertionError: The script was run inside the chroot.
+ """
- args_output = llvm_bisection.GetCommandLineArgs()
+ chroot.VerifyOutsideChroot()
- if os.path.isfile(args_output.last_tested):
- print('Resuming bisection for %s' % args_output.last_tested)
- else:
- print('Starting a new bisection for %s' % args_output.last_tested)
+ args_output = llvm_bisection.GetCommandLineArgs()
- while True:
- # Update the status of existing tryjobs
if os.path.isfile(args_output.last_tested):
- update_start_time = time.time()
- with open(args_output.last_tested) as json_file:
- json_dict = json.load(json_file)
- while True:
- print('\nAttempting to update all tryjobs whose "status" is '
- '"pending":')
- print('-' * 40)
-
- completed = True
- for tryjob in json_dict['jobs']:
- if tryjob[
- 'status'] == update_tryjob_status.TryjobStatus.PENDING.value:
- status = GetBuildResult(args_output.chroot_path,
- tryjob['buildbucket_id'])
- if status:
- tryjob['status'] = status
- else:
- completed = False
-
- print('-' * 40)
-
- # Proceed to the next step if all the existing tryjobs have completed.
- if completed:
- break
-
- delta_time = time.time() - update_start_time
-
- if delta_time > POLLING_LIMIT_SECS:
- # Something is wrong with updating the tryjobs's 'status' via
- # `cros buildresult` (e.g. network issue, etc.).
- sys.exit('Failed to update pending tryjobs.')
-
- print('-' * 40)
- print('Sleeping for %d minutes.' % (POLL_RETRY_TIME_SECS // 60))
- time.sleep(POLL_RETRY_TIME_SECS)
-
- # There should always be update from the tryjobs launched in the
- # last iteration.
- temp_filename = '%s.new' % args_output.last_tested
- with open(temp_filename, 'w') as temp_file:
- json.dump(json_dict, temp_file, indent=4, separators=(',', ': '))
- os.rename(temp_filename, args_output.last_tested)
-
- # Launch more tryjobs.
- for cur_try in range(1, BISECTION_ATTEMPTS + 1):
- try:
- print('\nAttempting to launch more tryjobs if possible:')
- print('-' * 40)
-
- bisection_ret = llvm_bisection.main(args_output)
-
- print('-' * 40)
-
- # Stop if the bisection has completed.
- if bisection_ret == BisectionExitStatus.BISECTION_COMPLETE.value:
- sys.exit(0)
-
- # Successfully launched more tryjobs.
- break
- except Exception:
- traceback.print_exc()
-
- print('-' * 40)
-
- # Exceeded the number of times to launch more tryjobs.
- if cur_try == BISECTION_ATTEMPTS:
- sys.exit('Unable to continue bisection.')
-
- num_retries_left = BISECTION_ATTEMPTS - cur_try
-
- print('Retries left to continue bisection %d.' % num_retries_left)
-
- print('Sleeping for %d minutes.' % (BISECTION_RETRY_TIME_SECS // 60))
- time.sleep(BISECTION_RETRY_TIME_SECS)
-
-
-if __name__ == '__main__':
- main()
+ print("Resuming bisection for %s" % args_output.last_tested)
+ else:
+ print("Starting a new bisection for %s" % args_output.last_tested)
+
+ while True:
+ # Update the status of existing tryjobs
+ if os.path.isfile(args_output.last_tested):
+ update_start_time = time.time()
+ with open(args_output.last_tested) as json_file:
+ json_dict = json.load(json_file)
+ while True:
+ print(
+ '\nAttempting to update all tryjobs whose "status" is '
+ '"pending":'
+ )
+ print("-" * 40)
+
+ completed = True
+ for tryjob in json_dict["jobs"]:
+ if (
+ tryjob["status"]
+ == update_tryjob_status.TryjobStatus.PENDING.value
+ ):
+ status = GetBuildResult(
+ args_output.chroot_path, tryjob["buildbucket_id"]
+ )
+ if status:
+ tryjob["status"] = status
+ else:
+ completed = False
+
+ print("-" * 40)
+
+ # Proceed to the next step if all the existing tryjobs have completed.
+ if completed:
+ break
+
+ delta_time = time.time() - update_start_time
+
+ if delta_time > POLLING_LIMIT_SECS:
+ # Something is wrong with updating the tryjobs's 'status' via
+ # `cros buildresult` (e.g. network issue, etc.).
+ sys.exit("Failed to update pending tryjobs.")
+
+ print("-" * 40)
+ print("Sleeping for %d minutes." % (POLL_RETRY_TIME_SECS // 60))
+ time.sleep(POLL_RETRY_TIME_SECS)
+
+ # There should always be update from the tryjobs launched in the
+ # last iteration.
+ temp_filename = "%s.new" % args_output.last_tested
+ with open(temp_filename, "w") as temp_file:
+ json.dump(
+ json_dict, temp_file, indent=4, separators=(",", ": ")
+ )
+ os.rename(temp_filename, args_output.last_tested)
+
+ # Launch more tryjobs.
+ for cur_try in range(1, BISECTION_ATTEMPTS + 1):
+ try:
+ print("\nAttempting to launch more tryjobs if possible:")
+ print("-" * 40)
+
+ bisection_ret = llvm_bisection.main(args_output)
+
+ print("-" * 40)
+
+ # Stop if the bisection has completed.
+ if (
+ bisection_ret
+ == BisectionExitStatus.BISECTION_COMPLETE.value
+ ):
+ sys.exit(0)
+
+ # Successfully launched more tryjobs.
+ break
+ except Exception:
+ traceback.print_exc()
+
+ print("-" * 40)
+
+ # Exceeded the number of times to launch more tryjobs.
+ if cur_try == BISECTION_ATTEMPTS:
+ sys.exit("Unable to continue bisection.")
+
+ num_retries_left = BISECTION_ATTEMPTS - cur_try
+
+ print(
+ "Retries left to continue bisection %d." % num_retries_left
+ )
+
+ print(
+ "Sleeping for %d minutes."
+ % (BISECTION_RETRY_TIME_SECS // 60)
+ )
+ time.sleep(BISECTION_RETRY_TIME_SECS)
+
+
+if __name__ == "__main__":
+ main()