LLVM tools: Added support for 'skip' and executing a custom script
If a tryjob's status is set to 'skip', then that tryjob will not be
considered when bisecting LLVM. And for executing a custom script,
the exit code will be used by a mapping that sets the 'status' to
the equivalent value of the exit code.
BUG=None
TEST=Ran the 'update_tryjob_status.py' with the 'skip' option and
successfully set the tryjob's status to 'skip'. Also, created a testing
script to serve as the custom script. Successfully set the 'status'
value based off of the custom script's exit code.
Change-Id: I0ae3a9b53467b13ff5ce26aeff46b31563cfc7e0
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1772472
Reviewed-by: George Burgess <gbiv@chromium.org>
Reviewed-by: Manoj Gupta <manojgupta@chromium.org>
Tested-by: Salud Lemus <saludlemus@google.com>
diff --git a/llvm_tools/llvm_bisection.py b/llvm_tools/llvm_bisection.py
index b4705d4..361b918 100755
--- a/llvm_tools/llvm_bisection.py
+++ b/llvm_tools/llvm_bisection.py
@@ -154,7 +154,8 @@
]
Returns:
- The new start version and end version for bisection.
+ The new start version and end version for bisection, a set of revisions
+ that are 'pending' and a set of revisions that are to be skipped.
Raises:
ValueError: The value for 'status' is missing or there is a mismatch
@@ -198,20 +199,32 @@
# Find all revisions that are 'pending' within 'good_rev' and 'bad_rev'.
#
# NOTE: The intent is to not launch tryjobs between 'good_rev' and 'bad_rev'
- # that have already been launched (this list is used when constructing the
+ # that have already been launched (this set is used when constructing the
# list of revisions to launch tryjobs for).
- pending_revisions = [
+ pending_revisions = {
tryjob['rev']
for tryjob in tryjobs
if tryjob['status'] == TryjobStatus.PENDING.value and
good_rev < tryjob['rev'] < bad_rev
- ]
+ }
- return good_rev, bad_rev, pending_revisions
+ # Find all revisions that are to be skipped within 'good_rev' and 'bad_rev'.
+ #
+ # NOTE: The intent is to not launch tryjobs between 'good_rev' and 'bad_rev'
+ # that have already been marked as 'skip' (this set is used when constructing
+ # the list of revisions to launch tryjobs for).
+ skip_revisions = {
+ tryjob['rev']
+ for tryjob in tryjobs
+ if tryjob['status'] == TryjobStatus.SKIP.value and
+ good_rev < tryjob['rev'] < bad_rev
+ }
+
+ return good_rev, bad_rev, pending_revisions, skip_revisions
def GetRevisionsBetweenBisection(start, end, parallel, src_path,
- pending_revisions):
+ pending_revisions, skip_revisions):
"""Gets the revisions between 'start' and 'end'.
Sometimes, the LLVM source tree's revisions do not increment by 1 (there is
@@ -224,8 +237,10 @@
end: The end revision.
parallel: The number of tryjobs to create between 'start' and 'end'.
src_path: The absolute path to the LLVM source tree to use.
- pending_revisions: A list of 'pending' revisions that are between 'start'
- and 'end'.
+ pending_revisions: A set containing 'pending' revisions that are between
+ 'start' and 'end'.
+ skip_revisions: A set containing revisions between 'start' and 'end' that
+ are to be skipped.
Returns:
A list of revisions between 'start' and 'end'.
@@ -242,7 +257,8 @@
# this.
for cur_revision in range(start + 1, end):
try:
- if cur_revision not in pending_revisions:
+ if cur_revision not in pending_revisions and \
+ cur_revision not in skip_revisions:
# Verify that the current revision exists by finding its corresponding
# git hash in the LLVM source tree.
new_llvm.GetGitHashForVersion(src_path, cur_revision)
@@ -258,16 +274,14 @@
if not index_step:
index_step = 1
- # Starting at 'index_step' because the first element would be close to
- # 'start' (similar to ('parallel' + 1) for the last element).
result = [valid_revisions[index] \
- for index in range(index_step, len(valid_revisions), index_step)]
+ for index in range(0, len(valid_revisions), index_step)]
return result
def GetRevisionsListAndHashList(start, end, parallel, src_path,
- pending_revisions):
+ pending_revisions, skip_revisions):
"""Determines the revisions between start and end."""
new_llvm = LLVMHash()
@@ -278,16 +292,13 @@
src_path = new_repo
# Get a list of revisions between start and end.
- revisions = GetRevisionsBetweenBisection(start, end, parallel, src_path,
- pending_revisions)
+ revisions = GetRevisionsBetweenBisection(
+ start, end, parallel, src_path, pending_revisions, skip_revisions)
git_hashes = [
new_llvm.GetGitHashForVersion(src_path, rev) for rev in revisions
]
- assert revisions, ('No revisions between start %d and end %d to create '
- 'tryjobs.' % (start, end))
-
return revisions, git_hashes
@@ -323,13 +334,25 @@
_ValidateStartAndEndAgainstJSONStartAndEnd(
start, end, bisect_contents['start'], bisect_contents['end'])
- # Pending revisions are between 'start_revision' and 'end_revision'.
- start_revision, end_revision, pending_revisions = GetStartAndEndRevision(
- start, end, bisect_contents['jobs'])
+ # Pending and skipped revisions are between 'start_revision' and
+ # 'end_revision'.
+ start_revision, end_revision, pending_revisions, skip_revisions = \
+ GetStartAndEndRevision(start, end, bisect_contents['jobs'])
revisions, git_hashes = GetRevisionsListAndHashList(
start_revision, end_revision, args_output.parallel, args_output.src_path,
- pending_revisions)
+ pending_revisions, skip_revisions)
+
+ if not revisions:
+ no_revisions_message = (
+ 'No revisions between start %d and end '
+ '%d to create tryjobs' % (start_revision, end_revision))
+
+ if skip_revisions:
+ no_revisions_message += '\nThe following tryjobs were skipped:\n' \
+ + '\n'.join(str(rev) for rev in skip_revisions)
+
+ raise ValueError(no_revisions_message)
# Check if any revisions that are going to be added as a tryjob exist already
# in the 'jobs' list.