Salud Lemus | 6270ccc | 2019-09-04 18:15:35 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 2 | # -*- coding: utf-8 -*- |
| 3 | # Copyright 2019 The Chromium OS Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | |
| 7 | """Performs bisection on LLVM based off a .JSON file.""" |
| 8 | |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 9 | from __future__ import print_function |
| 10 | |
| 11 | import argparse |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 12 | import enum |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 13 | import errno |
| 14 | import json |
| 15 | import os |
Jian Cai | b9a4299 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 16 | import subprocess |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 17 | import sys |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 18 | |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 19 | import chroot |
| 20 | import get_llvm_hash |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 21 | import git_llvm_rev |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 22 | import modify_a_tryjob |
Ryan Beltran | 5200728 | 2021-10-27 20:41:33 +0000 | [diff] [blame] | 23 | import update_chromeos_llvm_hash |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 24 | import update_tryjob_status |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 25 | |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 26 | |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 27 | class BisectionExitStatus(enum.Enum): |
| 28 | """Exit code when performing bisection.""" |
| 29 | |
| 30 | # Means that there are no more revisions available to bisect. |
| 31 | BISECTION_COMPLETE = 126 |
| 32 | |
| 33 | |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 34 | def GetCommandLineArgs(): |
| 35 | """Parses the command line for the command line arguments.""" |
| 36 | |
| 37 | # Default path to the chroot if a path is not specified. |
| 38 | cros_root = os.path.expanduser('~') |
| 39 | cros_root = os.path.join(cros_root, 'chromiumos') |
| 40 | |
| 41 | # Create parser and add optional command-line arguments. |
| 42 | parser = argparse.ArgumentParser( |
| 43 | description='Bisects LLVM via tracking a JSON file.') |
| 44 | |
| 45 | # Add argument for other change lists that want to run alongside the tryjob |
| 46 | # which has a change list of updating a package's git hash. |
| 47 | parser.add_argument( |
| 48 | '--parallel', |
| 49 | type=int, |
| 50 | default=3, |
| 51 | help='How many tryjobs to create between the last good version and ' |
| 52 | 'the first bad version (default: %(default)s)') |
| 53 | |
| 54 | # Add argument for the good LLVM revision for bisection. |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 55 | parser.add_argument('--start_rev', |
| 56 | required=True, |
| 57 | type=int, |
| 58 | help='The good revision for the bisection.') |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 59 | |
| 60 | # Add argument for the bad LLVM revision for bisection. |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 61 | parser.add_argument('--end_rev', |
| 62 | required=True, |
| 63 | type=int, |
| 64 | help='The bad revision for the bisection.') |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 65 | |
| 66 | # Add argument for the absolute path to the file that contains information on |
| 67 | # the previous tested svn version. |
| 68 | parser.add_argument( |
| 69 | '--last_tested', |
| 70 | required=True, |
| 71 | help='the absolute path to the file that contains the tryjobs') |
| 72 | |
| 73 | # Add argument for the absolute path to the LLVM source tree. |
| 74 | parser.add_argument( |
| 75 | '--src_path', |
| 76 | help='the path to the LLVM source tree to use (used for retrieving the ' |
| 77 | 'git hash of each version between the last good version and first bad ' |
| 78 | 'version)') |
| 79 | |
| 80 | # Add argument for other change lists that want to run alongside the tryjob |
| 81 | # which has a change list of updating a package's git hash. |
| 82 | parser.add_argument( |
| 83 | '--extra_change_lists', |
| 84 | type=int, |
| 85 | nargs='+', |
| 86 | help='change lists that would like to be run alongside the change list ' |
| 87 | 'of updating the packages') |
| 88 | |
| 89 | # Add argument for custom options for the tryjob. |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 90 | parser.add_argument('--options', |
| 91 | required=False, |
| 92 | nargs='+', |
| 93 | help='options to use for the tryjob testing') |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 94 | |
| 95 | # Add argument for the builder to use for the tryjob. |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 96 | parser.add_argument('--builder', |
| 97 | required=True, |
| 98 | help='builder to use for the tryjob testing') |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 99 | |
| 100 | # Add argument for the description of the tryjob. |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 101 | parser.add_argument('--description', |
| 102 | required=False, |
| 103 | nargs='+', |
| 104 | help='the description of the tryjob') |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 105 | |
| 106 | # Add argument for a specific chroot path. |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 107 | parser.add_argument('--chroot_path', |
| 108 | default=cros_root, |
| 109 | help='the path to the chroot (default: %(default)s)') |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 110 | |
Salud Lemus | 6270ccc | 2019-09-04 18:15:35 -0700 | [diff] [blame] | 111 | # Add argument for whether to display command contents to `stdout`. |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 112 | parser.add_argument('--verbose', |
| 113 | action='store_true', |
| 114 | help='display contents of a command to the terminal ' |
| 115 | '(default: %(default)s)') |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 116 | |
Jian Cai | b9a4299 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 117 | # Add argument for whether to display command contents to `stdout`. |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 118 | parser.add_argument('--nocleanup', |
| 119 | action='store_false', |
| 120 | dest='cleanup', |
| 121 | help='Abandon CLs created for bisectoin') |
Jian Cai | b9a4299 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 122 | |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 123 | args_output = parser.parse_args() |
| 124 | |
| 125 | assert args_output.start_rev < args_output.end_rev, ( |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 126 | 'Start revision %d is >= end revision %d' % |
| 127 | (args_output.start_rev, args_output.end_rev)) |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 128 | |
| 129 | if args_output.last_tested and not args_output.last_tested.endswith('.json'): |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 130 | raise ValueError('Filed provided %s does not end in ".json"' % |
| 131 | args_output.last_tested) |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 132 | |
| 133 | return args_output |
| 134 | |
| 135 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 136 | def GetRemainingRange(start, end, tryjobs): |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 137 | """Gets the start and end intervals in 'json_file'. |
| 138 | |
| 139 | Args: |
| 140 | start: The start version of the bisection provided via the command line. |
| 141 | end: The end version of the bisection provided via the command line. |
| 142 | tryjobs: A list of tryjobs where each element is in the following format: |
| 143 | [ |
| 144 | {[TRYJOB_INFORMATION]}, |
| 145 | {[TRYJOB_INFORMATION]}, |
| 146 | ..., |
| 147 | {[TRYJOB_INFORMATION]} |
| 148 | ] |
| 149 | |
| 150 | Returns: |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 151 | The new start version and end version for bisection, a set of revisions |
| 152 | that are 'pending' and a set of revisions that are to be skipped. |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 153 | |
| 154 | Raises: |
| 155 | ValueError: The value for 'status' is missing or there is a mismatch |
| 156 | between 'start' and 'end' compared to the 'start' and 'end' in the JSON |
| 157 | file. |
| 158 | AssertionError: The new start version is >= than the new end version. |
| 159 | """ |
| 160 | |
| 161 | if not tryjobs: |
Salud Lemus | 0263063 | 2019-08-28 15:27:59 -0700 | [diff] [blame] | 162 | return start, end, {}, {} |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 163 | |
| 164 | # Verify that each tryjob has a value for the 'status' key. |
| 165 | for cur_tryjob_dict in tryjobs: |
| 166 | if not cur_tryjob_dict.get('status', None): |
Salud Lemus | 6270ccc | 2019-09-04 18:15:35 -0700 | [diff] [blame] | 167 | raise ValueError('"status" is missing or has no value, please ' |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 168 | 'go to %s and update it' % cur_tryjob_dict['link']) |
| 169 | |
| 170 | all_bad_revisions = [end] |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 171 | all_bad_revisions.extend( |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 172 | cur_tryjob['rev'] for cur_tryjob in tryjobs |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 173 | if cur_tryjob['status'] == update_tryjob_status.TryjobStatus.BAD.value) |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 174 | |
| 175 | # The minimum value for the 'bad' field in the tryjobs is the new end |
| 176 | # version. |
| 177 | bad_rev = min(all_bad_revisions) |
| 178 | |
| 179 | all_good_revisions = [start] |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 180 | all_good_revisions.extend( |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 181 | cur_tryjob['rev'] for cur_tryjob in tryjobs |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 182 | if cur_tryjob['status'] == update_tryjob_status.TryjobStatus.GOOD.value) |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 183 | |
| 184 | # The maximum value for the 'good' field in the tryjobs is the new start |
| 185 | # version. |
| 186 | good_rev = max(all_good_revisions) |
| 187 | |
| 188 | # The good version should always be strictly less than the bad version; |
| 189 | # otherwise, bisection is broken. |
| 190 | assert good_rev < bad_rev, ('Bisection is broken because %d (good) is >= ' |
| 191 | '%d (bad)' % (good_rev, bad_rev)) |
| 192 | |
| 193 | # Find all revisions that are 'pending' within 'good_rev' and 'bad_rev'. |
| 194 | # |
| 195 | # NOTE: The intent is to not launch tryjobs between 'good_rev' and 'bad_rev' |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 196 | # that have already been launched (this set is used when constructing the |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 197 | # list of revisions to launch tryjobs for). |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 198 | pending_revisions = { |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 199 | tryjob['rev'] |
| 200 | for tryjob in tryjobs |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 201 | if tryjob['status'] == update_tryjob_status.TryjobStatus.PENDING.value |
| 202 | and good_rev < tryjob['rev'] < bad_rev |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 203 | } |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 204 | |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 205 | # Find all revisions that are to be skipped within 'good_rev' and 'bad_rev'. |
| 206 | # |
| 207 | # NOTE: The intent is to not launch tryjobs between 'good_rev' and 'bad_rev' |
| 208 | # that have already been marked as 'skip' (this set is used when constructing |
| 209 | # the list of revisions to launch tryjobs for). |
| 210 | skip_revisions = { |
| 211 | tryjob['rev'] |
| 212 | for tryjob in tryjobs |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 213 | if tryjob['status'] == update_tryjob_status.TryjobStatus.SKIP.value |
| 214 | and good_rev < tryjob['rev'] < bad_rev |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | return good_rev, bad_rev, pending_revisions, skip_revisions |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 218 | |
| 219 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 220 | def GetCommitsBetween(start, end, parallel, src_path, pending_revisions, |
| 221 | skip_revisions): |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 222 | """Determines the revisions between start and end.""" |
| 223 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 224 | with get_llvm_hash.LLVMHash().CreateTempDirectory() as temp_dir: |
| 225 | # We have guaranteed contiguous revision numbers after this, |
| 226 | # and that guarnatee simplifies things considerably, so we don't |
| 227 | # support anything before it. |
| 228 | assert start >= git_llvm_rev.base_llvm_revision, f'{start} was too long ago' |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 229 | |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 230 | with get_llvm_hash.CreateTempLLVMRepo(temp_dir) as new_repo: |
Salud Lemus | 4223570 | 2019-08-23 16:49:28 -0700 | [diff] [blame] | 231 | if not src_path: |
| 232 | src_path = new_repo |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 233 | index_step = (end - (start + 1)) // (parallel + 1) |
| 234 | if not index_step: |
| 235 | index_step = 1 |
| 236 | revisions = [ |
| 237 | rev for rev in range(start + 1, end, index_step) |
| 238 | if rev not in pending_revisions and rev not in skip_revisions |
| 239 | ] |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 240 | git_hashes = [ |
| 241 | get_llvm_hash.GetGitHashFrom(src_path, rev) for rev in revisions |
| 242 | ] |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 243 | return revisions, git_hashes |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 244 | |
| 245 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 246 | def Bisect(revisions, git_hashes, bisect_state, last_tested, update_packages, |
| 247 | chroot_path, patch_metadata_file, extra_change_lists, options, |
| 248 | builder, verbose): |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 249 | """Adds tryjobs and updates the status file with the new tryjobs.""" |
| 250 | |
| 251 | try: |
| 252 | for svn_revision, git_hash in zip(revisions, git_hashes): |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 253 | tryjob_dict = modify_a_tryjob.AddTryjob(update_packages, git_hash, |
| 254 | svn_revision, chroot_path, |
| 255 | patch_metadata_file, |
| 256 | extra_change_lists, options, |
| 257 | builder, verbose, svn_revision) |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 258 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 259 | bisect_state['jobs'].append(tryjob_dict) |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 260 | finally: |
| 261 | # Do not want to lose progress if there is an exception. |
| 262 | if last_tested: |
| 263 | new_file = '%s.new' % last_tested |
| 264 | with open(new_file, 'w') as json_file: |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 265 | json.dump(bisect_state, json_file, indent=4, separators=(',', ': ')) |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 266 | |
| 267 | os.rename(new_file, last_tested) |
| 268 | |
| 269 | |
Salud Lemus | 97c1e1c | 2019-09-10 16:28:47 -0700 | [diff] [blame] | 270 | def LoadStatusFile(last_tested, start, end): |
| 271 | """Loads the status file for bisection.""" |
| 272 | |
| 273 | try: |
| 274 | with open(last_tested) as f: |
| 275 | return json.load(f) |
| 276 | except IOError as err: |
| 277 | if err.errno != errno.ENOENT: |
| 278 | raise |
| 279 | |
| 280 | return {'start': start, 'end': end, 'jobs': []} |
| 281 | |
| 282 | |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 283 | def main(args_output): |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 284 | """Bisects LLVM commits. |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 285 | |
| 286 | Raises: |
| 287 | AssertionError: The script was run inside the chroot. |
| 288 | """ |
| 289 | |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 290 | chroot.VerifyOutsideChroot() |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 291 | patch_metadata_file = 'PATCHES.json' |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 292 | start = args_output.start_rev |
| 293 | end = args_output.end_rev |
| 294 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 295 | bisect_state = LoadStatusFile(args_output.last_tested, start, end) |
| 296 | if start != bisect_state['start'] or end != bisect_state['end']: |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 297 | raise ValueError( |
| 298 | f'The start {start} or the end {end} version provided is ' |
| 299 | f'different than "start" {bisect_state["start"]} or "end" ' |
| 300 | f'{bisect_state["end"]} in the .JSON file') |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 301 | |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 302 | # Pending and skipped revisions are between 'start_rev' and 'end_rev'. |
| 303 | start_rev, end_rev, pending_revs, skip_revs = GetRemainingRange( |
| 304 | start, end, bisect_state['jobs']) |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 305 | |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 306 | revisions, git_hashes = GetCommitsBetween(start_rev, end_rev, |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 307 | args_output.parallel, |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 308 | args_output.src_path, pending_revs, |
| 309 | skip_revs) |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 310 | |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 311 | # No more revisions between 'start_rev' and 'end_rev', so |
Salud Lemus | c856b68 | 2019-08-29 11:46:49 -0700 | [diff] [blame] | 312 | # bisection is complete. |
| 313 | # |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 314 | # This is determined by finding all valid revisions between 'start_rev' |
| 315 | # and 'end_rev' and that are NOT in the 'pending' and 'skipped' set. |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 316 | if not revisions: |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 317 | if pending_revs: |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 318 | # Some tryjobs are not finished which may change the actual bad |
| 319 | # commit/revision when those tryjobs are finished. |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 320 | no_revisions_message = (f'No revisions between start {start_rev} ' |
| 321 | f'and end {end_rev} to create tryjobs\n') |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 322 | |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 323 | if pending_revs: |
| 324 | no_revisions_message += ('The following tryjobs are pending:\n' + |
| 325 | '\n'.join(str(rev) |
| 326 | for rev in pending_revs) + '\n') |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 327 | |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 328 | if skip_revs: |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 329 | no_revisions_message += ('The following tryjobs were skipped:\n' + |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 330 | '\n'.join(str(rev) |
| 331 | for rev in skip_revs) + '\n') |
Salud Lemus | ffed65d | 2019-08-26 14:52:02 -0700 | [diff] [blame] | 332 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 333 | raise ValueError(no_revisions_message) |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 334 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 335 | print(f'Finished bisecting for {args_output.last_tested}') |
| 336 | if args_output.src_path: |
| 337 | bad_llvm_hash = get_llvm_hash.GetGitHashFrom(args_output.src_path, |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 338 | end_rev) |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 339 | else: |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 340 | bad_llvm_hash = get_llvm_hash.LLVMHash().GetLLVMHash(end_rev) |
| 341 | print(f'The bad revision is {end_rev} and its commit hash is ' |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 342 | f'{bad_llvm_hash}') |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 343 | if skip_revs: |
| 344 | skip_revs_message = ('\nThe following revisions were skipped:\n' + |
| 345 | '\n'.join(str(rev) for rev in skip_revs)) |
| 346 | print(skip_revs_message) |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 347 | |
Jian Cai | b9a4299 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 348 | if args_output.cleanup: |
Bob Haarman | 2c27f0a | 2020-11-20 15:30:19 +0000 | [diff] [blame] | 349 | # Abandon all the CLs created for bisection |
Jian Cai | b9a4299 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 350 | gerrit = os.path.join(args_output.chroot_path, 'chromite/bin/gerrit') |
| 351 | for build in bisect_state['jobs']: |
| 352 | try: |
Bob Haarman | 2c27f0a | 2020-11-20 15:30:19 +0000 | [diff] [blame] | 353 | subprocess.check_output( |
| 354 | [gerrit, 'abandon', str(build['cl'])], |
| 355 | stderr=subprocess.STDOUT, |
| 356 | encoding='utf-8') |
Jian Cai | b9a4299 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 357 | except subprocess.CalledProcessError as err: |
| 358 | # the CL may have been abandoned |
| 359 | if 'chromite.lib.gob_util.GOBError' not in err.output: |
| 360 | raise |
| 361 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 362 | return BisectionExitStatus.BISECTION_COMPLETE.value |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 363 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 364 | for rev in revisions: |
| 365 | if update_tryjob_status.FindTryjobIndex(rev, |
| 366 | bisect_state['jobs']) is not None: |
| 367 | raise ValueError(f'Revision {rev} exists already in "jobs"') |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 368 | |
Jian Cai | 089db67 | 2020-08-23 20:09:02 -0700 | [diff] [blame] | 369 | Bisect(revisions, git_hashes, bisect_state, args_output.last_tested, |
Ryan Beltran | d080198 | 2021-10-27 20:47:16 +0000 | [diff] [blame^] | 370 | update_chromeos_llvm_hash.DEFAULT_PACKAGES, args_output.chroot_path, |
| 371 | patch_metadata_file, args_output.extra_change_lists, |
| 372 | args_output.options, args_output.builder, args_output.verbose) |
Salud Lemus | 055838a | 2019-08-19 13:37:28 -0700 | [diff] [blame] | 373 | |
| 374 | |
| 375 | if __name__ == '__main__': |
Jian Cai | c16daa1 | 2020-04-15 17:53:41 -0700 | [diff] [blame] | 376 | sys.exit(main(GetCommandLineArgs())) |