blob: 182ecb4f850fc8c34d1777fc8d1a7257aa9d928d [file] [log] [blame]
Kuang-che Wubfc4a642018-04-19 11:54:08 +08001#!/usr/bin/env python2
Kuang-che Wu6e4beca2018-06-27 17:45:02 +08002# -*- coding: utf-8 -*-
Kuang-che Wubfc4a642018-04-19 11:54:08 +08003# Copyright 2018 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"""ChromeOS bisector to bisect local build commits.
7
8Example:
Kuang-che Wu94f48e52018-07-25 15:28:31 +08009 $ ./bisect_cros_repo.py init --old rev1 --new rev2 \\
10 --chromeos_root ~/chromiumos \\
Kuang-che Wud8fc9572018-10-03 21:00:41 +080011 --chromeos_mirror $CHROMEOS_MIRROR
Kuang-che Wubfc4a642018-04-19 11:54:08 +080012 $ ./bisect_cros_repo.py config switch ./switch_cros_localbuild.py
13 $ ./bisect_cros_repo.py config eval ./eval-manually.sh
14 $ ./bisect_cros_repo.py run
15
16When running switcher and evaluator, following environment variables
17will be set:
18 BOARD (e.g. samus),
19 DUT (e.g. samus-dut),
20 INTRA_REV (e.g. 9901.0.0,9902.0.0+3), and
Kuang-che Wuc95fc152018-06-28 18:13:22 +080021 CHROMEOS_ROOT (e.g. ~/chromiumos).
Kuang-che Wubfc4a642018-04-19 11:54:08 +080022"""
23
24from __future__ import print_function
25import logging
26
27from bisect_kit import cli
Kuang-che Wue4bae0b2018-07-19 12:10:14 +080028from bisect_kit import codechange
Kuang-che Wubfc4a642018-04-19 11:54:08 +080029from bisect_kit import configure
30from bisect_kit import core
Kuang-che Wue4bae0b2018-07-19 12:10:14 +080031from bisect_kit import cros_util
Kuang-che Wue121fae2018-11-09 16:18:39 +080032from bisect_kit import errors
Kuang-che Wue4bae0b2018-07-19 12:10:14 +080033from bisect_kit import repo_util
Kuang-che Wubfc4a642018-04-19 11:54:08 +080034
35logger = logging.getLogger(__name__)
36
37
Kuang-che Wue80bb872018-11-15 19:45:25 +080038def generate_action_link(action):
39 if action['action_type'] == 'commit':
40 repo_url = action['repo_url']
41 action['link'] = repo_url + '/+/' + action['rev']
42
43
Kuang-che Wubfc4a642018-04-19 11:54:08 +080044class ChromeOSRepoDomain(core.BisectDomain):
45 """BisectDomain for ChromeOS code changes."""
46 revtype = staticmethod(cros_util.argtype_cros_version)
Kuang-che Wu752228c2018-09-05 13:54:22 +080047 intra_revtype = staticmethod(
48 codechange.argtype_intra_rev(cros_util.argtype_cros_version))
Kuang-che Wubfc4a642018-04-19 11:54:08 +080049 help = globals()['__doc__']
50
51 @staticmethod
52 def add_init_arguments(parser):
53 parser.add_argument(
54 '--dut',
55 type=cli.argtype_notempty,
56 metavar='DUT',
Kuang-che Wue4bae0b2018-07-19 12:10:14 +080057 default=configure.get('DUT'),
Kuang-che Wubfc4a642018-04-19 11:54:08 +080058 help='DUT address')
59 parser.add_argument(
60 '--board',
61 metavar='BOARD',
62 default=configure.get('BOARD', ''),
63 help='ChromeOS board name')
64 parser.add_argument(
Kuang-che Wuc95fc152018-06-28 18:13:22 +080065 '--chromeos_root',
66 metavar='CHROMEOS_ROOT',
Kuang-che Wubfc4a642018-04-19 11:54:08 +080067 type=cli.argtype_dir_path,
68 required=True,
Kuang-che Wuc95fc152018-06-28 18:13:22 +080069 default=configure.get('CHROMEOS_ROOT'),
Kuang-che Wubfc4a642018-04-19 11:54:08 +080070 help='ChromeOS tree root')
Kuang-che Wue4bae0b2018-07-19 12:10:14 +080071 parser.add_argument(
Kuang-che Wud8fc9572018-10-03 21:00:41 +080072 '--chromeos_mirror',
Kuang-che Wue4bae0b2018-07-19 12:10:14 +080073 type=cli.argtype_dir_path,
Kuang-che Wud8fc9572018-10-03 21:00:41 +080074 default=configure.get('CHROMEOS_MIRROR', ''),
Kuang-che Wue4bae0b2018-07-19 12:10:14 +080075 help='ChromeOS repo mirror path')
Kuang-che Wubfc4a642018-04-19 11:54:08 +080076
77 @staticmethod
78 def init(opts):
79 if not opts.dut and not opts.board:
Kuang-che Wue121fae2018-11-09 16:18:39 +080080 raise errors.ArgumentError('--dut and --board', 'Neither is specified')
Kuang-che Wubfc4a642018-04-19 11:54:08 +080081
82 if opts.dut:
83 assert cros_util.is_dut(opts.dut)
84 else:
85 logger.info("Tips: unless you don't need to build, otherwise it's "
86 "recommended to specify --dut in bisector instead of "
87 "switcher and evaluator.")
88
89 if not opts.board:
90 opts.board = cros_util.query_dut_board(opts.dut)
91
92 if cros_util.is_cros_short_version(opts.old):
93 opts.old = cros_util.version_to_full(opts.board, opts.old)
94 if cros_util.is_cros_short_version(opts.new):
95 opts.new = cros_util.version_to_full(opts.board, opts.new)
96
97 logger.info('Clean up previous result of "mark as stable"')
Kuang-che Wuc95fc152018-06-28 18:13:22 +080098 repo_util.abandon(opts.chromeos_root, 'stabilizing_branch')
Kuang-che Wubfc4a642018-04-19 11:54:08 +080099
Kuang-che Wuc95fc152018-06-28 18:13:22 +0800100 config = dict(
Kuang-che Wue4bae0b2018-07-19 12:10:14 +0800101 dut=opts.dut,
102 board=opts.board,
103 chromeos_root=opts.chromeos_root,
Kuang-che Wud8fc9572018-10-03 21:00:41 +0800104 chromeos_mirror=opts.chromeos_mirror)
Kuang-che Wubfc4a642018-04-19 11:54:08 +0800105
Kuang-che Wue4bae0b2018-07-19 12:10:14 +0800106 spec_manager = cros_util.ChromeOSSpecManager(config)
Kuang-che Wud8fc9572018-10-03 21:00:41 +0800107 cache = repo_util.RepoMirror(opts.chromeos_mirror)
Kuang-che Wue4bae0b2018-07-19 12:10:14 +0800108
109 # Make sure all repos in between are cached
110 float_specs = spec_manager.collect_float_spec(opts.old, opts.new)
111 for spec in reversed(float_specs):
112 spec_manager.parse_spec(spec)
113 if cache.are_spec_commits_available(spec):
114 continue
115 spec_manager.sync_disk_state(spec.name)
116
117 code_manager = codechange.CodeManager(opts.chromeos_root, spec_manager,
118 cache)
119 revlist = code_manager.build_revlist(opts.old, opts.new)
Kuang-che Wubfc4a642018-04-19 11:54:08 +0800120 return config, revlist
121
122 def __init__(self, config):
123 self.config = config
124
125 def setenv(self, env, rev):
126 if self.config['dut']:
127 env['DUT'] = self.config['dut']
128 if self.config['board']:
129 env['BOARD'] = self.config['board']
Kuang-che Wuc95fc152018-06-28 18:13:22 +0800130 env['CHROMEOS_ROOT'] = self.config['chromeos_root']
Kuang-che Wud8fc9572018-10-03 21:00:41 +0800131 env['CHROMEOS_MIRROR'] = self.config['chromeos_mirror']
Kuang-che Wubfc4a642018-04-19 11:54:08 +0800132 env['INTRA_REV'] = rev
133
Kuang-che Wue80bb872018-11-15 19:45:25 +0800134 def fill_candidate_summary(self, summary, interesting_indexes):
135 old, new = summary['current_range']
136 old_base, _, _ = codechange.parse_intra_rev(old)
137 _, new_next, _ = codechange.parse_intra_rev(new)
138 old_short = cros_util.version_to_short(old_base)
139 new_short = cros_util.version_to_short(new_next)
140 url_template = 'https://crosland.corp.google.com/log/%s..%s'
Kuang-che Wuaccf9202019-01-04 15:40:42 +0800141 summary['links'] = [
142 {
143 'name': 'change_list',
144 'url': url_template % (old_short, new_short),
145 },
146 ]
Kuang-che Wubfc4a642018-04-19 11:54:08 +0800147
Kuang-che Wud8fc9572018-10-03 21:00:41 +0800148 cache = repo_util.RepoMirror(self.config['chromeos_mirror'])
Kuang-che Wue80bb872018-11-15 19:45:25 +0800149 spec_manager = cros_util.ChromeOSSpecManager(self.config)
Kuang-che Wue4bae0b2018-07-19 12:10:14 +0800150 code_manager = codechange.CodeManager(self.config['chromeos_root'],
151 spec_manager, cache)
Kuang-che Wue80bb872018-11-15 19:45:25 +0800152 for i in interesting_indexes:
153 rev_info = summary['rev_info'][i]
154 rev_info.update(code_manager.get_rev_detail(rev_info['rev']))
155 for action in rev_info.get('actions', []):
156 generate_action_link(action)
Kuang-che Wubfc4a642018-04-19 11:54:08 +0800157
158
159if __name__ == '__main__':
160 cli.BisectorCommandLine(ChromeOSRepoDomain).main()