blob: 76d33abb400122c4687a83af3d1a6e22ddc2940c [file] [log] [blame]
Jack Neus56bd8c92022-09-21 23:05:34 +00001# Copyright 2017 The ChromiumOS Authors
xixuanbea010f2017-03-27 10:10:19 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Module for ChromeOS & Android build related logic in suite scheduler."""
Xixuan Wu5d6063e2017-09-05 16:15:07 -07006# pylint: disable=g-bad-import-order
xixuanbea010f2017-03-27 10:10:19 -07007
Xixuan Wu5d6063e2017-09-05 16:15:07 -07008from distutils import version
xixuanbea010f2017-03-27 10:10:19 -07009import collections
Xixuan Wu244e0ec2018-05-23 14:49:55 -070010import json
xixuanbea010f2017-03-27 10:10:19 -070011import logging
12import re
13
Xixuan Wu5d6063e2017-09-05 16:15:07 -070014import apiclient
15
Xixuan Wuf856ff12019-05-21 14:09:38 -070016BuildInfo = collections.namedtuple(
17 'BuildInfo',
18 [
19 'board',
20 'model',
21 'milestone',
22 'platform',
23 'build_config',
24 ])
25
xixuanbea010f2017-03-27 10:10:19 -070026# Bare branches
27BARE_BRANCHES = ['factory', 'firmware']
28
29# Definition of os types.
30OS_TYPE_CROS = 'cros'
31OS_TYPE_BRILLO = 'brillo'
32OS_TYPE_ANDROID = 'android'
33OS_TYPES = [OS_TYPE_CROS, OS_TYPE_BRILLO, OS_TYPE_ANDROID]
34OS_TYPES_LAUNCH_CONTROL = [OS_TYPE_BRILLO, OS_TYPE_ANDROID]
35
Xixuan Wu5d6063e2017-09-05 16:15:07 -070036# Launch control build's target's information
xixuanbea010f2017-03-27 10:10:19 -070037LaunchControlBuildTargetInfo = collections.namedtuple(
38 'LaunchControlBuildTargetInfo',
39 [
Xixuan Wu5d6063e2017-09-05 16:15:07 -070040 'target',
41 'type',
xixuanbea010f2017-03-27 10:10:19 -070042 ])
43
Xixuan Wu5d6063e2017-09-05 16:15:07 -070044# ChromeOS build config's information
xixuanbea010f2017-03-27 10:10:19 -070045CrOSBuildConfigInfo = collections.namedtuple(
46 'CrOSBuildConfigInfo',
47 [
Xixuan Wu5d6063e2017-09-05 16:15:07 -070048 'board',
49 'type',
xixuanbea010f2017-03-27 10:10:19 -070050 ])
51
xixuanbea010f2017-03-27 10:10:19 -070052# The default build type for fetching latest build.
Xixuan Wu7899db52018-05-29 14:19:06 -070053_DEFAULT_BUILD_SUFFIX = '-release'
xixuanbea010f2017-03-27 10:10:19 -070054
55# The default setting of board for fetching latest build.
Jack Neus56bd8c92022-09-21 23:05:34 +000056_DEFAULT_HEAD = 'main'
xixuanbea010f2017-03-27 10:10:19 -070057
58# The path for storing the latest build.
Ned Nguyenb0a377d2020-08-27 08:43:30 -060059_GS_LATEST_HEAD_PATTERN = '%(board)s%(suffix)s/%(name)s'
xixuanbea010f2017-03-27 10:10:19 -070060
61# The gs bucket to fetch the latest build.
62_GS_BUCKET = 'chromeos-image-archive'
63
64# The file in Google Storage to fetch the latest build.
Dhanya Ganesh8860cf02021-04-13 21:12:12 +000065_LATEST_HEAD = 'LATEST-main'
xixuanbea010f2017-03-27 10:10:19 -070066
Xixuan Wu244e0ec2018-05-23 14:49:55 -070067# The bucket for ChromeOS build release boards. Maintained by GoldenEye.
68_GE_RELEASE_BUILD_BUCKET = 'chromeos-build-release-console'
69
xixuanbea010f2017-03-27 10:10:19 -070070# Special android target to board map.
71_ANDROID_TARGET_TO_BOARD_MAP = {
72 'seed_l8150': 'gm4g_sprout',
73 'bat_land': 'bat'
74}
75
76# CrOS build name patter
77_CROS_BUILD_PATTERN = '%(board)s-%(build_type)s/R%(milestone)s-%(manifest)s'
78
79# Android build name pattern
80_ANDROID_BUILD_PATTERN = '%(branch)s/%(target)s/%(build_id)s'
81
82# The pattern for Launch Control target
83_LAUNCH_CONTROL_TARGET_PATTERN = r'(?P<build_target>.+)-(?P<build_type>[^-]+)'
84
85# The pattern for CrOS build config
86_CROS_BUILD_CONFIG_PATTERN = r'-([^-]+)(?:-group)?'
Xixuan Wu5d6063e2017-09-05 16:15:07 -070087
88
89class NoBuildError(Exception):
90 """Raised when failing to get the required build from Google Storage."""
91
92
93class BuildType(object):
94 """Representing the type of test source build.
95
96 This is used to identify the test source build for testing.
97 """
98 FIRMWARE_RW = 'firmware_rw'
99 FIRMWARE_RO = 'firmware_ro'
100 CROS = 'cros'
101
102
103class BuildVersionKey(object):
104 """Keys referring to the builds to install in run_suites."""
105
106 CROS_VERSION = 'cros_version'
107 ANDROID_BUILD_VERSION = 'android_version'
108 TESTBED_BUILD_VERSION = 'testbed_version'
109 FW_RW_VERSION = 'fwrw_version'
110 FW_RO_VERSION = 'fwro_version'
111
112
113class AndroidBuild(collections.namedtuple(
114 '_AndroidBuildBase', ['branch', 'target', 'build_id']), object):
115 """Class for constructing android build string."""
116
117 def __str__(self):
118 return _ANDROID_BUILD_PATTERN % {'branch': self.branch,
119 'target': self.target,
120 'build_id': self.build_id}
121
122
123class CrOSBuild(collections.namedtuple(
124 '_CrOSBuildBase',
125 ['board', 'build_type', 'milestone', 'manifest']), object):
126 """Class for constructing ChromeOS build string."""
127
128 def __str__(self):
129 return _CROS_BUILD_PATTERN % {'board': self.board,
130 'build_type': self.build_type,
131 'milestone': self.milestone,
132 'manifest': self.manifest}
133
134
135def get_latest_cros_build_from_gs(storage_client, board=None, suffix=None):
136 """Get latest build for given board from Google Storage.
137
138 Args:
139 storage_client: a rest_client.StorageRestClient object.
Jack Neus56bd8c92022-09-21 23:05:34 +0000140 board: the board to fetch latest build. Default is 'main'.
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700141 suffix: suffix represents build channel, like '-release'.
142 Default is '-paladin'.
143
144 Returns:
145 a ChromeOS version string, e.g. '59.0.000.0'.
146
147 Raises:
148 HttpError if error happens in interacting with Google Storage.
149 """
Ned Nguyenb0a377d2020-08-27 08:43:30 -0600150 board = board if board is not None else _DEFAULT_HEAD
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700151 suffix = suffix if suffix is not None else _DEFAULT_BUILD_SUFFIX
Ned Nguyenb0a377d2020-08-27 08:43:30 -0600152 file_to_check = _GS_LATEST_HEAD_PATTERN % {
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700153 'board': board,
154 'suffix': suffix,
Ned Nguyenb0a377d2020-08-27 08:43:30 -0600155 'name': _LATEST_HEAD}
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700156
157 try:
158 return storage_client.read_object(_GS_BUCKET, file_to_check)
159 except apiclient.errors.HttpError as e:
160 raise NoBuildError(
161 'Cannot find latest build for board %s, suffix %s: %s' %
162 (board, suffix, str(e)))
163
164
Xixuan Wu244e0ec2018-05-23 14:49:55 -0700165def get_board_family_mapping_from_gs(storage_client):
166 """Get board_family to boards mapping from Google Storage.
167
168 Args:
169 storage_client: a rest_client.StorageRestClient object.
170
171 Returns:
172 a dictionary of mapping between board family name to boards, e.g.
173 {'nyan': ['nyan', 'nyan_big', 'nyan_blaze', ..]}
174
175 Raises:
176 HttpError if error happens in interacting with Google Storage.
177 """
178 try:
179 boards = storage_client.read_object(_GE_RELEASE_BUILD_BUCKET, 'boards.json')
180 json_object = json.loads(boards)
181 board_family = {}
182 for board in json_object['boards']:
183 group = board['reference_group']
184 if not group:
185 continue
186
187 # This is to change boards like nyan-blaze to nyan_blaze, which is
188 # actually used in lab.
189 board_name = board['public_codename'].replace('-', '_')
190 if group not in board_family:
191 board_family[group] = []
192
193 board_family[group].append(board_name)
194
195 logging.info('Successfully get following board families from GS: %r',
196 board_family.keys())
197 return board_family
198 except apiclient.errors.HttpError as e:
199 logging.error('Cannot load boards.json in bucket %s: %s',
200 _GE_RELEASE_BUILD_BUCKET, str(e))
201 raise
202
203
Jack Neus8f0edb42022-03-17 20:21:39 +0000204def buildinfo_list_to_branch_build_dict(cros_board_list, buildinfo_list,
Jack Neus2cbdc432022-06-24 20:21:30 +0000205 stable_rubik_milestones = None,
Jack Neus8f0edb42022-03-17 20:21:39 +0000206 use_rubik = False):
Craig Bergstrom58263d32018-04-26 14:11:35 -0600207 """Validate and convert a list of BuildInfo to branch build dict.
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700208
209 Args:
Xixuan Wu6fb16272017-10-19 13:16:00 -0700210 cros_board_list: The board list including all CrOS boards.
Xixuan Wuc6819012019-05-23 11:34:59 -0700211 buildinfo_list: A list of BuildInfo objects.
Jack Neus2cbdc432022-06-24 20:21:30 +0000212 stable_rubik_milestones: map of build target to stable Rubik milestone,
213 used to determine where we should use Rubik builds instead of Leagcy.
214 use_rubik: bool. If True will only keep builds for milestones >= the stable
215 rubik milestone for the build target (as specified in
216 stable_rubik_milestone) If False, will only keep builds for milestones <
217 the stable rubik milestone. If a build target is not included in
218 stable_rubik_milestones, no Rubik builds for that build target will be
219 used.
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700220
221 Returns:
Craig Bergstrom58263d32018-04-26 14:11:35 -0600222 A branch build dict:
223 key: a tuple of (board, build_type, milestone), like:
224 ('wolf', 'release', '58')
225 value: the latest manifest for the given tuple, like:
226 '9242.0.0'.
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700227 """
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700228 branch_build_dict = {}
Craig Bergstrom58263d32018-04-26 14:11:35 -0600229 for build in buildinfo_list:
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700230 try:
231 build_config_info = parse_cros_build_config(build.board,
232 build.build_config)
233 except ValueError as e:
234 logging.warning('Failed to parse build config: %s: %s',
235 build.build_config, e)
236 continue
237
238 if build.board != build_config_info.board:
239 logging.warning('Non-matched build_config and board: %s, %s',
240 build.board, build.board)
241 continue
242
Xixuan Wu6fb16272017-10-19 13:16:00 -0700243 if build.board not in cros_board_list:
244 logging.warning('%s is not a valid CrOS board.', build.board)
245 continue
246
Jack Neus2cbdc432022-06-24 20:21:30 +0000247 if stable_rubik_milestones:
248 stable_rubik_milestone = stable_rubik_milestones.get(build.board, None)
Jack Neus8f0edb42022-03-17 20:21:39 +0000249 if use_rubik:
Jack Neus2cbdc432022-06-24 20:21:30 +0000250 # Discard builds for milestones before the stable_rubik_milestone.
251 if not stable_rubik_milestone or int(build.milestone) < stable_rubik_milestone:
252 logging.warning('%s is not a Rubik board for milestone %s, discarding.',
253 build.board, build.milestone)
Jack Neus8f0edb42022-03-17 20:21:39 +0000254 continue
255 else:
Jack Neus2cbdc432022-06-24 20:21:30 +0000256 # Discard builds for milestones after the stable_rubik_milestone.
257 if stable_rubik_milestone and int(build.milestone) >= stable_rubik_milestones:
258 logging.warning('%s is a Rubik board for milestone %s, discarding.',
259 build.board, build.milestone)
Jack Neus8f0edb42022-03-17 20:21:39 +0000260 continue
261
Xixuan Wu8d2f2862018-08-28 16:48:04 -0700262 build_key = (build.board, build.model, build_config_info.type,
263 build.milestone)
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700264 cur_manifest = branch_build_dict.get(build_key)
265 if cur_manifest is not None:
266 branch_build_dict[build_key] = max(
267 [cur_manifest, build.platform], key=version.LooseVersion)
268 else:
269 branch_build_dict[build_key] = build.platform
270
271 return branch_build_dict
272
273
Xinan Lin71eeeb02020-03-10 17:37:12 -0700274def get_cros_builds(build_client, cros_board_list, earliest_end_time,
Jack Neus2cbdc432022-06-24 20:21:30 +0000275 latest_end_time, event_type, stable_rubik_milestones = None):
Xinan Linea1efcb2019-12-30 23:46:42 -0800276 """Get branch builds for ChromeOS boards inside the given time span.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600277
278 Args:
Xixuan Wuc6819012019-05-23 11:34:59 -0700279 build_client: a rest_client.BuildBucketBigqueryClient object, to
280 connect Buildbucket Bigquery.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600281 cros_board_list: The board list including all CrOS boards.
Xinan Linea1efcb2019-12-30 23:46:42 -0800282 earliest_end_time: a datetime.datetime object in UTC.
283 latest_end_time: a datetime.datetime object in UTC.
Xinan Lin71eeeb02020-03-10 17:37:12 -0700284 event: a string of event type.
Jack Neus2cbdc432022-06-24 20:21:30 +0000285 stable_rubik_milestones: map of build target to stable Rubik milestone,
286 used to determine where we should use Rubik builds instead of Leagcy.
Craig Bergstrom58263d32018-04-26 14:11:35 -0600287
288 Returns:
289 a two-tuple of branch build dicts. Each branch build dict has
290 keys and value described below. The first build_dict describes
291 successful builds and the second describes builds that failed
Jared Loucks7068d8b2022-04-28 09:41:33 -0600292 but met the relaxed success requirement (a successful 'UploadTestArtifacts'
Craig Bergstrom58263d32018-04-26 14:11:35 -0600293 stage).
294 key: a tuple of (board, build_type, milestone), like:
295 ('wolf', 'release', '58')
296 value: the latest manifest for the given tuple, like:
297 '9242.0.0'.
298 """
Xixuan Wuc6819012019-05-23 11:34:59 -0700299 # Buildbucket Bigquery use UTC timezone
Xinan Linea1efcb2019-12-30 23:46:42 -0800300 all_branch_builds = build_client.get_passed_builds(
Xinan Lin71eeeb02020-03-10 17:37:12 -0700301 earliest_end_time, latest_end_time, event_type)
Xinan Linea1efcb2019-12-30 23:46:42 -0800302 relaxed_builds = build_client.get_relaxed_passed_builds(
Xinan Lin71eeeb02020-03-10 17:37:12 -0700303 earliest_end_time, latest_end_time, event_type)
Jack Neus8f0edb42022-03-17 20:21:39 +0000304 all_branch_rubik_builds = build_client.get_passed_rubik_builds(
305 earliest_end_time, latest_end_time, event_type)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600306
Jack Neus8f0edb42022-03-17 20:21:39 +0000307 # TODO(b/225382624): Remove all logic fetching Legacy builds
Craig Bergstrom58263d32018-04-26 14:11:35 -0600308 branch_builds_dict = buildinfo_list_to_branch_build_dict(
Jack Neus2cbdc432022-06-24 20:21:30 +0000309 cros_board_list, all_branch_builds, stable_rubik_milestones=stable_rubik_milestones)
Jack Neus8f0edb42022-03-17 20:21:39 +0000310 rubik_branch_builds_dict = buildinfo_list_to_branch_build_dict(
Jack Neus2cbdc432022-06-24 20:21:30 +0000311 cros_board_list, all_branch_rubik_builds, stable_rubik_milestones=stable_rubik_milestones,
Jack Neus8f0edb42022-03-17 20:21:39 +0000312 use_rubik=True)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600313 relaxed_builds_dict = buildinfo_list_to_branch_build_dict(
Jack Neuscb14a3b2022-04-01 16:39:38 +0000314 cros_board_list, relaxed_builds + all_branch_builds,
Jack Neus2cbdc432022-06-24 20:21:30 +0000315 stable_rubik_milestones=stable_rubik_milestones)
Jack Neuscb14a3b2022-04-01 16:39:38 +0000316 # Include Rubik builds in the relaxed builds dict. We can't pass the rubik
317 # builds to the above call because they'll get filtered out (use_rubik is False).
318 relaxed_builds_dict.update(rubik_branch_builds_dict)
Craig Bergstrom58263d32018-04-26 14:11:35 -0600319
Jack Neus8f0edb42022-03-17 20:21:39 +0000320 return dict(branch_builds_dict, **rubik_branch_builds_dict), relaxed_builds_dict
Craig Bergstrom58263d32018-04-26 14:11:35 -0600321
322
Xixuan Wu5d6063e2017-09-05 16:15:07 -0700323def get_latest_launch_control_build(android_client, branch, target):
324 """Get the latest launch control build from Android Build API.
325
326 Args:
327 android_client: a rest_client.AndroidBuildRestClient object.
328 branch: the launch control branch.
329 target: the launch control target.
330
331 Returns:
332 a string latest launch control build id.
333
334 Raises:
335 NoBuildError if no latest launch control build is found.
336 """
337 try:
338 latest_build_id = android_client.get_latest_build_id(branch, target)
339 if latest_build_id is None:
340 raise NoBuildError('No latest builds is found.')
341
342 return latest_build_id
343 except apiclient.errors.HttpError as e:
344 raise NoBuildError('HttpError happened in getting the latest launch '
345 'control build for '
346 '%s,%s: %s' % (branch, target, str(e)))
347
348
349def get_launch_control_builds_by_branch_targets(
350 android_client, android_board_list, launch_control_branch_targets):
351 """Get latest launch_control_builds for android boards.
352
353 For every tasks in this event, if it has settings of launch control
354 branch & target, get the latest launch control build for it.
355
356 Args:
357 android_client: a rest_client.AndroidBuildRestClient object to
358 interact with android build API.
359 android_board_list: a list of Android boards.
360 launch_control_branch_targets: a dict of branch:targets, see property
361 launch_control_branch_targets in base_event.py.
362
363 Returns:
364 a launch control build dict:
365 key: an android board, like 'shamu'.
366 value: a list involves the latest builds for each pair
367 (branch, target) of this board, like:
368 [u'git_nyc-mr2-release/shamu-userdebug/3844975',
369 u'git_nyc-mr1-release/shamu-userdebug/3783920']
370 """
371 launch_control_dict = {}
372 board_to_builds_dict = {}
373 for branch, targets in launch_control_branch_targets.iteritems():
374 for t in targets:
375 try:
376 board = parse_launch_control_target(t).target
377 except ValueError:
378 logging.warning(
379 'Failed to parse launch control target: %s', t)
380 continue
381
382 if board not in android_board_list:
383 continue
384
385 # Use dict here to reduce the times to call AndroidBuild API
386 if launch_control_dict.get((branch, t)) is None:
387 try:
388 build_id = get_latest_launch_control_build(
389 android_client, branch, t)
390 except NoBuildError as e:
391 logging.warning(e)
392 continue
393
394 build = str(AndroidBuild(branch, t, build_id))
395 launch_control_dict[(branch, t)] = build
396 board_to_builds_dict.setdefault(board, []).append(
397 build)
398
399 for board, in board_to_builds_dict.iteritems():
400 mapped_board = get_board_by_android_target(board)
401 if mapped_board != board:
402 logging.debug('Map board %s to %s', board, mapped_board)
403 if board_to_builds_dict.get(mapped_board) is None:
404 del board_to_builds_dict[board]
405 else:
406 board_to_builds_dict[board] = board_to_builds_dict[
407 mapped_board]
408
409 return board_to_builds_dict
410
411
412def parse_launch_control_target(target):
413 """Parse the build target and type from a Launch Control target.
414
415 The Launch Control target has the format of build_target-build_type, e.g.,
416 shamu-eng or dragonboard-userdebug. This method extracts the build target
417 and type from the target name.
418
419 Args:
420 target: Name of a Launch Control target, e.g., shamu-userdebug.
421
422 Returns:
423 a LaunchControlBuildTargetInfo object whose value is like
424 (target='shamu',
425 type='userdebug')
426
427 Raises:
428 ValueError: if target is not valid.
429 """
430 match = re.match(_LAUNCH_CONTROL_TARGET_PATTERN, target)
431 if not match:
432 raise ValueError('target format is not valid')
433
434 return LaunchControlBuildTargetInfo(match.group('build_target'),
435 match.group('build_type'))
436
437
438def parse_cros_build_config(board, build_config):
439 """Parse build_type from a given builder for a given board.
440
441 Args:
442 board: the prefix of a ChromeOS build_config, representing board.
443 build_config: a ChromeOS build_config name, like 'kevin-release'.
444
445 Returns:
446 a CrOSBuildConfigInfo object whose value is like
447 (board='kevin',
448 type='release')
449
450 Raises:
451 ValueError: if build_config is in invalid form.
452 """
453 if build_config[0:len(board)] != board:
454 raise ValueError('build_config cannot be parsed: %s' % build_config)
455
456 match = re.match(_CROS_BUILD_CONFIG_PATTERN, build_config[len(board):])
457 if not match:
458 raise ValueError('build_config %s is not matched %s' % (
459 build_config, _CROS_BUILD_CONFIG_PATTERN))
460
461 return CrOSBuildConfigInfo(board, match.groups()[0])
462
463
464def get_board_by_android_target(target):
465 """Map a android target to a android board.
466
467 # Mapping between an android board name and a build target. This is for
468 # special case handling for certain Android board that the board name and
469 # build target name does not match.
470 # This comes from server/site_utils.py in autotest module.
471
472 Args:
473 target: an android target.
474
475 Returns:
476 a string android board mapped by ANDROID_TARGET_TO_BOARD_MAP.
477 """
478 return _ANDROID_TARGET_TO_BOARD_MAP.get(target, target)
Xixuan Wu588668d2019-01-04 10:33:31 -0800479
480
481def to_full_model(board, model):
482 """Form a full model name with given board, model.
483
484 Args:
485 board: A string board name.
486 model: A string model name.
487
488 Returns:
489 A string full_model name.
490 """
491 return '%s_%s' % (board, model)
Xixuan Wub4b2f412019-05-03 11:22:31 -0700492
493
494def reshape_board(board):
495 """Reshape some variants of board names to original board.
496
497 Args:
498 board: A string board name.
499
500 Returns:
501 A string board name after reshaping.
502 """
503 # The hack derives from build info structure saved in CIDB/buildbucket:
Kazuhiro Inabaf0208222020-03-05 10:33:07 +0900504 # *-kernelnext/*-arcnext etc are saved as board name, but not the real board
Xixuan Wub4b2f412019-05-03 11:22:31 -0700505 # for DUT.
Sean Abraham2a177d72021-02-01 09:38:16 -0700506 # NOTE: please try to keep this list in sync with the corresponding list in
507 # chromite/lib/config_lib.py
508 special_suffixes = [
Navil Perezc7a29172021-03-09 22:06:25 +0000509 '-arc64', #
Sean Abraham2a177d72021-02-01 09:38:16 -0700510 '-arc-r', #
511 '-arc-r-userdebug', #
Jiyoun Haff42b7d2021-04-22 13:35:33 +0900512 '-arc-s', #
Kazuhiro Inabac05184e2022-05-11 16:52:55 +0900513 '-arc-t', #
Sean Abraham2a177d72021-02-01 09:38:16 -0700514 '-arcnext', #
515 '-arcvm', #
Arowa Suliman4c5b2bc2021-08-09 18:57:06 -0700516 '-connectivitynext', #
Sean Abraham2a177d72021-02-01 09:38:16 -0700517 '-borealis', #
518 '-campfire', #
519 '-cfm', #
520 '-kernelnext', #
521 '-kvm', #
Sean Abrahamd6815ba2021-02-26 09:29:53 -0700522 '-libcamera', #
C Shapiro975a83a2021-08-16 15:14:50 -0500523 '-manatee', #
Tomasz Nowickif7f974d2023-02-07 21:21:37 +0000524 '-manatee-kernelnext', #
Sean Abraham2a177d72021-02-01 09:38:16 -0700525 '-ndktranslation', #
Tomasz Nowickia0fd4fc2023-02-07 21:25:30 +0000526 '-nopkvm', #
Tomasz Nowicki0c2bfba2023-02-07 21:25:05 +0000527 '-pkvm', #
Kazuhiro Inaba840dac72021-02-01 16:47:05 +0900528 '-userdebug', #
Sean Abrahambf297a92020-12-10 09:19:49 -0700529 ]
Stephen Boydfb1bfaa2021-07-14 21:19:48 +0000530 # ARM64 userspace boards use 64 suffix but can't put that in list above
531 # because of collisions with boards like kevin-arc64.
Stephen Boyde8446cc2022-10-21 12:21:16 -0700532 ARM64_BOARDS = ['kevin64', 'strongbad64', 'trogdor64', 'cherry64', 'corsola64', 'jacuzzi64']
Sean Abraham2a177d72021-02-01 09:38:16 -0700533 for s in special_suffixes:
Sean Abrahambf297a92020-12-10 09:19:49 -0700534 if board.endswith(s):
535 board = board[:-len(s)]
Stephen Boydfb1bfaa2021-07-14 21:19:48 +0000536 if board in ARM64_BOARDS:
537 # Remove '64' suffix from the board name.
538 board = board[:-2]
Xixuan Wub4b2f412019-05-03 11:22:31 -0700539 return board