blob: ed3423515e3d0abfac2f7a02860d8f848cbc7aaf [file] [log] [blame]
Alex Kleineb77ffa2019-05-28 14:47:44 -06001# Copyright 2019 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Package related functionality."""
6
Alex Klein076841b2019-08-29 15:19:39 -06007from chromite.api import faux
David Burger1e0fe232019-07-01 14:52:07 -06008from chromite.api import validate
Alex Kleineb77ffa2019-05-28 14:47:44 -06009from chromite.api.controller import controller_util
10from chromite.api.gen.chromite.api import binhost_pb2
Alex Klein6becabc2020-09-11 14:03:05 -060011from chromite.api.gen.chromite.api import packages_pb2
David Burger1e0fe232019-07-01 14:52:07 -060012from chromite.api.gen.chromiumos import common_pb2
Alex Kleineb77ffa2019-05-28 14:47:44 -060013from chromite.lib import constants
14from chromite.lib import cros_build_lib
Alex Klein445ae3c2020-01-08 16:40:43 -070015from chromite.lib import cros_logging as logging
Michael Mortensenbbce7e42020-05-01 15:03:49 -060016from chromite.lib import portage_util
Alex Klein87531182019-08-12 15:23:37 -060017from chromite.lib.uprev_lib import GitRef
Alex Klein6becabc2020-09-11 14:03:05 -060018from chromite.lib.parser import package_info
Alex Kleineb77ffa2019-05-28 14:47:44 -060019from chromite.service import packages
20
21
22_OVERLAY_TYPE_TO_NAME = {
23 binhost_pb2.OVERLAYTYPE_PUBLIC: constants.PUBLIC_OVERLAYS,
24 binhost_pb2.OVERLAYTYPE_PRIVATE: constants.PRIVATE_OVERLAYS,
25 binhost_pb2.OVERLAYTYPE_BOTH: constants.BOTH_OVERLAYS,
26}
27
Michael Mortensen2677bf62019-10-29 08:31:25 -060028def _UprevResponse(_input_proto, output_proto, _config):
29 """Add fake paths to a successful uprev response."""
30 output_proto.modified_ebuilds.add().path = '/fake/path1'
31 output_proto.modified_ebuilds.add().path = '/fake/path2'
Alex Kleineb77ffa2019-05-28 14:47:44 -060032
Michael Mortensen2677bf62019-10-29 08:31:25 -060033@faux.success(_UprevResponse)
34@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -060035@validate.require('overlay_type')
36@validate.is_in('overlay_type', _OVERLAY_TYPE_TO_NAME)
37@validate.validation_complete
38def Uprev(input_proto, output_proto, _config):
Alex Kleineb77ffa2019-05-28 14:47:44 -060039 """Uprev all cros workon ebuilds that have changes."""
Alex Klein26e472b2020-03-10 14:35:01 -060040 build_targets = controller_util.ParseBuildTargets(input_proto.build_targets)
Alex Kleineb77ffa2019-05-28 14:47:44 -060041 overlay_type = _OVERLAY_TYPE_TO_NAME[input_proto.overlay_type]
42 chroot = controller_util.ParseChroot(input_proto.chroot)
43 output_dir = input_proto.output_dir or None
44
45 try:
Alex Klein5dd6b1e2019-07-31 15:45:24 -060046 uprevved = packages.uprev_build_targets(build_targets, overlay_type, chroot,
47 output_dir)
Alex Kleineb77ffa2019-05-28 14:47:44 -060048 except packages.Error as e:
49 # Handle module errors nicely, let everything else bubble up.
Mike Frysinger6b5c3cd2019-08-27 16:51:00 -040050 cros_build_lib.Die(e)
David Burger1e0fe232019-07-01 14:52:07 -060051
Alex Klein5dd6b1e2019-07-31 15:45:24 -060052 for path in uprevved:
53 output_proto.modified_ebuilds.add().path = path
54
Alex Klein231d2da2019-07-22 16:44:45 -060055
Michael Mortensen2677bf62019-10-29 08:31:25 -060056def _UprevVersionedPackageResponse(_input_proto, output_proto, _config):
57 """Add fake paths to a successful uprev versioned package response."""
58 uprev_response = output_proto.responses.add()
59 uprev_response.modified_ebuilds.add().path = '/uprev/response/path'
60
61
62@faux.success(_UprevVersionedPackageResponse)
63@faux.empty_error
Alex Klein87531182019-08-12 15:23:37 -060064@validate.require('versions')
65@validate.require('package_info.package_name', 'package_info.category')
Alex Klein231d2da2019-07-22 16:44:45 -060066@validate.validation_complete
Alex Klein87531182019-08-12 15:23:37 -060067def UprevVersionedPackage(input_proto, output_proto, _config):
Evan Hernandez38555d42019-08-05 15:11:54 -060068 """Uprev a versioned package.
69
70 See go/pupr-generator for details about this endpoint.
71 """
Alex Klein87531182019-08-12 15:23:37 -060072 chroot = controller_util.ParseChroot(input_proto.chroot)
73 build_targets = controller_util.ParseBuildTargets(input_proto.build_targets)
74 package = controller_util.PackageInfoToCPV(input_proto.package_info)
75 refs = []
76 for ref in input_proto.versions:
77 refs.append(GitRef(path=ref.repository, ref=ref.ref, revision=ref.revision))
78
79 try:
Alex Klein34afcbc2019-08-22 16:14:31 -060080 result = packages.uprev_versioned_package(package, build_targets, refs,
81 chroot)
Alex Klein87531182019-08-12 15:23:37 -060082 except packages.Error as e:
83 # Handle module errors nicely, let everything else bubble up.
Mike Frysinger6b5c3cd2019-08-27 16:51:00 -040084 cros_build_lib.Die(e)
Alex Klein87531182019-08-12 15:23:37 -060085
Alex Klein34afcbc2019-08-22 16:14:31 -060086 if not result.uprevved:
87 # No uprevs executed, skip the output population.
88 return
89
Yaakov Shaul730814a2019-09-10 13:58:25 -060090 for modified in result.modified:
91 uprev_response = output_proto.responses.add()
92 uprev_response.version = modified.new_version
93 for path in modified.files:
94 uprev_response.modified_ebuilds.add().path = path
95
Alex Klein87531182019-08-12 15:23:37 -060096
Michael Mortensen2677bf62019-10-29 08:31:25 -060097def _GetBestVisibleResponse(_input_proto, output_proto, _config):
98 """Add fake paths to a successful GetBestVisible response."""
Alex Klein6becabc2020-09-11 14:03:05 -060099 pkg_info_msg = common_pb2.PackageInfo(
Michael Mortensen2677bf62019-10-29 08:31:25 -0600100 category='category',
101 package_name='name',
102 version='1.01',
103 )
Alex Klein6becabc2020-09-11 14:03:05 -0600104 output_proto.package_info.CopyFrom(pkg_info_msg)
Michael Mortensen2677bf62019-10-29 08:31:25 -0600105
106
107@faux.success(_GetBestVisibleResponse)
108@faux.empty_error
David Burger1e0fe232019-07-01 14:52:07 -0600109@validate.require('atom')
Alex Klein231d2da2019-07-22 16:44:45 -0600110@validate.validation_complete
111def GetBestVisible(input_proto, output_proto, _config):
David Burger1e0fe232019-07-01 14:52:07 -0600112 """Returns the best visible PackageInfo for the indicated atom."""
Alex Kleinbbef2b32019-08-27 10:38:50 -0600113 build_target = None
114 if input_proto.build_target.name:
115 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
116
117 cpv = packages.get_best_visible(input_proto.atom, build_target=build_target)
Alex Klein6becabc2020-09-11 14:03:05 -0600118 pkg_info_msg = common_pb2.PackageInfo()
119 controller_util.CPVToPackageInfo(cpv, pkg_info_msg)
120 output_proto.package_info.CopyFrom(pkg_info_msg)
Alex Klein551e8052019-08-29 11:23:48 -0600121
122
Michael Mortensen68abdb72019-10-28 09:43:52 -0600123def _ChromeVersionResponse(_input_proto, output_proto, _config):
124 """Add a fake chrome version to a successful response."""
125 output_proto.version = '78.0.3900.0'
126
127
128@faux.success(_ChromeVersionResponse)
129@faux.empty_error
Alex Klein551e8052019-08-29 11:23:48 -0600130@validate.require('build_target.name')
131@validate.validation_complete
132def GetChromeVersion(input_proto, output_proto, _config):
133 """Returns the chrome version."""
134 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
Michael Mortensen9fe740c2019-10-29 14:42:48 -0600135 chrome_version = packages.determine_chrome_version(build_target)
136 if chrome_version:
137 output_proto.version = chrome_version
Alex Kleinda39c6d2019-09-16 14:36:36 -0600138
139
Michael Mortensen2677bf62019-10-29 08:31:25 -0600140def _GetTargetVersionsResponse(_input_proto, output_proto, _config):
141 """Add fake target version fields to a successful response."""
142 output_proto.android_version = '5812377'
143 output_proto.android_branch_version = 'git_nyc-mr1-arc'
144 output_proto.android_target_version = 'cheets'
145 output_proto.chrome_version = '78.0.3900.0'
146 output_proto.platform_version = '12438.0.0'
147 output_proto.milestone_version = '78'
148 output_proto.full_version = 'R78-12438.0.0'
149
150
151@faux.success(_GetTargetVersionsResponse)
152@faux.empty_error
Michael Mortensenb70e8a82019-10-10 18:43:41 -0600153@validate.require('build_target.name')
Alex Klein45b73432020-09-23 13:51:20 -0600154@validate.require_each('packages', ['category', 'package_name'])
Michael Mortensenb70e8a82019-10-10 18:43:41 -0600155@validate.validation_complete
156def GetTargetVersions(input_proto, output_proto, _config):
157 """Returns the target versions."""
158 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
Mike Frysinger8e1c99a2021-03-05 00:58:11 -0500159 # Look up the android package here once since the operation is so slow.
160 android_package = packages.determine_android_package(build_target.name)
161 if android_package:
162 # Android version.
163 android_version = packages.determine_android_version(
164 build_target.name, package=android_package)
165 logging.info('Found android version: %s', android_version)
166 if android_version:
167 output_proto.android_version = android_version
168 # Android branch version.
169 android_branch_version = packages.determine_android_branch(
170 build_target.name, package=android_package)
171 logging.info('Found android branch version: %s', android_branch_version)
172 if android_branch_version:
173 output_proto.android_branch_version = android_branch_version
174 # Android target version.
175 android_target_version = packages.determine_android_target(
176 build_target.name, package=android_package)
177 logging.info('Found android target version: %s', android_target_version)
178 if android_target_version:
179 output_proto.android_target_version = android_target_version
Alex Klein445ae3c2020-01-08 16:40:43 -0700180
Michael Mortensen9fe740c2019-10-29 14:42:48 -0600181 # TODO(crbug/1019770): Investigate cases where builds_chrome is true but
182 # chrome_version is None.
Michael Mortensen42c330e32020-09-02 09:59:16 -0600183
184 # If input_proto.packages is empty, then the default set of packages will
185 # be used as defined in dependency.GetBuildDependency.
186 package_list = None
187 if input_proto.packages:
188 package_list = [
189 controller_util.PackageInfoToCPV(x) for x in input_proto.packages
190 ]
191 builds_chrome = packages.builds(constants.CHROME_CP, build_target,
192 packages=package_list)
Michael Mortensen1d2ab0d2019-10-17 13:19:25 -0600193 if builds_chrome:
Alex Klein445ae3c2020-01-08 16:40:43 -0700194 # Chrome version fetch.
Michael Mortensen9fe740c2019-10-29 14:42:48 -0600195 chrome_version = packages.determine_chrome_version(build_target)
Alex Klein445ae3c2020-01-08 16:40:43 -0700196 logging.info('Found chrome version: %s', chrome_version)
Michael Mortensen9fe740c2019-10-29 14:42:48 -0600197 if chrome_version:
198 output_proto.chrome_version = chrome_version
Alex Klein445ae3c2020-01-08 16:40:43 -0700199
200 # The ChromeOS version info.
Michael Mortensen9fdb14b2019-10-17 11:17:30 -0600201 output_proto.platform_version = packages.determine_platform_version()
Michael Mortensen009cb662019-10-21 11:38:43 -0600202 output_proto.milestone_version = packages.determine_milestone_version()
203 output_proto.full_version = packages.determine_full_version()
Michael Mortensenb70e8a82019-10-10 18:43:41 -0600204
205
Michael Mortensenbfc56392020-04-30 15:23:47 -0600206def _GetBuilderMetadataResponse(input_proto, output_proto, _config):
207 """Add fake metadata fields to a successful response."""
208 # Populate only a few fields to validate faux testing.
209 build_target_metadata = output_proto.build_target_metadata.add()
210 build_target_metadata.build_target = input_proto.build_target.name
211 build_target_metadata.android_container_branch = 'git_pi-arc'
212 model_metadata = output_proto.model_metadata.add()
213 model_metadata.model_name = 'astronaut'
214 model_metadata.ec_firmware_version = 'coral_v1.1.1234-56789f'
215
216
217@faux.success(_GetBuilderMetadataResponse)
218@faux.empty_error
219@validate.require('build_target.name')
220@validate.validation_complete
221def GetBuilderMetadata(input_proto, output_proto, _config):
222 """Returns the target builder metadata."""
223 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
224 build_target_metadata = output_proto.build_target_metadata.add()
225 build_target_metadata.build_target = build_target.name
Michael Mortensenbbce7e42020-05-01 15:03:49 -0600226 # Android version.
Mike Frysingerb53f1822021-03-05 00:44:50 -0500227 android_version = packages.determine_android_version(build_target.name)
Michael Mortensenbbce7e42020-05-01 15:03:49 -0600228 logging.info('Found android version: %s', android_version)
229 if android_version:
230 build_target_metadata.android_container_version = android_version
231 # Android branch version.
Michael Mortensen027ecd82020-05-05 13:13:40 -0600232 android_branch_version = packages.determine_android_branch(build_target.name)
Michael Mortensenbbce7e42020-05-01 15:03:49 -0600233 logging.info('Found android branch version: %s', android_branch_version)
234 if android_branch_version:
235 build_target_metadata.android_container_branch = android_branch_version
236 # Android target version.
Michael Mortensen027ecd82020-05-05 13:13:40 -0600237 android_target_version = packages.determine_android_target(build_target.name)
Michael Mortensenbbce7e42020-05-01 15:03:49 -0600238 logging.info('Found android target version: %s', android_target_version)
239 if android_target_version:
240 build_target_metadata.android_container_target = android_target_version
241
242 build_target_metadata.arc_use_set = 'arc' in portage_util.GetBoardUseFlags(
243 build_target.name)
244
Michael Mortensena4af79e2020-05-06 16:18:48 -0600245 fw_versions = packages.determine_firmware_versions(build_target)
246 build_target_metadata.main_firmware_version = fw_versions.main_fw_version
247 build_target_metadata.ec_firmware_version = fw_versions.ec_fw_version
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -0600248 build_target_metadata.kernel_version = packages.determine_kernel_version(
249 build_target)
Michael Mortensend81d81e2020-06-09 14:20:59 -0600250 fingerprints = packages.find_fingerprints(build_target)
251 build_target_metadata.fingerprints.extend(fingerprints)
Michael Mortensenbfc56392020-04-30 15:23:47 -0600252
Michael Mortensen770bc122020-05-27 17:53:30 -0600253 models = packages.get_models(build_target)
254 if models:
255 all_fw_versions = packages.get_all_firmware_versions(build_target)
256 for model in models:
257 if model in all_fw_versions:
258 fw_versions = all_fw_versions[model]
259 ec = fw_versions.ec_rw or fw_versions.ec
260 main_ro = fw_versions.main
261 main_rw = fw_versions.main_rw or main_ro
262 # Get the firmware key-id for the current board and model.
263 key_id = packages.get_key_id(build_target, model)
264 model_metadata = output_proto.model_metadata.add()
265 model_metadata.model_name = model
266 model_metadata.ec_firmware_version = ec
267 model_metadata.firmware_key_id = key_id
268 model_metadata.main_readonly_firmware_version = main_ro
269 model_metadata.main_readwrite_firmware_version = main_rw
270
271
Alex Klein7d66c092020-03-23 15:13:18 -0600272def _HasPrebuiltSuccess(_input_proto, output_proto, _config):
Michael Mortensen68abdb72019-10-28 09:43:52 -0600273 """The mock success case for HasChromePrebuilt."""
274 output_proto.has_prebuilt = True
275
276
Alex Klein7d66c092020-03-23 15:13:18 -0600277@faux.success(_HasPrebuiltSuccess)
Alex Kleinda39c6d2019-09-16 14:36:36 -0600278@faux.empty_error
279@validate.require('build_target.name')
280@validate.validation_complete
281def HasChromePrebuilt(input_proto, output_proto, _config):
282 """Checks if the most recent version of Chrome has a prebuilt."""
283 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
Alex Klein149fd3b2019-12-16 16:01:05 -0700284 useflags = 'chrome_internal' if input_proto.chrome else None
285 exists = packages.has_prebuilt(constants.CHROME_CP, build_target=build_target,
286 useflags=useflags)
Alex Kleinda39c6d2019-09-16 14:36:36 -0600287
288 output_proto.has_prebuilt = exists
Alex Klein73fb6572019-09-30 16:55:23 -0600289
290
Alex Klein7d66c092020-03-23 15:13:18 -0600291@faux.success(_HasPrebuiltSuccess)
292@faux.empty_error
George Engelbrechtfce26aa2020-03-23 20:53:41 -0600293@validate.require('build_target.name', 'package_info.category',
294 'package_info.package_name')
Alex Klein7d66c092020-03-23 15:13:18 -0600295@validate.validation_complete
296def HasPrebuilt(input_proto, output_proto, _config):
297 """Checks if the most recent version of Chrome has a prebuilt."""
298 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
299 package = controller_util.PackageInfoToCPV(input_proto.package_info).cp
300 useflags = 'chrome_internal' if input_proto.chrome else None
301 exists = packages.has_prebuilt(
302 package, build_target=build_target, useflags=useflags)
303
304 output_proto.has_prebuilt = exists
305
306
Alex Klein73fb6572019-09-30 16:55:23 -0600307def _BuildsChromeSuccess(_input_proto, output_proto, _config):
308 """Mock success case for BuildsChrome."""
309 output_proto.builds_chrome = True
310
311
312@faux.success(_BuildsChromeSuccess)
313@faux.empty_error
314@validate.require('build_target.name')
Alex Klein45b73432020-09-23 13:51:20 -0600315@validate.require_each('packages', ['category', 'package_name'])
Alex Klein73fb6572019-09-30 16:55:23 -0600316@validate.validation_complete
317def BuildsChrome(input_proto, output_proto, _config):
318 """Check if the board builds chrome."""
Alex Kleine65131f2019-10-03 10:34:01 -0600319 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
David Burger0f9dd4e2019-10-08 12:33:42 -0600320 cpvs = [controller_util.PackageInfoToCPV(pi) for pi in input_proto.packages]
321 builds_chrome = packages.builds(constants.CHROME_CP, build_target, cpvs)
Alex Kleine65131f2019-10-03 10:34:01 -0600322 output_proto.builds_chrome = builds_chrome
Alex Klein6becabc2020-09-11 14:03:05 -0600323
324
325def _NeedsChromeSourceSuccess(_input_proto, output_proto, _config):
326 """Mock success case for NeedsChromeSource."""
327 output_proto.needs_chrome_source = True
328 output_proto.builds_chrome = True
329
330 output_proto.reasons.append(
331 packages_pb2.NeedsChromeSourceResponse.NO_PREBUILT)
332 pkg_info_msg = output_proto.packages.add()
333 pkg_info_msg.category = constants.CHROME_CN
334 pkg_info_msg.package_name = constants.CHROME_PN
335
336 output_proto.reasons.append(
337 packages_pb2.NeedsChromeSourceResponse.FOLLOWER_LACKS_PREBUILT)
338 for pkg in constants.OTHER_CHROME_PACKAGES:
339 pkg_info_msg = output_proto.packages.add()
340 pkg_info = package_info.parse(pkg)
341 controller_util.serialize_package_info(pkg_info, pkg_info_msg)
342
343
344@faux.success(_NeedsChromeSourceSuccess)
345@faux.empty_error
346@validate.require('install_request.sysroot.build_target.name')
347@validate.exists('install_request.sysroot.path')
348@validate.validation_complete
349def NeedsChromeSource(input_proto, output_proto, _config):
350 """Check if the build will need the chrome source."""
351 # Input parsing.
352 build_target = controller_util.ParseBuildTarget(
353 input_proto.install_request.sysroot.build_target)
Mike Frysingercf36bb02021-03-05 01:37:20 -0500354 compile_source = (input_proto.install_request.flags.compile_source or
355 input_proto.install_request.flags.toolchain_changed)
Alex Klein6becabc2020-09-11 14:03:05 -0600356 pkgs = [controller_util.deserialize_package_info(pi) for pi in
357 input_proto.install_request.packages]
Alex Kleina8052162021-02-03 14:28:22 -0700358 use_flags = [f.flag for f in input_proto.install_request.use_flags]
Alex Klein6becabc2020-09-11 14:03:05 -0600359
360 result = packages.needs_chrome_source(
361 build_target,
362 compile_source=compile_source,
363 packages=pkgs,
364 useflags=use_flags)
365
366 # Record everything in the response.
367 output_proto.needs_chrome_source = result.needs_chrome_source
368 output_proto.builds_chrome = result.builds_chrome
369
370 # Compile source reason.
371 if compile_source:
372 output_proto.reasons.append(
373 packages_pb2.NeedsChromeSourceResponse.COMPILE_SOURCE)
374
Alex Klein9ce3f682021-06-23 15:06:44 -0600375 # Local uprev reason.
376 if result.local_uprev:
377 output_proto.reasons.append(
378 packages_pb2.NeedsChromeSourceResponse.LOCAL_UPREV)
379
Alex Klein6becabc2020-09-11 14:03:05 -0600380 # No chrome prebuilt reason.
381 if result.missing_chrome_prebuilt:
382 output_proto.reasons.append(
383 packages_pb2.NeedsChromeSourceResponse.NO_PREBUILT)
384
385 # Follower package(s) lack prebuilt reason.
386 if result.missing_follower_prebuilt:
387 output_proto.reasons.append(
388 packages_pb2.NeedsChromeSourceResponse.FOLLOWER_LACKS_PREBUILT)
389
390 for pkg in result.packages:
391 pkg_info = output_proto.packages.add()
392 controller_util.serialize_package_info(pkg, pkg_info)
Shao-Chuan Leeeb834a32021-05-12 17:10:55 +0900393
394
395def _GetAndroidMetadataResponse(_input_proto, output_proto, _config):
396 """Mock Android metadata on successful run."""
397 output_proto.android_package = 'android-vm-rvc'
398 output_proto.android_branch = 'git_rvc-arc'
399 output_proto.android_version = '7123456'
400
401
402@faux.success(_GetAndroidMetadataResponse)
403@faux.empty_error
404@validate.require('build_target.name')
405@validate.validation_complete
406def GetAndroidMetadata(input_proto, output_proto, _config):
407 """Returns Android-related metadata."""
408 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
409 # This returns a full CPVR string, e.g.
410 # 'chromeos-base/android-vm-rvc-7336577-r1'
411 android_full_package = packages.determine_android_package(build_target.name)
412 if android_full_package:
413 logging.info('Found Android package: %s', android_full_package)
414 info = package_info.parse(android_full_package)
415 output_proto.android_package = info.package
416
417 android_branch = packages.determine_android_branch(
418 build_target.name, package=android_full_package)
419 logging.info('Found Android branch: %s', android_branch)
420 output_proto.android_branch = android_branch
421
422 android_version = packages.determine_android_version(
423 build_target.name, package=android_full_package)
424 logging.info('Found Android version: %s', android_version)
425 output_proto.android_version = android_version