blob: 360dd9f276011c147f2eeb03f7777e4ae6a88d51 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
Alex Kleineb77ffa2019-05-28 14:47:44 -06002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Package utility functionality."""
6
Yaakov Shaul730814a2019-09-10 13:58:25 -06007import collections
Ben Reiche779cf42020-12-15 03:21:31 +00008from distutils.version import LooseVersion
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -06009import fileinput
Alex Klein87531182019-08-12 15:23:37 -060010import functools
Yaakov Shaul395ae832019-09-09 14:45:32 -060011import json
Chris McDonaldf7c03d42021-07-21 11:54:26 -060012import logging
Evan Hernandezb51f1522019-08-15 11:29:40 -060013import os
Michael Mortensenb70e8a82019-10-10 18:43:41 -060014import re
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -060015import sys
Alex Klein68a28712021-11-08 11:08:30 -070016from typing import Iterable, List, NamedTuple, Optional, TYPE_CHECKING, Union
Alex Klein87531182019-08-12 15:23:37 -060017
Mike Frysinger2c024062021-05-22 15:43:22 -040018from chromite.third_party.google.protobuf import json_format
Yaakov Shaul730814a2019-09-10 13:58:25 -060019
Andrew Lamb2bde9e42019-11-04 13:24:09 -070020from chromite.api.gen.config import replication_config_pb2
Ram Chandrasekar60f69f32022-06-03 22:49:30 +000021from chromite.lib import chromeos_version
Alex Kleineb77ffa2019-05-28 14:47:44 -060022from chromite.lib import constants
Evan Hernandezb51f1522019-08-15 11:29:40 -060023from chromite.lib import cros_build_lib
Alex Kleineb77ffa2019-05-28 14:47:44 -060024from chromite.lib import git
Michael Mortensende716a12020-05-15 11:27:00 -060025from chromite.lib import image_lib
Michael Mortensenb70e8a82019-10-10 18:43:41 -060026from chromite.lib import osutils
Alex Kleineb77ffa2019-05-28 14:47:44 -060027from chromite.lib import portage_util
Andrew Lamb2bde9e42019-11-04 13:24:09 -070028from chromite.lib import replication_lib
Alex Kleind6195b62019-08-06 16:01:16 -060029from chromite.lib import uprev_lib
Alex Klein18a60af2020-06-11 12:08:47 -060030from chromite.lib.parser import package_info
Shao-Chuan Lee05e51142021-11-24 12:27:37 +090031from chromite.service import android
Alex Kleineb77ffa2019-05-28 14:47:44 -060032
Mike Frysinger68796b52019-08-25 00:04:27 -040033
Alex Klein5caab872021-09-10 11:44:37 -060034if TYPE_CHECKING:
Alex Klein1699fab2022-09-08 08:46:06 -060035 from chromite.lib import build_target_lib
36 from chromite.lib import chroot_lib
Chris McDonaldf7c03d42021-07-21 11:54:26 -060037
Alex Klein36b117f2019-09-30 15:13:46 -060038if cros_build_lib.IsInsideChroot():
Alex Klein1699fab2022-09-08 08:46:06 -060039 from chromite.lib import depgraph
40 from chromite.service import dependency
Alex Klein36b117f2019-09-30 15:13:46 -060041
Alex Klein87531182019-08-12 15:23:37 -060042# Registered handlers for uprevving versioned packages.
43_UPREV_FUNCS = {}
44
Alex Kleineb77ffa2019-05-28 14:47:44 -060045
46class Error(Exception):
Alex Klein1699fab2022-09-08 08:46:06 -060047 """Module's base error class."""
Alex Kleineb77ffa2019-05-28 14:47:44 -060048
49
Alex Klein4de25e82019-08-05 15:58:39 -060050class UnknownPackageError(Error):
Alex Klein1699fab2022-09-08 08:46:06 -060051 """Uprev attempted for a package without a registered handler."""
Alex Klein4de25e82019-08-05 15:58:39 -060052
53
Alex Kleineb77ffa2019-05-28 14:47:44 -060054class UprevError(Error):
Alex Klein1699fab2022-09-08 08:46:06 -060055 """An error occurred while uprevving packages."""
Alex Kleineb77ffa2019-05-28 14:47:44 -060056
57
Michael Mortensenb70e8a82019-10-10 18:43:41 -060058class NoAndroidVersionError(Error):
Alex Klein1699fab2022-09-08 08:46:06 -060059 """An error occurred while trying to determine the android version."""
Michael Mortensenb70e8a82019-10-10 18:43:41 -060060
61
62class NoAndroidBranchError(Error):
Alex Klein1699fab2022-09-08 08:46:06 -060063 """An error occurred while trying to determine the android branch."""
Michael Mortensenb70e8a82019-10-10 18:43:41 -060064
65
66class NoAndroidTargetError(Error):
Alex Klein1699fab2022-09-08 08:46:06 -060067 """An error occurred while trying to determine the android target."""
Michael Mortensenb70e8a82019-10-10 18:43:41 -060068
69
Lizzy Presland0b978e62022-09-09 16:55:29 +000070class KernelVersionError(Error):
71 """An error occurred while trying to determine the kernel version."""
72
73
Alex Klein4de25e82019-08-05 15:58:39 -060074class AndroidIsPinnedUprevError(UprevError):
Alex Klein1699fab2022-09-08 08:46:06 -060075 """Raised when we try to uprev while Android is pinned."""
Alex Klein4de25e82019-08-05 15:58:39 -060076
Alex Klein1699fab2022-09-08 08:46:06 -060077 def __init__(self, new_android_atom):
78 """Initialize a AndroidIsPinnedUprevError.
Alex Klein4de25e82019-08-05 15:58:39 -060079
Alex Klein1699fab2022-09-08 08:46:06 -060080 Args:
Alex Klein348e7692022-10-13 17:03:37 -060081 new_android_atom: The Android atom that we failed to uprev to, due
82 to Android being pinned.
Alex Klein1699fab2022-09-08 08:46:06 -060083 """
84 assert new_android_atom
85 msg = (
86 "Failed up uprev to Android version %s as Android was pinned."
87 % new_android_atom
88 )
89 super().__init__(msg)
90 self.new_android_atom = new_android_atom
Alex Klein87531182019-08-12 15:23:37 -060091
92
Andrew Lamb9563a152019-12-04 11:42:18 -070093class GeneratedCrosConfigFilesError(Error):
Alex Klein1699fab2022-09-08 08:46:06 -060094 """Error when cros_config_schema does not produce expected files"""
Andrew Lamb9563a152019-12-04 11:42:18 -070095
Alex Klein1699fab2022-09-08 08:46:06 -060096 def __init__(self, expected_files, found_files):
97 msg = "Expected to find generated C files: %s. Actually found: %s" % (
98 expected_files,
99 found_files,
100 )
101 super().__init__(msg)
Andrew Lamb9563a152019-12-04 11:42:18 -0700102
Alex Klein7a3a7dd2020-01-08 16:44:38 -0700103
Alex Klein1699fab2022-09-08 08:46:06 -0600104NeedsChromeSourceResult = collections.namedtuple(
105 "NeedsChromeSourceResult",
106 (
107 "needs_chrome_source",
108 "builds_chrome",
109 "packages",
110 "missing_chrome_prebuilt",
111 "missing_follower_prebuilt",
112 "local_uprev",
113 ),
114)
Alex Klein6becabc2020-09-11 14:03:05 -0600115
116
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -0600117def patch_ebuild_vars(ebuild_path, variables):
Alex Klein1699fab2022-09-08 08:46:06 -0600118 """Updates variables in ebuild.
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -0600119
Alex Klein1699fab2022-09-08 08:46:06 -0600120 Use this function rather than portage_util.EBuild.UpdateEBuild when you
121 want to preserve the variable position and quotes within the ebuild.
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -0600122
Alex Klein1699fab2022-09-08 08:46:06 -0600123 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600124 ebuild_path: The path of the ebuild.
125 variables: Dictionary of variables to update in ebuild.
Alex Klein1699fab2022-09-08 08:46:06 -0600126 """
127 try:
128 for line in fileinput.input(ebuild_path, inplace=1):
129 for var, value in variables.items():
130 line = re.sub(rf"\b{var}=\S+", f'{var}="{value}"', line)
131 sys.stdout.write(line)
132 finally:
133 fileinput.close()
Yaakov Shaulcb1cfc32019-09-16 13:51:19 -0600134
135
Alex Klein87531182019-08-12 15:23:37 -0600136def uprevs_versioned_package(package):
Alex Klein1699fab2022-09-08 08:46:06 -0600137 """Decorator to register package uprev handlers."""
138 assert package
Alex Klein87531182019-08-12 15:23:37 -0600139
Alex Klein1699fab2022-09-08 08:46:06 -0600140 def register(func):
141 """Registers |func| as a handler for |package|."""
142 _UPREV_FUNCS[package] = func
Alex Klein87531182019-08-12 15:23:37 -0600143
Alex Klein1699fab2022-09-08 08:46:06 -0600144 @functools.wraps(func)
145 def pass_through(*args, **kwargs):
146 return func(*args, **kwargs)
Alex Klein87531182019-08-12 15:23:37 -0600147
Alex Klein1699fab2022-09-08 08:46:06 -0600148 return pass_through
Alex Klein87531182019-08-12 15:23:37 -0600149
Alex Klein1699fab2022-09-08 08:46:06 -0600150 return register
Alex Klein87531182019-08-12 15:23:37 -0600151
152
Shao-Chuan Lee84bf9a22021-11-19 17:42:11 +0900153class UprevAndroidResult(NamedTuple):
Alex Klein1699fab2022-09-08 08:46:06 -0600154 """Results of an Android uprev."""
155
156 revved: bool
157 android_atom: str = None
158 modified_files: List[str] = None
Shao-Chuan Lee84bf9a22021-11-19 17:42:11 +0900159
160
161def uprev_android(
162 android_package: str,
Alex Klein1699fab2022-09-08 08:46:06 -0600163 chroot: "chroot_lib.Chroot",
164 build_targets: Optional[List["build_target_lib.BuildTarget"]] = None,
Shao-Chuan Lee84bf9a22021-11-19 17:42:11 +0900165 android_build_branch: Optional[str] = None,
166 android_version: Optional[str] = None,
Alex Klein1699fab2022-09-08 08:46:06 -0600167 skip_commit: bool = False,
168) -> UprevAndroidResult:
169 """Performs an Android uprev by calling cros_mark_android_as_stable.
Shao-Chuan Lee84bf9a22021-11-19 17:42:11 +0900170
Alex Klein1699fab2022-09-08 08:46:06 -0600171 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600172 android_package: The Android package to uprev.
173 chroot: The chroot to enter.
174 build_targets: List of build targets to cleanup after uprev.
175 android_build_branch: Override the default Android branch corresponding
176 to the package.
177 android_version: Uprev to the particular version. By default the latest
178 available version is used.
179 skip_commit: Whether to skip committing the change after a successful
180 uprev.
Shao-Chuan Lee84bf9a22021-11-19 17:42:11 +0900181
Alex Klein1699fab2022-09-08 08:46:06 -0600182 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600183 The uprev result containing:
184 revved: Whether an uprev happened.
185 android_atom: If revved, the portage atom for the revved Android
186 ebuild.
187 modified_files: If revved, list of files being modified.
Alex Klein1699fab2022-09-08 08:46:06 -0600188 """
189 command = [
190 "cros_mark_android_as_stable",
191 f"--android_package={android_package}",
192 ]
193 if build_targets:
194 command.append(f'--boards={":".join(bt.name for bt in build_targets)}')
195 if android_build_branch:
196 command.append(f"--android_build_branch={android_build_branch}")
197 if android_version:
198 command.append(f"--force_version={android_version}")
199 if skip_commit:
200 command.append("--skip_commit")
Alex Klein4de25e82019-08-05 15:58:39 -0600201
Alex Klein1699fab2022-09-08 08:46:06 -0600202 result = cros_build_lib.run(
203 command,
204 stdout=True,
205 enter_chroot=True,
206 encoding="utf-8",
207 chroot_args=chroot.get_enter_args(),
208 )
Alex Klein4de25e82019-08-05 15:58:39 -0600209
Alex Klein1699fab2022-09-08 08:46:06 -0600210 # cros_mark_android_as_stable prints the uprev result to stdout as JSON in a
211 # single line. We only take the last line from stdout to make sure no junk
212 # output is included (e.g. messages from bashrc scripts that run upon entering
213 # the chroot.)
214 output = json.loads(result.stdout.strip().splitlines()[-1])
Shao-Chuan Leedea458f2021-11-25 23:46:53 +0900215
Alex Klein1699fab2022-09-08 08:46:06 -0600216 if not output["revved"]:
217 logging.info("Found nothing to rev.")
218 return UprevAndroidResult(revved=False)
Shao-Chuan Lee84bf9a22021-11-19 17:42:11 +0900219
Alex Klein1699fab2022-09-08 08:46:06 -0600220 android_atom = output["android_atom"]
Alex Klein4de25e82019-08-05 15:58:39 -0600221
Alex Klein1699fab2022-09-08 08:46:06 -0600222 for target in build_targets or []:
223 # Sanity check: We should always be able to merge the version of
224 # Android we just unmasked.
225 command = [f"emerge-{target.name}", "-p", "--quiet", f"={android_atom}"]
226 try:
227 cros_build_lib.run(
228 command, enter_chroot=True, chroot_args=chroot.get_enter_args()
229 )
230 except cros_build_lib.RunCommandError:
231 logging.error(
232 "Cannot emerge-%s =%s\nIs Android pinned to an older "
233 "version?",
234 target,
235 android_atom,
236 )
237 raise AndroidIsPinnedUprevError(android_atom)
Alex Klein4de25e82019-08-05 15:58:39 -0600238
Alex Klein1699fab2022-09-08 08:46:06 -0600239 return UprevAndroidResult(
240 revved=True,
241 android_atom=android_atom,
242 modified_files=output["modified_files"],
243 )
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900244
245
Alex Klein1699fab2022-09-08 08:46:06 -0600246def uprev_android_lkgb(
247 android_package: str,
248 build_targets: List["build_target_lib.BuildTarget"],
249 chroot: "chroot_lib.Chroot",
250) -> uprev_lib.UprevVersionedPackageResult:
251 """Uprevs an Android package to the version specified in the LKGB file.
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900252
Alex Klein1699fab2022-09-08 08:46:06 -0600253 This is the PUpr handler for Android packages, triggered whenever the
254 corresponding LKGB file is being updated.
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900255
Alex Klein1699fab2022-09-08 08:46:06 -0600256 PUpr for Android does not test the uprev change in CQ; instead we run separate
257 jobs to test new Android versions, and we write the latest vetted version to
258 the LKGB file. Find the design at go/android-uprev-recipes.
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900259
Alex Klein1699fab2022-09-08 08:46:06 -0600260 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600261 android_package: The Android package to uprev.
262 build_targets: List of build targets to cleanup after uprev.
263 chroot: The chroot to enter.
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900264
Alex Klein1699fab2022-09-08 08:46:06 -0600265 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600266 An uprev_lib.UprevVersionedPackageResult containing the new version and
267 a list of modified files.
Alex Klein1699fab2022-09-08 08:46:06 -0600268 """
269 android_package_dir = android.GetAndroidPackageDir(android_package)
Shao-Chuan Leee0b9ba92023-01-18 19:35:36 +0900270 android_version = android.ReadLKGB(android_package_dir)["build_id"]
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900271
Alex Klein1699fab2022-09-08 08:46:06 -0600272 result = uprev_lib.UprevVersionedPackageResult()
273 uprev_result = uprev_android(
274 android_package,
275 chroot,
276 build_targets=build_targets,
277 android_version=android_version,
278 skip_commit=True,
279 )
280 if not uprev_result.revved:
281 return result
282
283 # cros_mark_android_as_stable returns paths relative to |android.OVERLAY_DIR|.
284 result.add_result(
285 android_version,
286 [
287 os.path.join(android.OVERLAY_DIR, f)
288 for f in uprev_result.modified_files
289 ],
290 )
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900291 return result
292
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900293
294def define_uprev_android_lkgb_handlers():
Alex Klein1699fab2022-09-08 08:46:06 -0600295 """Dynamically define uprev handlers for each Android package"""
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900296
Alex Klein1699fab2022-09-08 08:46:06 -0600297 def define_handler(android_package):
298 """Defines the uprev handler for an Android package."""
299 full_package_name = "chromeos-base/" + android_package
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900300
Alex Klein1699fab2022-09-08 08:46:06 -0600301 @uprevs_versioned_package(full_package_name)
302 def _handler(build_targets, _refs, chroot):
303 return uprev_android_lkgb(android_package, build_targets, chroot)
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900304
Shao-Chuan Leeca2cbcc2022-11-02 08:28:31 +0900305 for android_package in android.GetAllAndroidPackages():
Alex Klein1699fab2022-09-08 08:46:06 -0600306 define_handler(android_package)
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900307
308
309define_uprev_android_lkgb_handlers()
Alex Klein4de25e82019-08-05 15:58:39 -0600310
311
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700312def uprev_build_targets(
Alex Klein1699fab2022-09-08 08:46:06 -0600313 build_targets: Optional[List["build_target_lib.BuildTarget"]],
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700314 overlay_type: str,
Alex Klein1699fab2022-09-08 08:46:06 -0600315 chroot: "chroot_lib.Chroot" = None,
316 output_dir: Optional[str] = None,
317):
318 """Uprev the set provided build targets, or all if not specified.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600319
Alex Klein1699fab2022-09-08 08:46:06 -0600320 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600321 build_targets: The build targets whose overlays should be uprevved,
322 empty or None for all.
323 overlay_type: One of the valid overlay types except None (see
324 constants.VALID_OVERLAYS).
325 chroot: The chroot to clean, if desired.
326 output_dir: The path to optionally dump result files.
Alex Klein1699fab2022-09-08 08:46:06 -0600327 """
328 # Need a valid overlay, but exclude None.
329 assert overlay_type and overlay_type in constants.VALID_OVERLAYS
Alex Kleineb77ffa2019-05-28 14:47:44 -0600330
Alex Klein1699fab2022-09-08 08:46:06 -0600331 if build_targets:
332 overlays = portage_util.FindOverlaysForBoards(
333 overlay_type, boards=[t.name for t in build_targets]
334 )
335 else:
336 overlays = portage_util.FindOverlays(overlay_type)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600337
Alex Klein1699fab2022-09-08 08:46:06 -0600338 return uprev_overlays(
339 overlays,
340 build_targets=build_targets,
341 chroot=chroot,
342 output_dir=output_dir,
343 )
Alex Kleineb77ffa2019-05-28 14:47:44 -0600344
345
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700346def uprev_overlays(
347 overlays: List[str],
Alex Klein1699fab2022-09-08 08:46:06 -0600348 build_targets: Optional[List["build_target_lib.BuildTarget"]] = None,
349 chroot: Optional["chroot_lib.Chroot"] = None,
350 output_dir: Optional[str] = None,
351) -> List[str]:
352 """Uprev the given overlays.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600353
Alex Klein1699fab2022-09-08 08:46:06 -0600354 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600355 overlays: The list of overlay paths.
356 build_targets: The build targets to clean in |chroot|, if desired. No
357 effect unless |chroot| is provided.
358 chroot: The chroot to clean, if desired.
359 output_dir: The path to optionally dump result files.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600360
Alex Klein1699fab2022-09-08 08:46:06 -0600361 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600362 The paths to all the modified ebuild files. This includes the new files
363 that were added (i.e. the new versions) and all the removed files
Alex Klein1699fab2022-09-08 08:46:06 -0600364 (i.e. the old versions).
365 """
366 assert overlays
Alex Kleineb77ffa2019-05-28 14:47:44 -0600367
Alex Klein1699fab2022-09-08 08:46:06 -0600368 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600369
Alex Klein1699fab2022-09-08 08:46:06 -0600370 uprev_manager = uprev_lib.UprevOverlayManager(
371 overlays,
372 manifest,
373 build_targets=build_targets,
374 chroot=chroot,
375 output_dir=output_dir,
376 )
377 uprev_manager.uprev()
Alex Kleineb77ffa2019-05-28 14:47:44 -0600378
Alex Klein1699fab2022-09-08 08:46:06 -0600379 return uprev_manager.modified_ebuilds, uprev_manager.revved_packages
Alex Kleineb77ffa2019-05-28 14:47:44 -0600380
381
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700382def uprev_versioned_package(
383 package: package_info.CPV,
Alex Klein1699fab2022-09-08 08:46:06 -0600384 build_targets: List["build_target_lib.BuildTarget"],
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700385 refs: List[uprev_lib.GitRef],
Alex Klein1699fab2022-09-08 08:46:06 -0600386 chroot: "chroot_lib.Chroot",
387) -> "uprev_lib.UprevVersionedPackageResult":
388 """Call registered uprev handler function for the package.
Alex Klein87531182019-08-12 15:23:37 -0600389
Alex Klein1699fab2022-09-08 08:46:06 -0600390 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600391 package: The package being uprevved.
392 build_targets: The build targets to clean on a successful uprev.
393 refs:
394 chroot: The chroot to enter for cleaning.
Alex Klein87531182019-08-12 15:23:37 -0600395
Alex Klein1699fab2022-09-08 08:46:06 -0600396 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600397 The result.
Alex Klein1699fab2022-09-08 08:46:06 -0600398 """
399 assert package
Alex Klein87531182019-08-12 15:23:37 -0600400
Alex Klein1699fab2022-09-08 08:46:06 -0600401 if package.cp not in _UPREV_FUNCS:
402 raise UnknownPackageError(
403 'Package "%s" does not have a registered handler.' % package.cp
404 )
Alex Klein87531182019-08-12 15:23:37 -0600405
Alex Klein1699fab2022-09-08 08:46:06 -0600406 return _UPREV_FUNCS[package.cp](build_targets, refs, chroot)
Alex Klein87531182019-08-12 15:23:37 -0600407
408
Alex Klein1699fab2022-09-08 08:46:06 -0600409@uprevs_versioned_package("media-libs/virglrenderer")
Navil Perezf57ba872020-06-04 22:38:37 +0000410def uprev_virglrenderer(_build_targets, refs, _chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600411 """Updates virglrenderer ebuilds.
Navil Perezf57ba872020-06-04 22:38:37 +0000412
Alex Klein1699fab2022-09-08 08:46:06 -0600413 See: uprev_versioned_package.
Navil Perezf57ba872020-06-04 22:38:37 +0000414
Alex Klein1699fab2022-09-08 08:46:06 -0600415 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600416 UprevVersionedPackageResult: The result of updating virglrenderer
417 ebuilds.
Alex Klein1699fab2022-09-08 08:46:06 -0600418 """
419 overlay = os.path.join(
420 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
421 )
422 repo_path = os.path.join(
423 constants.SOURCE_ROOT, "src", "third_party", "virglrenderer"
424 )
425 manifest = git.ManifestCheckout.Cached(repo_path)
Navil Perezf57ba872020-06-04 22:38:37 +0000426
Alex Klein1699fab2022-09-08 08:46:06 -0600427 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
428 # TODO(crbug.com/1066242): Ebuilds for virglrenderer are currently
429 # denylisted. Do not force uprevs after builder is stable and ebuilds are no
430 # longer denylisted.
431 uprev_manager.uprev(package_list=["media-libs/virglrenderer"], force=True)
Navil Perezf57ba872020-06-04 22:38:37 +0000432
Alex Klein1699fab2022-09-08 08:46:06 -0600433 updated_files = uprev_manager.modified_ebuilds
434 result = uprev_lib.UprevVersionedPackageResult()
435 result.add_result(refs[-1].revision, updated_files)
436 return result
Navil Perezf57ba872020-06-04 22:38:37 +0000437
Alex Klein1699fab2022-09-08 08:46:06 -0600438
Matthew Lam59ca37d2022-10-24 18:11:06 +0000439@uprevs_versioned_package("x11-apps/igt-gpu-tools")
440def uprev_igt_gpu_tools(_build_targets, refs, _chroot):
441 """Updates igt-gpu-tools ebuilds.
442
443 See: uprev_versioned_package.
444
445 Returns:
446 UprevVersionedPackageResult: The result of updating igt-gpu-tools ebuilds.
447 """
448 overlay = os.path.join(
449 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
450 )
451 repo_path = os.path.join(
452 constants.SOURCE_ROOT, "src", "third_party", "igt-gpu-tools"
453 )
454 manifest = git.ManifestCheckout.Cached(repo_path)
455
456 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
457 uprev_manager.uprev(package_list=["x11-apps/igt-gpu-tools"], force=True)
458
459 updated_files = uprev_manager.modified_ebuilds
460 result = uprev_lib.UprevVersionedPackageResult()
461 result.add_result(refs[-1].revision, updated_files)
462 return result
463
464
Alex Klein1699fab2022-09-08 08:46:06 -0600465@uprevs_versioned_package("chromeos-base/drivefs")
Jose Magana03b5a842020-08-19 12:52:59 +1000466def uprev_drivefs(_build_targets, refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600467 """Updates drivefs ebuilds.
Jose Magana03b5a842020-08-19 12:52:59 +1000468
Alex Klein1699fab2022-09-08 08:46:06 -0600469 DriveFS versions follow the tag format of refs/tags/drivefs_1.2.3.
470 See: uprev_versioned_package.
Jose Magana03b5a842020-08-19 12:52:59 +1000471
Alex Klein1699fab2022-09-08 08:46:06 -0600472 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600473 UprevVersionedPackageResult: The result of updating drivefs ebuilds.
Alex Klein1699fab2022-09-08 08:46:06 -0600474 """
Jose Magana03b5a842020-08-19 12:52:59 +1000475
Alex Klein1699fab2022-09-08 08:46:06 -0600476 DRIVEFS_PATH_PREFIX = "src/private-overlays/chromeos-overlay/chromeos-base"
477 result = uprev_lib.UprevVersionedPackageResult()
478 all_changed_files = []
Jose Magana03b5a842020-08-19 12:52:59 +1000479
Alex Klein1699fab2022-09-08 08:46:06 -0600480 DRIVEFS_REFS_PREFIX = "refs/tags/drivefs_"
481 drivefs_version = _get_latest_version_from_refs(DRIVEFS_REFS_PREFIX, refs)
482 if not drivefs_version:
483 # No valid DriveFS version is identified.
484 return result
485
486 logging.debug("DriveFS version determined from refs: %s", drivefs_version)
487
488 # Attempt to uprev drivefs package.
489 pkg_path = os.path.join(DRIVEFS_PATH_PREFIX, "drivefs")
490 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
491 pkg_path, drivefs_version, chroot, allow_downrev=False
492 )
493
494 if not uprev_result:
495 return result
496 all_changed_files.extend(uprev_result.changed_files)
497 result.add_result(drivefs_version, all_changed_files)
498
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000499 return result
Jose Magana03b5a842020-08-19 12:52:59 +1000500
Jose Magana03b5a842020-08-19 12:52:59 +1000501
Alex Klein1699fab2022-09-08 08:46:06 -0600502@uprevs_versioned_package("chromeos-base/perfetto")
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800503def uprev_perfetto(_build_targets, refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600504 """Updates Perfetto ebuilds.
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800505
Alex Klein1699fab2022-09-08 08:46:06 -0600506 Perfetto versions follow the tag format of refs/tags/v1.2.
507 See: uprev_versioned_package.
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800508
Alex Klein1699fab2022-09-08 08:46:06 -0600509 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600510 UprevVersionedPackageResult: The result of updating Perfetto ebuilds.
Alex Klein1699fab2022-09-08 08:46:06 -0600511 """
512 result = uprev_lib.UprevVersionedPackageResult()
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800513
Alex Klein1699fab2022-09-08 08:46:06 -0600514 PERFETTO_REFS_PREFIX = "refs/tags/v"
Chinglin Yuad12a512022-10-07 17:26:12 +0800515 PERFETTO_PATH = os.path.join(
516 constants.CHROMIUMOS_OVERLAY_DIR, "chromeos-base/perfetto"
517 )
518
519 # Decide the version number to uprev to:
520 # * If |refs| contains refs/tags/v*, get the latest from them.
Alex Klein1699fab2022-09-08 08:46:06 -0600521 perfetto_version = _get_latest_version_from_refs(PERFETTO_REFS_PREFIX, refs)
Chinglin Yuad12a512022-10-07 17:26:12 +0800522 # * Or if |refs| contains only the latest trunk revisions, use the current
523 # stable ebuild version for a revision bump.
524 if refs and not perfetto_version:
525 perfetto_version = uprev_lib.get_stable_ebuild_version(PERFETTO_PATH)
526
Alex Klein1699fab2022-09-08 08:46:06 -0600527 if not perfetto_version:
528 # No valid Perfetto version is identified.
529 return result
530
Alex Klein1699fab2022-09-08 08:46:06 -0600531 # Attempt to uprev perfetto package.
Chinglin Yuad12a512022-10-07 17:26:12 +0800532 # |perfetto_version| is only used in determining the ebuild version. The
533 # package is always updated to the latest HEAD.
Alex Klein1699fab2022-09-08 08:46:06 -0600534 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
535 PERFETTO_PATH,
536 perfetto_version,
537 chroot,
538 allow_downrev=False,
Chinglin Yu84818732022-10-03 12:03:43 +0800539 # Use default ref="HEAD"
Alex Klein1699fab2022-09-08 08:46:06 -0600540 )
541
542 if not uprev_result:
543 return result
544
Chinglin Yu5de28a42022-11-11 19:52:21 +0800545 # Include short git sha hash in the uprev commit message.
546 # Use 9 digits to match the short hash length in `perfetto --version`.
547 short_revision = refs[-1].revision[0:9]
548 version_and_rev = f"{perfetto_version}-{short_revision}"
549 result.add_result(version_and_rev, uprev_result.changed_files)
Alex Klein1699fab2022-09-08 08:46:06 -0600550
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800551 return result
552
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800553
Denis Nikitin63613e32022-09-09 22:26:50 -0700554class AfdoMetadata(NamedTuple):
555 """Data class holding AFDO metadata."""
556
557 var_name: str
558 path: str
559
560
Alex Klein1699fab2022-09-08 08:46:06 -0600561@uprevs_versioned_package("afdo/kernel-profiles")
Yaakov Shaul395ae832019-09-09 14:45:32 -0600562def uprev_kernel_afdo(*_args, **_kwargs):
Alex Klein1699fab2022-09-08 08:46:06 -0600563 """Updates kernel ebuilds with versions from kernel_afdo.json.
Yaakov Shaul395ae832019-09-09 14:45:32 -0600564
Alex Klein1699fab2022-09-08 08:46:06 -0600565 See: uprev_versioned_package.
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600566
Alex Klein1699fab2022-09-08 08:46:06 -0600567 Raises:
Alex Klein348e7692022-10-13 17:03:37 -0600568 EbuildManifestError: When ebuild manifest does not complete
569 successfully.
570 JSONDecodeError: When json is malformed.
Alex Klein1699fab2022-09-08 08:46:06 -0600571 """
Denis Nikitin63613e32022-09-09 22:26:50 -0700572 metadata_dir = os.path.join(
Alex Klein1699fab2022-09-08 08:46:06 -0600573 constants.SOURCE_ROOT,
574 "src",
575 "third_party",
576 "toolchain-utils",
577 "afdo_metadata",
Denis Nikitin63613e32022-09-09 22:26:50 -0700578 )
579 metadata_files = (
580 AfdoMetadata(
581 var_name="AFDO_PROFILE_VERSION",
582 path=os.path.join(metadata_dir, "kernel_afdo.json"),
583 ),
584 AfdoMetadata(
585 var_name="ARM_AFDO_PROFILE_VERSION",
586 path=os.path.join(metadata_dir, "kernel_arm_afdo.json"),
587 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600588 )
Yaakov Shaul395ae832019-09-09 14:45:32 -0600589
Alex Klein1699fab2022-09-08 08:46:06 -0600590 result = uprev_lib.UprevVersionedPackageResult()
Denis Nikitin63613e32022-09-09 22:26:50 -0700591 for metadata in metadata_files:
592 with open(metadata.path, "r") as f:
593 versions = json.load(f)
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600594
Denis Nikitin63613e32022-09-09 22:26:50 -0700595 for kernel_pkg, version_info in versions.items():
596 path = os.path.join(
597 constants.CHROMIUMOS_OVERLAY_DIR, "sys-kernel", kernel_pkg
598 )
599 ebuild_path = os.path.join(
600 constants.SOURCE_ROOT, path, f"{kernel_pkg}-9999.ebuild"
601 )
602 chroot_ebuild_path = os.path.join(
603 constants.CHROOT_SOURCE_ROOT, path, f"{kernel_pkg}-9999.ebuild"
604 )
605 afdo_profile_version = version_info["name"]
606 patch_ebuild_vars(
607 ebuild_path, {metadata.var_name: afdo_profile_version}
Alex Klein1699fab2022-09-08 08:46:06 -0600608 )
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600609
Denis Nikitin63613e32022-09-09 22:26:50 -0700610 try:
611 cmd = ["ebuild", chroot_ebuild_path, "manifest", "--force"]
612 cros_build_lib.run(cmd, enter_chroot=True)
613 except cros_build_lib.RunCommandError as e:
614 raise uprev_lib.EbuildManifestError(
615 "Error encountered when regenerating the manifest for "
616 f"ebuild: {chroot_ebuild_path}\n{e}",
617 e,
618 )
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600619
Denis Nikitin63613e32022-09-09 22:26:50 -0700620 manifest_path = os.path.join(
621 constants.SOURCE_ROOT, path, "Manifest"
622 )
623 result.add_result(
624 afdo_profile_version, [ebuild_path, manifest_path]
625 )
Yaakov Shaul730814a2019-09-10 13:58:25 -0600626
Alex Klein1699fab2022-09-08 08:46:06 -0600627 return result
Yaakov Shaul395ae832019-09-09 14:45:32 -0600628
629
Alex Klein1699fab2022-09-08 08:46:06 -0600630@uprevs_versioned_package("chromeos-base/termina-dlc")
631@uprevs_versioned_package("chromeos-base/termina-tools-dlc")
Maciek Swiech6b12f662022-01-25 16:51:19 +0000632def uprev_termina_dlcs(_build_targets, _refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600633 """Updates shared termina-dlc and termina-tools-dlc ebuilds.
Maciek Swiech6b12f662022-01-25 16:51:19 +0000634
Alex Klein1699fab2022-09-08 08:46:06 -0600635 termina-dlc - chromeos-base/termina-dlc
636 termina-tools-dlc - chromeos-base/termina-tools-dlc
Trent Beginaf51f1b2020-03-09 17:35:31 -0600637
Alex Klein1699fab2022-09-08 08:46:06 -0600638 See: uprev_versioned_package.
639 """
640 termina_dlc_pkg = "termina-dlc"
641 termina_dlc_pkg_path = os.path.join(
642 constants.CHROMIUMOS_OVERLAY_DIR, "chromeos-base", termina_dlc_pkg
643 )
644 tools_dlc_pkg = "termina-tools-dlc"
645 tools_dlc_pkg_path = os.path.join(
646 constants.CHROMIUMOS_OVERLAY_DIR, "chromeos-base", tools_dlc_pkg
647 )
Patrick Meiring5897add2020-09-16 16:30:17 +1000648
Alex Klein1699fab2022-09-08 08:46:06 -0600649 # termina-dlc and termina-tools-dlc are pinned to the same version.
650 version_pin_src_path = _get_version_pin_src_path(termina_dlc_pkg_path)
651 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
Patrick Meiring5897add2020-09-16 16:30:17 +1000652
Alex Klein1699fab2022-09-08 08:46:06 -0600653 result = uprev_lib.uprev_ebuild_from_pin(
654 termina_dlc_pkg_path, version_no_rev, chroot
655 )
656 result += uprev_lib.uprev_ebuild_from_pin(
657 tools_dlc_pkg_path, version_no_rev, chroot
658 )
Patrick Meiring5897add2020-09-16 16:30:17 +1000659
Alex Klein1699fab2022-09-08 08:46:06 -0600660 return result
Patrick Meiring5897add2020-09-16 16:30:17 +1000661
Alex Klein1699fab2022-09-08 08:46:06 -0600662
663@uprevs_versioned_package("chromeos-base/chromeos-lacros")
Julio Hurtadof1befec2021-05-05 21:34:26 +0000664def uprev_lacros(_build_targets, refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600665 """Updates lacros ebuilds.
Julio Hurtadof1befec2021-05-05 21:34:26 +0000666
Alex Klein1699fab2022-09-08 08:46:06 -0600667 Version to uprev to is gathered from the QA qualified version tracking file
668 stored in chromium/src/chrome/LACROS_QA_QUALIFIED_VERSION. Uprev is triggered
669 on modification of this file across all chromium/src branches.
Julio Hurtadof1befec2021-05-05 21:34:26 +0000670
Alex Klein1699fab2022-09-08 08:46:06 -0600671 See: uprev_versioned_package.
672 """
673 result = uprev_lib.UprevVersionedPackageResult()
674 path = os.path.join(
675 constants.CHROMIUMOS_OVERLAY_DIR, "chromeos-base", "chromeos-lacros"
676 )
677 lacros_version = refs[0].revision
678 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
679 path, lacros_version, chroot, allow_downrev=False
680 )
Julio Hurtadoa994e002021-07-07 17:57:45 +0000681
Alex Klein1699fab2022-09-08 08:46:06 -0600682 if not uprev_result:
683 return result
684
685 result.add_result(lacros_version, uprev_result.changed_files)
Julio Hurtadoa994e002021-07-07 17:57:45 +0000686 return result
687
Julio Hurtadof1befec2021-05-05 21:34:26 +0000688
Alex Klein1699fab2022-09-08 08:46:06 -0600689@uprevs_versioned_package("chromeos-base/chromeos-lacros-parallel")
Julio Hurtado870ed322021-12-03 18:22:40 +0000690def uprev_lacros_in_parallel(
Alex Klein1699fab2022-09-08 08:46:06 -0600691 _build_targets: Optional[List["build_target_lib.BuildTarget"]],
Julio Hurtado870ed322021-12-03 18:22:40 +0000692 refs: List[uprev_lib.GitRef],
Alex Klein1699fab2022-09-08 08:46:06 -0600693 chroot: "chroot_lib.Chroot",
694) -> "uprev_lib.UprevVersionedPackageResult":
695 """Updates lacros ebuilds in parallel with ash-chrome.
Julio Hurtado870ed322021-12-03 18:22:40 +0000696
Alex Klein1699fab2022-09-08 08:46:06 -0600697 This handler is going to be used temporarily while lacros transitions to being
698 uprevved atomically with ash-chrome. Unlike a standalone lacros uprev, this
699 handler will not need to look at the QA qualified file. Rather, it will
700 function identical to ash-chrome using git tags.
Julio Hurtado870ed322021-12-03 18:22:40 +0000701
Alex Klein1699fab2022-09-08 08:46:06 -0600702 See: uprev_versioned_package.
Julio Hurtado870ed322021-12-03 18:22:40 +0000703
Alex Klein1699fab2022-09-08 08:46:06 -0600704 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600705 UprevVersionedPackageResult: The result.
Alex Klein1699fab2022-09-08 08:46:06 -0600706 """
707 result = uprev_lib.UprevVersionedPackageResult()
708 path = os.path.join(
709 constants.CHROMIUMOS_OVERLAY_DIR, "chromeos-base", "chromeos-lacros"
710 )
711 lacros_version = uprev_lib.get_version_from_refs(refs)
712 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
713 path, lacros_version, chroot, allow_downrev=False
714 )
Julio Hurtado870ed322021-12-03 18:22:40 +0000715
Alex Klein1699fab2022-09-08 08:46:06 -0600716 if not uprev_result:
717 return result
718
719 result.add_result(lacros_version, uprev_result.changed_files)
Julio Hurtado870ed322021-12-03 18:22:40 +0000720 return result
721
Julio Hurtado870ed322021-12-03 18:22:40 +0000722
Alex Klein1699fab2022-09-08 08:46:06 -0600723@uprevs_versioned_package("app-emulation/parallels-desktop")
Patrick Meiring5897add2020-09-16 16:30:17 +1000724def uprev_parallels_desktop(_build_targets, _refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600725 """Updates Parallels Desktop ebuild - app-emulation/parallels-desktop.
Patrick Meiring5897add2020-09-16 16:30:17 +1000726
Alex Klein1699fab2022-09-08 08:46:06 -0600727 See: uprev_versioned_package
Patrick Meiring5897add2020-09-16 16:30:17 +1000728
Alex Klein1699fab2022-09-08 08:46:06 -0600729 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600730 UprevVersionedPackageResult: The result.
Alex Klein1699fab2022-09-08 08:46:06 -0600731 """
732 package = "parallels-desktop"
733 package_path = os.path.join(
734 constants.CHROMEOS_PARTNER_OVERLAY_DIR, "app-emulation", package
735 )
736 version_pin_src_path = _get_version_pin_src_path(package_path)
Patrick Meiring5897add2020-09-16 16:30:17 +1000737
Alex Klein1699fab2022-09-08 08:46:06 -0600738 # Expect a JSON blob like the following:
739 # {
740 # "version": "1.2.3",
741 # "test_image": { "url": "...", "size": 12345678,
742 # "sha256sum": "<32 bytes of hexadecimal>" }
743 # }
744 with open(version_pin_src_path, "r") as f:
745 pinned = json.load(f)
Patrick Meiring5897add2020-09-16 16:30:17 +1000746
Alex Klein1699fab2022-09-08 08:46:06 -0600747 if "version" not in pinned or "test_image" not in pinned:
748 raise UprevError(
749 "VERSION-PIN for %s missing version and/or "
750 "test_image field" % package
751 )
Patrick Meiring5897add2020-09-16 16:30:17 +1000752
Alex Klein1699fab2022-09-08 08:46:06 -0600753 version = pinned["version"]
754 if not isinstance(version, str):
755 raise UprevError("version in VERSION-PIN for %s not a string" % package)
Patrick Meiring5897add2020-09-16 16:30:17 +1000756
Alex Klein1699fab2022-09-08 08:46:06 -0600757 # Update the ebuild.
758 result = uprev_lib.uprev_ebuild_from_pin(package_path, version, chroot)
Patrick Meiring5897add2020-09-16 16:30:17 +1000759
Alex Klein1699fab2022-09-08 08:46:06 -0600760 # Update the VM image used for testing.
761 test_image_path = (
762 "src/platform/tast-tests-private/src/chromiumos/tast/"
763 "local/bundles/crosint/pita/data/"
764 "pluginvm_image.zip.external"
765 )
766 test_image_src_path = os.path.join(constants.SOURCE_ROOT, test_image_path)
767 with open(test_image_src_path, "w") as f:
768 json.dump(pinned["test_image"], f, indent=2)
769 result.add_result(version, [test_image_src_path])
Patrick Meiring5897add2020-09-16 16:30:17 +1000770
Alex Klein1699fab2022-09-08 08:46:06 -0600771 return result
Trent Beginaf51f1b2020-03-09 17:35:31 -0600772
773
Alex Klein1699fab2022-09-08 08:46:06 -0600774@uprevs_versioned_package("chromeos-base/chromeos-dtc-vm")
Trent Beginaf51f1b2020-03-09 17:35:31 -0600775def uprev_sludge(_build_targets, _refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600776 """Updates sludge VM - chromeos-base/chromeos-dtc-vm.
Trent Begin315d9d92019-12-03 21:55:53 -0700777
Alex Klein1699fab2022-09-08 08:46:06 -0600778 See: uprev_versioned_package.
779 """
780 package = "chromeos-dtc-vm"
781 package_path = os.path.join(
782 "src",
783 "private-overlays",
784 "project-wilco-private",
785 "chromeos-base",
786 package,
787 )
788 version_pin_src_path = _get_version_pin_src_path(package_path)
789 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
Trent Begin315d9d92019-12-03 21:55:53 -0700790
Alex Klein1699fab2022-09-08 08:46:06 -0600791 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
Trent Begin315d9d92019-12-03 21:55:53 -0700792
793
Alex Klein1699fab2022-09-08 08:46:06 -0600794@uprevs_versioned_package("chromeos-base/borealis-dlc")
David Riley8513c1f2021-10-14 17:07:41 -0700795def uprev_borealis_dlc(_build_targets, _refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600796 """Updates shared borealis-dlc ebuild - chromeos-base/borealis-dlc.
David Riley8513c1f2021-10-14 17:07:41 -0700797
Alex Klein1699fab2022-09-08 08:46:06 -0600798 See: uprev_versioned_package.
799 """
800 package_path = os.path.join(
801 "src",
802 "private-overlays",
803 "chromeos-partner-overlay",
804 "chromeos-base",
805 "borealis-dlc",
806 )
David Riley8513c1f2021-10-14 17:07:41 -0700807
Alex Klein1699fab2022-09-08 08:46:06 -0600808 version_pin_src_path = _get_version_pin_src_path(package_path)
809 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
David Riley8513c1f2021-10-14 17:07:41 -0700810
Alex Klein1699fab2022-09-08 08:46:06 -0600811 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
David Riley8513c1f2021-10-14 17:07:41 -0700812
813
Patrick Meiring5897add2020-09-16 16:30:17 +1000814def _get_version_pin_src_path(package_path):
Alex Klein1699fab2022-09-08 08:46:06 -0600815 """Returns the path to the VERSION-PIN file for the given package."""
816 return os.path.join(constants.SOURCE_ROOT, package_path, "VERSION-PIN")
Patrick Meiring5897add2020-09-16 16:30:17 +1000817
818
Alex Klein87531182019-08-12 15:23:37 -0600819@uprevs_versioned_package(constants.CHROME_CP)
Alex Klein4e839252022-01-06 13:29:18 -0700820def uprev_chrome_from_ref(build_targets, refs, _chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600821 """Uprev chrome and its related packages.
Alex Klein87531182019-08-12 15:23:37 -0600822
Alex Klein1699fab2022-09-08 08:46:06 -0600823 See: uprev_versioned_package.
824 """
825 # Determine the version from the refs (tags), i.e. the chrome versions are the
826 # tag names.
827 chrome_version = uprev_lib.get_version_from_refs(refs)
828 logging.debug("Chrome version determined from refs: %s", chrome_version)
Alex Klein87531182019-08-12 15:23:37 -0600829
Alex Klein1699fab2022-09-08 08:46:06 -0600830 return uprev_chrome(chrome_version, build_targets, None)
Alex Kleinf69bd802021-06-22 15:43:49 -0600831
832
Alex Klein9ce3f682021-06-23 15:06:44 -0600833def revbump_chrome(
Alex Klein1699fab2022-09-08 08:46:06 -0600834 build_targets: List["build_target_lib.BuildTarget"] = None,
835 chroot: Optional["chroot_lib.Chroot"] = None,
Alex Klein9ce3f682021-06-23 15:06:44 -0600836) -> uprev_lib.UprevVersionedPackageResult:
Alex Klein1699fab2022-09-08 08:46:06 -0600837 """Attempt to revbump chrome.
Alex Kleinf69bd802021-06-22 15:43:49 -0600838
Alex Klein1699fab2022-09-08 08:46:06 -0600839 Revbumps are done by executing an uprev using the current stable version.
840 E.g. if chrome is on 1.2.3.4 and has a 1.2.3.4_rc-r2.ebuild, performing an
841 uprev on version 1.2.3.4 when there are applicable changes (e.g. to the 9999
842 ebuild) will result in a revbump to 1.2.3.4_rc-r3.ebuild.
843 """
844 chrome_version = uprev_lib.get_stable_chrome_version()
845 return uprev_chrome(chrome_version, build_targets, chroot)
Alex Kleinf69bd802021-06-22 15:43:49 -0600846
847
Alex Klein9ce3f682021-06-23 15:06:44 -0600848def uprev_chrome(
Alex Klein16ea1b32021-10-01 15:48:50 -0600849 chrome_version: str,
Alex Klein1699fab2022-09-08 08:46:06 -0600850 build_targets: Optional[List["build_target_lib.BuildTarget"]],
851 chroot: Optional["chroot_lib.Chroot"],
Alex Klein9ce3f682021-06-23 15:06:44 -0600852) -> uprev_lib.UprevVersionedPackageResult:
Alex Klein1699fab2022-09-08 08:46:06 -0600853 """Attempt to uprev chrome and its related packages to the given version."""
854 uprev_manager = uprev_lib.UprevChromeManager(
855 chrome_version, build_targets=build_targets, chroot=chroot
856 )
857 result = uprev_lib.UprevVersionedPackageResult()
858 # TODO(crbug.com/1080429): Handle all possible outcomes of a Chrome uprev
859 # attempt. The expected behavior is documented in the following table:
860 #
861 # Outcome of Chrome uprev attempt:
862 # NEWER_VERSION_EXISTS:
863 # Do nothing.
864 # SAME_VERSION_EXISTS or REVISION_BUMP:
865 # Uprev followers
866 # Assert not VERSION_BUMP (any other outcome is fine)
867 # VERSION_BUMP or NEW_EBUILD_CREATED:
868 # Uprev followers
869 # Assert that Chrome & followers are at same package version
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600870
Alex Klein1699fab2022-09-08 08:46:06 -0600871 # Start with chrome itself so we can proceed accordingly.
872 chrome_result = uprev_manager.uprev(constants.CHROME_CP)
873 if chrome_result.newer_version_exists:
874 # Cannot use the given version (newer version already exists).
875 return result
876
877 # Also uprev related packages.
878 for package in constants.OTHER_CHROME_PACKAGES:
879 follower_result = uprev_manager.uprev(package)
880 if chrome_result.stable_version and follower_result.version_bump:
881 logging.warning(
882 "%s had a version bump, but no more than a revision bump "
883 "should have been possible.",
884 package,
885 )
886
887 if uprev_manager.modified_ebuilds:
888 # Record changes when we have them.
889 return result.add_result(chrome_version, uprev_manager.modified_ebuilds)
890
David Burger37f48672019-09-18 17:07:56 -0600891 return result
Alex Klein87531182019-08-12 15:23:37 -0600892
Alex Klein87531182019-08-12 15:23:37 -0600893
Alex Klein1699fab2022-09-08 08:46:06 -0600894def _get_latest_version_from_refs(
895 refs_prefix: str, refs: List[uprev_lib.GitRef]
896) -> str:
897 """Get the latest version from refs
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600898
Alex Klein1699fab2022-09-08 08:46:06 -0600899 Versions are compared using |distutils.version.LooseVersion| and
900 the latest version is returned.
Alex Klein87531182019-08-12 15:23:37 -0600901
Alex Klein1699fab2022-09-08 08:46:06 -0600902 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600903 refs_prefix: The refs prefix of the tag format.
904 refs: The tags to parse for the latest version.
Alex Klein87531182019-08-12 15:23:37 -0600905
Alex Klein1699fab2022-09-08 08:46:06 -0600906 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600907 The latest version to use as string.
Alex Klein1699fab2022-09-08 08:46:06 -0600908 """
909 valid_refs = []
910 for gitiles in refs:
911 if gitiles.ref.startswith(refs_prefix):
912 valid_refs.append(gitiles.ref)
Ben Reiche779cf42020-12-15 03:21:31 +0000913
Alex Klein1699fab2022-09-08 08:46:06 -0600914 if not valid_refs:
915 return None
Ben Reiche779cf42020-12-15 03:21:31 +0000916
Alex Klein1699fab2022-09-08 08:46:06 -0600917 # Sort by version and take the latest version.
918 target_version_ref = sorted(valid_refs, key=LooseVersion, reverse=True)[0]
919 return target_version_ref.replace(refs_prefix, "")
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800920
921
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700922def _generate_platform_c_files(
923 replication_config: replication_config_pb2.ReplicationConfig,
Alex Klein1699fab2022-09-08 08:46:06 -0600924 chroot: "chroot_lib.Chroot",
925) -> List[str]:
926 """Generates platform C files from a platform JSON payload.
Andrew Lamb9563a152019-12-04 11:42:18 -0700927
Alex Klein1699fab2022-09-08 08:46:06 -0600928 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600929 replication_config: A ReplicationConfig that has already been run. If it
930 produced a build_config.json file, that file will be used to
931 generate platform C files. Otherwise, nothing will be generated.
932 chroot: The chroot to use to generate.
Andrew Lamb9563a152019-12-04 11:42:18 -0700933
Alex Klein1699fab2022-09-08 08:46:06 -0600934 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600935 A list of generated files.
Alex Klein1699fab2022-09-08 08:46:06 -0600936 """
937 # Generate the platform C files from the build config. Note that it would be
938 # more intuitive to generate the platform C files from the platform config;
939 # however, cros_config_schema does not allow this, because the platform config
940 # payload is not always valid input. For example, if a property is both
941 # 'required' and 'build-only', it will fail schema validation. Thus, use the
942 # build config, and use '-f' to filter.
943 build_config_path = [
944 rule.destination_path
945 for rule in replication_config.file_replication_rules
946 if rule.destination_path.endswith("build_config.json")
947 ]
Andrew Lamb9563a152019-12-04 11:42:18 -0700948
Alex Klein1699fab2022-09-08 08:46:06 -0600949 if not build_config_path:
950 logging.info(
951 "No build_config.json found, will not generate platform C files. "
952 "Replication config: %s",
953 replication_config,
954 )
955 return []
Andrew Lamb9563a152019-12-04 11:42:18 -0700956
Alex Klein1699fab2022-09-08 08:46:06 -0600957 if len(build_config_path) > 1:
958 raise ValueError(
959 "Expected at most one build_config.json destination path. "
960 "Replication config: %s" % replication_config
961 )
Andrew Lamb9563a152019-12-04 11:42:18 -0700962
Alex Klein1699fab2022-09-08 08:46:06 -0600963 build_config_path = build_config_path[0]
Andrew Lamb9563a152019-12-04 11:42:18 -0700964
Alex Klein1699fab2022-09-08 08:46:06 -0600965 # Paths to the build_config.json and dir to output C files to, in the
966 # chroot.
967 build_config_chroot_path = os.path.join(
968 constants.CHROOT_SOURCE_ROOT, build_config_path
969 )
970 generated_output_chroot_dir = os.path.join(
971 constants.CHROOT_SOURCE_ROOT, os.path.dirname(build_config_path)
972 )
Andrew Lamb9563a152019-12-04 11:42:18 -0700973
Alex Klein1699fab2022-09-08 08:46:06 -0600974 command = [
975 "cros_config_schema",
976 "-m",
977 build_config_chroot_path,
978 "-g",
979 generated_output_chroot_dir,
980 "-f",
981 '"TRUE"',
982 ]
Andrew Lamb9563a152019-12-04 11:42:18 -0700983
Alex Klein1699fab2022-09-08 08:46:06 -0600984 cros_build_lib.run(
985 command, enter_chroot=True, chroot_args=chroot.get_enter_args()
986 )
Andrew Lamb9563a152019-12-04 11:42:18 -0700987
Alex Klein1699fab2022-09-08 08:46:06 -0600988 # A relative (to the source root) path to the generated C files.
989 generated_output_dir = os.path.dirname(build_config_path)
990 generated_files = []
991 expected_c_files = ["config.c", "ec_config.c", "ec_config.h"]
992 for f in expected_c_files:
993 if os.path.exists(
994 os.path.join(constants.SOURCE_ROOT, generated_output_dir, f)
995 ):
996 generated_files.append(os.path.join(generated_output_dir, f))
Andrew Lamb9563a152019-12-04 11:42:18 -0700997
Alex Klein1699fab2022-09-08 08:46:06 -0600998 if len(expected_c_files) != len(generated_files):
999 raise GeneratedCrosConfigFilesError(expected_c_files, generated_files)
Andrew Lamb9563a152019-12-04 11:42:18 -07001000
Alex Klein1699fab2022-09-08 08:46:06 -06001001 return generated_files
Andrew Lamb9563a152019-12-04 11:42:18 -07001002
1003
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001004def _get_private_overlay_package_root(ref: uprev_lib.GitRef, package: str):
Alex Klein1699fab2022-09-08 08:46:06 -06001005 """Returns the absolute path to the root of a given private overlay.
Andrew Lambe836f222019-12-09 12:27:38 -07001006
Alex Klein1699fab2022-09-08 08:46:06 -06001007 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001008 ref: GitRef for the private overlay.
1009 package: Path to the package in the overlay.
Alex Klein1699fab2022-09-08 08:46:06 -06001010 """
1011 # There might be a cleaner way to map from package -> path within the source
1012 # tree. For now, just use string patterns.
1013 private_overlay_ref_pattern = (
1014 r"/chromeos\/overlays\/overlay-([\w-]+)-private"
1015 )
1016 match = re.match(private_overlay_ref_pattern, ref.path)
1017 if not match:
1018 raise ValueError(
1019 "ref.path must match the pattern: %s. Actual ref: %s"
1020 % (private_overlay_ref_pattern, ref)
1021 )
Andrew Lambe836f222019-12-09 12:27:38 -07001022
Alex Klein1699fab2022-09-08 08:46:06 -06001023 overlay = match.group(1)
Andrew Lambe836f222019-12-09 12:27:38 -07001024
Alex Klein1699fab2022-09-08 08:46:06 -06001025 return os.path.join(
1026 constants.SOURCE_ROOT,
1027 "src/private-overlays/overlay-%s-private" % overlay,
1028 package,
1029 )
Andrew Lambe836f222019-12-09 12:27:38 -07001030
1031
Alex Klein1699fab2022-09-08 08:46:06 -06001032@uprevs_versioned_package("chromeos-base/chromeos-config-bsp")
Andrew Lambea9a8a22019-12-12 14:03:43 -07001033def replicate_private_config(_build_targets, refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -06001034 """Replicate a private cros_config change to the corresponding public config.
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001035
Alex Klein1699fab2022-09-08 08:46:06 -06001036 See uprev_versioned_package for args
1037 """
1038 package = "chromeos-base/chromeos-config-bsp"
Andrew Lambea9a8a22019-12-12 14:03:43 -07001039
Alex Klein1699fab2022-09-08 08:46:06 -06001040 if len(refs) != 1:
1041 raise ValueError("Expected exactly one ref, actual %s" % refs)
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001042
Alex Klein1699fab2022-09-08 08:46:06 -06001043 # Expect a replication_config.jsonpb in the package root.
1044 package_root = _get_private_overlay_package_root(refs[0], package)
1045 replication_config_path = os.path.join(
1046 package_root, "replication_config.jsonpb"
1047 )
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001048
Alex Klein1699fab2022-09-08 08:46:06 -06001049 try:
1050 replication_config = json_format.Parse(
1051 osutils.ReadFile(replication_config_path),
1052 replication_config_pb2.ReplicationConfig(),
1053 )
1054 except IOError:
1055 raise ValueError(
1056 "Expected ReplicationConfig missing at %s" % replication_config_path
1057 )
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001058
Alex Klein1699fab2022-09-08 08:46:06 -06001059 replication_lib.Replicate(replication_config)
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001060
Alex Klein1699fab2022-09-08 08:46:06 -06001061 modified_files = [
1062 rule.destination_path
1063 for rule in replication_config.file_replication_rules
1064 ]
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001065
Alex Klein1699fab2022-09-08 08:46:06 -06001066 # The generated platform C files are not easily filtered by replication rules,
1067 # i.e. JSON / proto filtering can be described by a FieldMask, arbitrary C
1068 # files cannot. Therefore, replicate and filter the JSON payloads, and then
1069 # generate filtered C files from the JSON payload.
1070 modified_files.extend(
1071 _generate_platform_c_files(replication_config, chroot)
1072 )
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001073
Alex Klein1699fab2022-09-08 08:46:06 -06001074 # Use the private repo's commit hash as the new version.
1075 new_private_version = refs[0].revision
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001076
Alex Klein1699fab2022-09-08 08:46:06 -06001077 # modified_files should contain only relative paths at this point, but the
1078 # returned UprevVersionedPackageResult must contain only absolute paths.
1079 for i, modified_file in enumerate(modified_files):
1080 assert not os.path.isabs(modified_file)
1081 modified_files[i] = os.path.join(constants.SOURCE_ROOT, modified_file)
Andrew Lamb988f4da2019-12-10 10:16:43 -07001082
Alex Klein1699fab2022-09-08 08:46:06 -06001083 return uprev_lib.UprevVersionedPackageResult().add_result(
1084 new_private_version, modified_files
1085 )
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001086
1087
Alex Klein1699fab2022-09-08 08:46:06 -06001088@uprevs_versioned_package("chromeos-base/crosvm")
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001089def uprev_crosvm(_build_targets, refs, _chroot):
Alex Klein1699fab2022-09-08 08:46:06 -06001090 """Updates crosvm ebuilds to latest revision
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001091
Alex Klein1699fab2022-09-08 08:46:06 -06001092 crosvm is not versioned. We are updating to the latest commit on the main
1093 branch.
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001094
Alex Klein1699fab2022-09-08 08:46:06 -06001095 See: uprev_versioned_package.
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001096
Alex Klein1699fab2022-09-08 08:46:06 -06001097 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001098 UprevVersionedPackageResult: The result of updating crosvm ebuilds.
Alex Klein1699fab2022-09-08 08:46:06 -06001099 """
1100 overlay = os.path.join(
1101 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
1102 )
1103 repo_path = os.path.join(constants.SOURCE_ROOT, "src", "crosvm")
1104 manifest = git.ManifestCheckout.Cached(repo_path)
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001105
Alex Klein1699fab2022-09-08 08:46:06 -06001106 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1107 uprev_manager.uprev(
1108 package_list=[
1109 "chromeos-base/crosvm",
1110 "dev-rust/assertions",
1111 "dev-rust/cros_async",
1112 "dev-rust/cros_fuzz",
1113 "dev-rust/data_model",
1114 "dev-rust/enumn",
1115 "dev-rust/io_uring",
1116 "dev-rust/p9",
1117 "dev-rust/sync",
1118 "dev-rust/sys_util",
1119 "dev-rust/tempfile",
1120 "media-sound/audio_streams",
1121 ],
1122 force=True,
1123 )
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001124
Alex Klein1699fab2022-09-08 08:46:06 -06001125 updated_files = uprev_manager.modified_ebuilds
1126 result = uprev_lib.UprevVersionedPackageResult()
1127 result.add_result(refs[0].revision, updated_files)
1128 return result
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001129
1130
Yi Choua4854ac2022-11-14 10:54:24 +08001131@uprevs_versioned_package("chromeos-base/ti50-emulator")
1132def uprev_ti50_emulator(_build_targets, refs, _chroot):
1133 """Updates ti50-emulator ebuilds to latest revision
1134
1135 ti50-emulator is not versioned. We are updating to the latest commit on the
1136 main branch.
1137
1138 See: uprev_versioned_package.
1139
1140 Returns:
1141 UprevVersionedPackageResult: The result of updating ti50-emulator
1142 ebuild.
1143 """
1144 overlay = os.path.join(
1145 constants.SOURCE_ROOT, constants.CHROMEOS_OVERLAY_DIR
1146 )
1147
1148 # The ti50-emulator will touch multiple repos.
1149 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
1150
1151 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1152 uprev_manager.uprev(
1153 package_list=["chromeos-base/ti50-emulator"],
1154 force=True,
1155 )
1156
1157 updated_files = uprev_manager.modified_ebuilds
1158 result = uprev_lib.UprevVersionedPackageResult()
1159 result.add_result(refs[-1].revision, updated_files)
1160 return result
1161
1162
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001163@uprevs_versioned_package("chromeos-base/ec-devutils")
Jeremy Bettis0186d252023-01-19 14:47:46 -07001164def uprev_ecdevutils(_build_targets, refs, _chroot):
1165 """Updates ec-devutils ebuilds to latest revision
1166
1167 ec-devutils is not versioned. We are updating to the latest commit on the main
1168 branch.
1169
1170 See: uprev_versioned_package.
1171
1172 Returns:
1173 UprevVersionedPackageResult: The result of updating ec-devutils ebuilds.
1174 """
1175 overlay = os.path.join(
1176 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
1177 )
1178 repo_path = os.path.join(constants.SOURCE_ROOT, "src", "platform", "ec")
1179 manifest = git.ManifestCheckout.Cached(repo_path)
1180
1181 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1182 uprev_manager.uprev(
1183 package_list=[
1184 "chromeos-base/ec-devutils",
1185 ],
1186 force=True,
1187 )
1188
1189 updated_files = uprev_manager.modified_ebuilds
1190 result = uprev_lib.UprevVersionedPackageResult()
1191 result.add_result(refs[0].revision, updated_files)
1192 return result
1193
1194
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001195@uprevs_versioned_package("chromeos-base/ec-utils")
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001196def uprev_ecutils(_build_targets, refs, _chroot):
1197 """Updates ec-utils ebuilds to latest revision
1198
1199 ec-utils is not versioned. We are updating to the latest commit on the main
1200 branch.
1201
1202 See: uprev_versioned_package.
1203
1204 Returns:
1205 UprevVersionedPackageResult: The result of updating ec-utils ebuilds.
1206 """
1207 overlay = os.path.join(
1208 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
1209 )
1210 repo_path = os.path.join(constants.SOURCE_ROOT, "src", "platform", "ec")
1211 manifest = git.ManifestCheckout.Cached(repo_path)
1212
1213 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1214 uprev_manager.uprev(
1215 package_list=[
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001216 "chromeos-base/ec-utils",
Jeremy Bettis0186d252023-01-19 14:47:46 -07001217 ],
1218 force=True,
1219 )
1220
1221 updated_files = uprev_manager.modified_ebuilds
1222 result = uprev_lib.UprevVersionedPackageResult()
1223 result.add_result(refs[0].revision, updated_files)
1224 return result
1225
1226
1227@uprevs_versioned_package("chromeos-base/ec-utils-test")
1228def uprev_ecutilstest(_build_targets, refs, _chroot):
1229 """Updates ec-utils-test ebuilds to latest revision
1230
1231 ec-utils-test is not versioned. We are updating to the latest commit on the main
1232 branch.
1233
1234 See: uprev_versioned_package.
1235
1236 Returns:
1237 UprevVersionedPackageResult: The result of updating ec-utils-test ebuilds.
1238 """
1239 overlay = os.path.join(
1240 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
1241 )
1242 repo_path = os.path.join(constants.SOURCE_ROOT, "src", "platform", "ec")
1243 manifest = git.ManifestCheckout.Cached(repo_path)
1244
1245 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1246 uprev_manager.uprev(
1247 package_list=[
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001248 "chromeos-base/ec-utils-test",
1249 ],
1250 force=True,
1251 )
1252
1253 updated_files = uprev_manager.modified_ebuilds
1254 result = uprev_lib.UprevVersionedPackageResult()
1255 result.add_result(refs[0].revision, updated_files)
1256 return result
1257
1258
Alex Klein5caab872021-09-10 11:44:37 -06001259def get_best_visible(
Alex Klein1699fab2022-09-08 08:46:06 -06001260 atom: str, build_target: Optional["build_target_lib.BuildTarget"] = None
Alex Klein5caab872021-09-10 11:44:37 -06001261) -> package_info.PackageInfo:
Alex Klein1699fab2022-09-08 08:46:06 -06001262 """Returns the best visible CPV for the given atom.
Alex Kleinbbef2b32019-08-27 10:38:50 -06001263
Alex Klein1699fab2022-09-08 08:46:06 -06001264 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001265 atom: The atom to look up.
1266 build_target: The build target whose sysroot should be searched, or the
1267 SDK if not provided.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001268
Alex Klein1699fab2022-09-08 08:46:06 -06001269 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001270 The best visible package, or None if none are visible.
Alex Klein1699fab2022-09-08 08:46:06 -06001271 """
1272 assert atom
Alex Kleinbbef2b32019-08-27 10:38:50 -06001273
Alex Klein1699fab2022-09-08 08:46:06 -06001274 return portage_util.PortageqBestVisible(
1275 atom,
1276 board=build_target.name if build_target else None,
1277 sysroot=build_target.root if build_target else None,
1278 )
Alex Kleinda39c6d2019-09-16 14:36:36 -06001279
1280
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001281def has_prebuilt(
1282 atom: str,
Alex Klein1699fab2022-09-08 08:46:06 -06001283 build_target: "build_target_lib.BuildTarget" = None,
1284 useflags: Union[Iterable[str], str] = None,
1285) -> bool:
1286 """Check if a prebuilt exists.
Alex Kleinda39c6d2019-09-16 14:36:36 -06001287
Alex Klein1699fab2022-09-08 08:46:06 -06001288 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001289 atom: The package whose prebuilt is being queried.
1290 build_target: The build target whose sysroot should be searched, or the
1291 SDK if not provided.
1292 useflags: Any additional USE flags that should be set. May be a string
1293 of properly formatted USE flags, or an iterable of individual flags.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001294
Alex Klein1699fab2022-09-08 08:46:06 -06001295 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001296 True if there is an available prebuilt, False otherwise.
Alex Klein1699fab2022-09-08 08:46:06 -06001297 """
1298 assert atom
Alex Kleinda39c6d2019-09-16 14:36:36 -06001299
Alex Klein1699fab2022-09-08 08:46:06 -06001300 board = build_target.name if build_target else None
1301 extra_env = None
1302 if useflags:
1303 new_flags = useflags
1304 if not isinstance(useflags, str):
1305 new_flags = " ".join(useflags)
Alex Klein149fd3b2019-12-16 16:01:05 -07001306
Alex Klein1699fab2022-09-08 08:46:06 -06001307 existing = os.environ.get("USE", "")
1308 final_flags = "%s %s" % (existing, new_flags)
1309 extra_env = {"USE": final_flags.strip()}
1310 return portage_util.HasPrebuilt(atom, board=board, extra_env=extra_env)
Alex Klein36b117f2019-09-30 15:13:46 -06001311
1312
David Burger0f9dd4e2019-10-08 12:33:42 -06001313def builds(atom, build_target, packages=None):
Alex Klein1699fab2022-09-08 08:46:06 -06001314 """Check if |build_target| builds |atom| (has it in its depgraph)."""
1315 cros_build_lib.AssertInsideChroot()
Alex Klein36b117f2019-09-30 15:13:46 -06001316
Alex Klein1699fab2022-09-08 08:46:06 -06001317 pkgs = tuple(packages) if packages else None
1318 # TODO(crbug/1081828): Receive and use sysroot.
1319 graph, _sdk_graph = dependency.GetBuildDependency(
1320 build_target.root, build_target.name, pkgs
1321 )
1322 return any(atom in package for package in graph["package_deps"])
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001323
1324
Alex Klein6becabc2020-09-11 14:03:05 -06001325def needs_chrome_source(
Alex Klein1699fab2022-09-08 08:46:06 -06001326 build_target: "build_target_lib.BuildTarget",
Alex Klein6becabc2020-09-11 14:03:05 -06001327 compile_source=False,
1328 packages: Optional[List[package_info.PackageInfo]] = None,
Alex Klein1699fab2022-09-08 08:46:06 -06001329 useflags=None,
1330):
1331 """Check if the chrome source is needed.
Alex Klein6becabc2020-09-11 14:03:05 -06001332
Alex Klein1699fab2022-09-08 08:46:06 -06001333 The chrome source is needed if the build target builds chrome or any of its
1334 follower packages, and can't use a prebuilt for them either because it's not
1335 available, or because we can't use prebuilts because it must build from
1336 source.
1337 """
1338 cros_build_lib.AssertInsideChroot()
Alex Klein6becabc2020-09-11 14:03:05 -06001339
Alex Klein1699fab2022-09-08 08:46:06 -06001340 # Check if it builds chrome and/or a follower package.
1341 graph = depgraph.get_sysroot_dependency_graph(build_target.root, packages)
1342 builds_chrome = constants.CHROME_CP in graph
1343 builds_follower = {
1344 pkg: pkg in graph for pkg in constants.OTHER_CHROME_PACKAGES
1345 }
Alex Klein6becabc2020-09-11 14:03:05 -06001346
Alex Klein1699fab2022-09-08 08:46:06 -06001347 local_uprev = builds_chrome and revbump_chrome([build_target])
Alex Klein9ce3f682021-06-23 15:06:44 -06001348
Alex Klein1699fab2022-09-08 08:46:06 -06001349 # When we are compiling source set False since we do not use prebuilts.
1350 # When not compiling from source, start with True, i.e. we have every prebuilt
1351 # we've checked for up to this point.
1352 has_chrome_prebuilt = not compile_source
1353 has_follower_prebuilts = not compile_source
1354 # Save packages that need prebuilts for reporting.
1355 pkgs_needing_prebuilts = []
1356 if compile_source:
1357 # Need everything.
Alex Klein6becabc2020-09-11 14:03:05 -06001358 pkgs_needing_prebuilts.append(constants.CHROME_CP)
Alex Klein1699fab2022-09-08 08:46:06 -06001359 pkgs_needing_prebuilts.extend(
1360 [pkg for pkg, builds_pkg in builds_follower.items() if builds_pkg]
1361 )
1362 else:
1363 # Check chrome itself.
1364 if builds_chrome:
1365 has_chrome_prebuilt = has_prebuilt(
1366 constants.CHROME_CP,
1367 build_target=build_target,
1368 useflags=useflags,
1369 )
1370 if not has_chrome_prebuilt:
1371 pkgs_needing_prebuilts.append(constants.CHROME_CP)
1372 # Check follower packages.
1373 for pkg, builds_pkg in builds_follower.items():
1374 if not builds_pkg:
1375 continue
1376 prebuilt = has_prebuilt(
1377 pkg, build_target=build_target, useflags=useflags
1378 )
1379 has_follower_prebuilts &= prebuilt
1380 if not prebuilt:
1381 pkgs_needing_prebuilts.append(pkg)
1382 # Postcondition: has_chrome_prebuilt and has_follower_prebuilts now correctly
1383 # reflect whether we actually have the corresponding prebuilts for the build.
Alex Klein6becabc2020-09-11 14:03:05 -06001384
Alex Klein1699fab2022-09-08 08:46:06 -06001385 needs_chrome = builds_chrome and not has_chrome_prebuilt
1386 needs_follower = (
1387 any(builds_follower.values()) and not has_follower_prebuilts
1388 )
Alex Klein6becabc2020-09-11 14:03:05 -06001389
Alex Klein1699fab2022-09-08 08:46:06 -06001390 return NeedsChromeSourceResult(
1391 needs_chrome_source=needs_chrome or needs_follower,
1392 builds_chrome=builds_chrome,
1393 packages=[package_info.parse(p) for p in pkgs_needing_prebuilts],
1394 missing_chrome_prebuilt=not has_chrome_prebuilt,
1395 missing_follower_prebuilt=not has_follower_prebuilts,
1396 local_uprev=local_uprev,
1397 )
Alex Klein6becabc2020-09-11 14:03:05 -06001398
1399
Alex Klein68a28712021-11-08 11:08:30 -07001400class TargetVersions(NamedTuple):
Alex Klein1699fab2022-09-08 08:46:06 -06001401 """Data class for the info that makes up the "target versions"."""
1402
1403 android_version: str
1404 android_branch: str
1405 android_target: str
1406 chrome_version: str
1407 platform_version: str
1408 milestone_version: str
1409 full_version: str
Alex Klein68a28712021-11-08 11:08:30 -07001410
1411
1412def get_target_versions(
Alex Klein1699fab2022-09-08 08:46:06 -06001413 build_target: "build_target_lib.BuildTarget",
1414 packages: List[package_info.PackageInfo] = None,
Alex Klein68a28712021-11-08 11:08:30 -07001415) -> TargetVersions:
Alex Klein1699fab2022-09-08 08:46:06 -06001416 """Aggregate version info for a few key packages and the OS as a whole."""
1417 # Android version.
1418 android_version = determine_android_version(build_target.name)
1419 logging.info("Found android version: %s", android_version)
1420 # Android branch version.
1421 android_branch = determine_android_branch(build_target.name)
1422 logging.info("Found android branch version: %s", android_branch)
1423 # Android target version.
1424 android_target = determine_android_target(build_target.name)
1425 logging.info("Found android target version: %s", android_target)
Alex Klein68a28712021-11-08 11:08:30 -07001426
Alex Klein1699fab2022-09-08 08:46:06 -06001427 # TODO(crbug/1019770): Investigate cases where builds_chrome is true but
1428 # chrome_version is None.
Alex Klein68a28712021-11-08 11:08:30 -07001429
Alex Klein1699fab2022-09-08 08:46:06 -06001430 builds_chrome = builds(constants.CHROME_CP, build_target, packages=packages)
1431 chrome_version = None
1432 if builds_chrome:
1433 # Chrome version fetch.
1434 chrome_version = determine_chrome_version(build_target)
1435 logging.info("Found chrome version: %s", chrome_version)
Alex Klein68a28712021-11-08 11:08:30 -07001436
Alex Klein1699fab2022-09-08 08:46:06 -06001437 # The ChromeOS version info.
1438 platform_version = determine_platform_version()
1439 milestone_version = determine_milestone_version()
1440 full_version = determine_full_version()
Alex Klein68a28712021-11-08 11:08:30 -07001441
Alex Klein1699fab2022-09-08 08:46:06 -06001442 return TargetVersions(
1443 android_version,
1444 android_branch,
1445 android_target,
1446 chrome_version,
1447 platform_version,
1448 milestone_version,
1449 full_version,
1450 )
Alex Klein68a28712021-11-08 11:08:30 -07001451
1452
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001453def determine_chrome_version(
Alex Klein1699fab2022-09-08 08:46:06 -06001454 build_target: "build_target_lib.BuildTarget",
1455) -> Optional[str]:
1456 """Returns the current Chrome version for the board (or in buildroot).
Michael Mortensenc2615b72019-10-15 08:12:24 -06001457
Alex Klein1699fab2022-09-08 08:46:06 -06001458 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001459 build_target: The board build target.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001460
Alex Klein1699fab2022-09-08 08:46:06 -06001461 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001462 The chrome version if available.
Alex Klein1699fab2022-09-08 08:46:06 -06001463 """
1464 # TODO(crbug/1019770): Long term we should not need the try/catch here once
1465 # the builds function above only returns True for chrome when
1466 # determine_chrome_version will succeed.
1467 try:
1468 pkg_info = portage_util.PortageqBestVisible(
1469 constants.CHROME_CP, build_target.name, cwd=constants.SOURCE_ROOT
1470 )
1471 except cros_build_lib.RunCommandError as e:
1472 # Return None because portage failed when trying to determine the chrome
1473 # version.
1474 logging.warning("Caught exception in determine_chrome_package: %s", e)
1475 return None
1476 # Something like 78.0.3877.4_rc -> 78.0.3877.4
1477 return pkg_info.version.partition("_")[0]
Michael Mortensenc2615b72019-10-15 08:12:24 -06001478
1479
Alex Klein68a28712021-11-08 11:08:30 -07001480@functools.lru_cache()
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001481def determine_android_package(board: str) -> Optional[str]:
Alex Klein1699fab2022-09-08 08:46:06 -06001482 """Returns the active Android container package in use by the board.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001483
Alex Klein1699fab2022-09-08 08:46:06 -06001484 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001485 board: The board name this is specific to.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001486
Alex Klein1699fab2022-09-08 08:46:06 -06001487 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001488 The android package string if there is one.
Alex Klein1699fab2022-09-08 08:46:06 -06001489 """
1490 try:
1491 packages = portage_util.GetPackageDependencies(
1492 "virtual/target-os", board=board
1493 )
1494 except cros_build_lib.RunCommandError as e:
1495 # Return None because a command (likely portage) failed when trying to
1496 # determine the package.
1497 logging.warning("Caught exception in determine_android_package: %s", e)
1498 return None
1499
1500 # We assume there is only one Android package in the depgraph.
1501 for package in packages:
1502 if package.startswith(
1503 "chromeos-base/android-container-"
1504 ) or package.startswith("chromeos-base/android-vm-"):
1505 return package
Michael Mortensene0f4b542019-10-24 15:30:23 -06001506 return None
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001507
1508
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001509def determine_android_version(board: str, package: str = None):
Alex Klein1699fab2022-09-08 08:46:06 -06001510 """Determine the current Android version in buildroot now and return it.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001511
Alex Klein1699fab2022-09-08 08:46:06 -06001512 This uses the typical portage logic to determine which version of Android
1513 is active right now in the buildroot.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001514
Alex Klein1699fab2022-09-08 08:46:06 -06001515 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001516 board: The board name this is specific to.
1517 package: The Android package, if already computed.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001518
Alex Klein1699fab2022-09-08 08:46:06 -06001519 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001520 The Android build ID of the container for the board.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001521
Alex Klein1699fab2022-09-08 08:46:06 -06001522 Raises:
Alex Klein348e7692022-10-13 17:03:37 -06001523 NoAndroidVersionError: if no unique Android version can be determined.
Alex Klein1699fab2022-09-08 08:46:06 -06001524 """
1525 if not package:
1526 package = determine_android_package(board)
1527 if not package:
1528 return None
1529 cpv = package_info.SplitCPV(package)
1530 if not cpv:
1531 raise NoAndroidVersionError(
1532 "Android version could not be determined for %s" % board
1533 )
1534 return cpv.version_no_rev
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001535
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001536
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001537def determine_android_branch(board, package=None):
Alex Klein1699fab2022-09-08 08:46:06 -06001538 """Returns the Android branch in use by the active container ebuild."""
1539 if not package:
1540 package = determine_android_package(board)
1541 if not package:
1542 return None
1543 ebuild_path = portage_util.FindEbuildForBoardPackage(package, board)
1544 # We assume all targets pull from the same branch and that we always
1545 # have at least one of the following targets.
Shao-Chuan Leeca2cbcc2022-11-02 08:28:31 +09001546 # TODO(b/187795671): Do this in a less hacky way.
1547 targets = android.GetAllAndroidEbuildTargets()
Alex Klein1699fab2022-09-08 08:46:06 -06001548 ebuild_content = osutils.SourceEnvironment(ebuild_path, targets)
1549 for target in targets:
1550 if target in ebuild_content:
1551 branch = re.search(r"(.*?)-linux-", ebuild_content[target])
1552 if branch is not None:
1553 return branch.group(1)
1554 raise NoAndroidBranchError(
1555 "Android branch could not be determined for %s (ebuild empty?)" % board
1556 )
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001557
1558
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001559def determine_android_target(board, package=None):
Alex Klein1699fab2022-09-08 08:46:06 -06001560 """Returns the Android target in use by the active container ebuild."""
1561 if not package:
1562 package = determine_android_package(board)
1563 if not package:
1564 return None
1565 if package.startswith("chromeos-base/android-vm-"):
1566 return "bertha"
1567 elif package.startswith("chromeos-base/android-container-"):
1568 return "cheets"
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001569
Alex Klein1699fab2022-09-08 08:46:06 -06001570 raise NoAndroidTargetError(
1571 "Android Target cannot be determined for the package: %s" % package
1572 )
Michael Mortensen9fdb14b2019-10-17 11:17:30 -06001573
1574
1575def determine_platform_version():
Alex Klein1699fab2022-09-08 08:46:06 -06001576 """Returns the platform version from the source root."""
1577 # Platform version is something like '12575.0.0'.
1578 version = chromeos_version.VersionInfo.from_repo(constants.SOURCE_ROOT)
1579 return version.VersionString()
Michael Mortensen009cb662019-10-21 11:38:43 -06001580
1581
1582def determine_milestone_version():
Alex Klein1699fab2022-09-08 08:46:06 -06001583 """Returns the platform version from the source root."""
1584 # Milestone version is something like '79'.
1585 version = chromeos_version.VersionInfo.from_repo(constants.SOURCE_ROOT)
1586 return version.chrome_branch
Michael Mortensen009cb662019-10-21 11:38:43 -06001587
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001588
Michael Mortensen009cb662019-10-21 11:38:43 -06001589def determine_full_version():
Alex Klein1699fab2022-09-08 08:46:06 -06001590 """Returns the full version from the source root."""
1591 # Full version is something like 'R79-12575.0.0'.
1592 milestone_version = determine_milestone_version()
1593 platform_version = determine_platform_version()
1594 full_version = "R%s-%s" % (milestone_version, platform_version)
1595 return full_version
Michael Mortensen71ef5682020-05-07 14:29:24 -06001596
1597
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001598def find_fingerprints(
Alex Klein1699fab2022-09-08 08:46:06 -06001599 build_target: "build_target_lib.BuildTarget",
1600) -> List[str]:
1601 """Returns a list of fingerprints for this build.
Michael Mortensende716a12020-05-15 11:27:00 -06001602
Alex Klein1699fab2022-09-08 08:46:06 -06001603 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001604 build_target: The build target.
Michael Mortensende716a12020-05-15 11:27:00 -06001605
Alex Klein1699fab2022-09-08 08:46:06 -06001606 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001607 List of fingerprint strings.
Alex Klein1699fab2022-09-08 08:46:06 -06001608 """
1609 cros_build_lib.AssertInsideChroot()
1610 fp_file = "cheets-fingerprint.txt"
1611 fp_path = os.path.join(
1612 image_lib.GetLatestImageLink(build_target.name), fp_file
1613 )
1614 if not os.path.isfile(fp_path):
1615 logging.info("Fingerprint file not found: %s", fp_path)
1616 return []
1617 logging.info("Reading fingerprint file: %s", fp_path)
1618 fingerprints = osutils.ReadFile(fp_path).splitlines()
1619 return fingerprints
Michael Mortensende716a12020-05-15 11:27:00 -06001620
1621
Alex Klein1699fab2022-09-08 08:46:06 -06001622def get_all_firmware_versions(build_target: "build_target_lib.BuildTarget"):
1623 """Extract firmware version for all models present.
Michael Mortensen59e30872020-05-18 14:12:49 -06001624
Alex Klein1699fab2022-09-08 08:46:06 -06001625 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001626 build_target: The build target.
Michael Mortensen59e30872020-05-18 14:12:49 -06001627
Alex Klein1699fab2022-09-08 08:46:06 -06001628 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001629 A dict of FirmwareVersions namedtuple instances by model.
1630 Each element will be populated based on whether it was present in the
1631 command output.
Alex Klein1699fab2022-09-08 08:46:06 -06001632 """
1633 cros_build_lib.AssertInsideChroot()
1634 result = {}
1635 # Note that example output for _get_firmware_version_cmd_result is available
1636 # in the packages_unittest.py for testing get_all_firmware_versions.
1637 cmd_result = _get_firmware_version_cmd_result(build_target)
Michael Mortensen59e30872020-05-18 14:12:49 -06001638
Alex Klein1699fab2022-09-08 08:46:06 -06001639 if cmd_result:
1640 # There is a blank line between the version info for each model.
1641 firmware_version_payloads = cmd_result.split("\n\n")
1642 for firmware_version_payload in firmware_version_payloads:
1643 if "BIOS" in firmware_version_payload:
1644 firmware_version = _find_firmware_versions(
1645 firmware_version_payload
1646 )
1647 result[firmware_version.model] = firmware_version
1648 return result
Michael Mortensen59e30872020-05-18 14:12:49 -06001649
1650
Benjamin Shai0858cd32022-01-10 20:23:49 +00001651class FirmwareVersions(NamedTuple):
Alex Klein1699fab2022-09-08 08:46:06 -06001652 """Tuple to hold firmware versions, with truthiness."""
Benjamin Shai0858cd32022-01-10 20:23:49 +00001653
Alex Klein1699fab2022-09-08 08:46:06 -06001654 model: Optional[str]
1655 main: Optional[str]
1656 main_rw: Optional[str]
1657 ec: Optional[str]
1658 ec_rw: Optional[str]
1659
1660 def __bool__(self):
1661 return bool(
1662 self.model or self.main or self.main_rw or self.ec or self.ec_rw
1663 )
Michael Mortensen71ef5682020-05-07 14:29:24 -06001664
1665
Alex Klein1699fab2022-09-08 08:46:06 -06001666def get_firmware_versions(build_target: "build_target_lib.BuildTarget"):
1667 """Extract version information from the firmware updater, if one exists.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001668
Alex Klein1699fab2022-09-08 08:46:06 -06001669 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001670 build_target: The build target.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001671
Alex Klein1699fab2022-09-08 08:46:06 -06001672 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001673 A FirmwareVersions namedtuple instance.
1674 Each element will either be set to the string output by the firmware
1675 updater shellball, or None if there is no firmware updater.
Alex Klein1699fab2022-09-08 08:46:06 -06001676 """
1677 cros_build_lib.AssertInsideChroot()
1678 cmd_result = _get_firmware_version_cmd_result(build_target)
1679 if cmd_result:
1680 return _find_firmware_versions(cmd_result)
1681 else:
1682 return FirmwareVersions(None, None, None, None, None)
Michael Mortensen71ef5682020-05-07 14:29:24 -06001683
1684
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001685def _get_firmware_version_cmd_result(
Alex Klein1699fab2022-09-08 08:46:06 -06001686 build_target: "build_target_lib.BuildTarget",
1687) -> Optional[str]:
1688 """Gets the raw result output of the firmware updater version command.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001689
Alex Klein1699fab2022-09-08 08:46:06 -06001690 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001691 build_target: The build target.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001692
Alex Klein1699fab2022-09-08 08:46:06 -06001693 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001694 Command execution result.
Alex Klein1699fab2022-09-08 08:46:06 -06001695 """
1696 updater = os.path.join(
1697 build_target.root, "usr/sbin/chromeos-firmwareupdate"
1698 )
1699 logging.info("Calling updater %s", updater)
1700 # Call the updater using the chroot-based path.
1701 try:
1702 return cros_build_lib.run(
1703 [updater, "-V"],
1704 capture_output=True,
1705 log_output=True,
1706 encoding="utf-8",
1707 ).stdout
1708 except cros_build_lib.RunCommandError:
1709 # Updater probably doesn't exist (e.g. betty).
1710 return None
Michael Mortensen71ef5682020-05-07 14:29:24 -06001711
1712
1713def _find_firmware_versions(cmd_output):
Alex Klein1699fab2022-09-08 08:46:06 -06001714 """Finds firmware version output via regex matches against the cmd_output.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001715
Alex Klein1699fab2022-09-08 08:46:06 -06001716 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001717 cmd_output: The raw output to search against.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001718
Alex Klein1699fab2022-09-08 08:46:06 -06001719 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001720 FirmwareVersions namedtuple with results.
1721 Each element will either be set to the string output by the firmware
1722 updater shellball, or None if there is no match.
Alex Klein1699fab2022-09-08 08:46:06 -06001723 """
Michael Mortensen71ef5682020-05-07 14:29:24 -06001724
Alex Klein1699fab2022-09-08 08:46:06 -06001725 # Sometimes a firmware bundle includes a special combination of RO+RW
1726 # firmware. In this case, the RW firmware version is indicated with a "(RW)
1727 # version" field. In other cases, the "(RW) version" field is not present.
1728 # Therefore, search for the "(RW)" fields first and if they aren't present,
1729 # fallback to the other format. e.g. just "BIOS version:".
1730 # TODO(mmortensen): Use JSON once the firmware updater supports it.
1731 main = None
1732 main_rw = None
1733 ec = None
1734 ec_rw = None
1735 model = None
Michael Mortensen71ef5682020-05-07 14:29:24 -06001736
Alex Klein1699fab2022-09-08 08:46:06 -06001737 match = re.search(r"BIOS version:\s*(?P<version>.*)", cmd_output)
1738 if match:
1739 main = match.group("version")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001740
Alex Klein1699fab2022-09-08 08:46:06 -06001741 match = re.search(r"BIOS \(RW\) version:\s*(?P<version>.*)", cmd_output)
1742 if match:
1743 main_rw = match.group("version")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001744
Alex Klein1699fab2022-09-08 08:46:06 -06001745 match = re.search(r"EC version:\s*(?P<version>.*)", cmd_output)
1746 if match:
1747 ec = match.group("version")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001748
Alex Klein1699fab2022-09-08 08:46:06 -06001749 match = re.search(r"EC \(RW\) version:\s*(?P<version>.*)", cmd_output)
1750 if match:
1751 ec_rw = match.group("version")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001752
Alex Klein1699fab2022-09-08 08:46:06 -06001753 match = re.search(r"Model:\s*(?P<model>.*)", cmd_output)
1754 if match:
1755 model = match.group("model")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001756
Alex Klein1699fab2022-09-08 08:46:06 -06001757 return FirmwareVersions(model, main, main_rw, ec, ec_rw)
Michael Mortensena4af79e2020-05-06 16:18:48 -06001758
1759
Benjamin Shai0858cd32022-01-10 20:23:49 +00001760class MainEcFirmwareVersions(NamedTuple):
Alex Klein1699fab2022-09-08 08:46:06 -06001761 """Tuple to hold main and ec firmware versions, with truthiness."""
Benjamin Shai0858cd32022-01-10 20:23:49 +00001762
Alex Klein1699fab2022-09-08 08:46:06 -06001763 main_fw_version: Optional[str]
1764 ec_fw_version: Optional[str]
1765
1766 def __bool__(self):
1767 return bool(self.main_fw_version or self.ec_fw_version)
Benjamin Shai0858cd32022-01-10 20:23:49 +00001768
Michael Mortensena4af79e2020-05-06 16:18:48 -06001769
Alex Klein1699fab2022-09-08 08:46:06 -06001770def determine_firmware_versions(build_target: "build_target_lib.BuildTarget"):
1771 """Returns a namedtuple with main and ec firmware versions.
Michael Mortensena4af79e2020-05-06 16:18:48 -06001772
Alex Klein1699fab2022-09-08 08:46:06 -06001773 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001774 build_target: The build target.
Michael Mortensena4af79e2020-05-06 16:18:48 -06001775
Alex Klein1699fab2022-09-08 08:46:06 -06001776 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001777 MainEcFirmwareVersions namedtuple with results.
Alex Klein1699fab2022-09-08 08:46:06 -06001778 """
1779 fw_versions = get_firmware_versions(build_target)
1780 main_fw_version = fw_versions.main_rw or fw_versions.main
1781 ec_fw_version = fw_versions.ec_rw or fw_versions.ec
Michael Mortensena4af79e2020-05-06 16:18:48 -06001782
Alex Klein1699fab2022-09-08 08:46:06 -06001783 return MainEcFirmwareVersions(main_fw_version, ec_fw_version)
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001784
Benjamin Shai0858cd32022-01-10 20:23:49 +00001785
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001786def determine_kernel_version(
Alex Klein1699fab2022-09-08 08:46:06 -06001787 build_target: "build_target_lib.BuildTarget",
Lizzy Presland0b978e62022-09-09 16:55:29 +00001788) -> str:
Alex Klein1699fab2022-09-08 08:46:06 -06001789 """Returns a string containing the kernel version for this build target.
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001790
Alex Klein1699fab2022-09-08 08:46:06 -06001791 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001792 build_target: The build target.
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001793
Alex Klein1699fab2022-09-08 08:46:06 -06001794 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001795 The kernel versions, or empty string.
Alex Klein1699fab2022-09-08 08:46:06 -06001796 """
Lizzy Presland0b978e62022-09-09 16:55:29 +00001797 target_virtual_pkg = "virtual/linux-sources"
Alex Klein1699fab2022-09-08 08:46:06 -06001798 try:
Lizzy Presland0b978e62022-09-09 16:55:29 +00001799 candidate_packages = portage_util.GetFlattenedDepsForPackage(
1800 target_virtual_pkg,
1801 sysroot=build_target.root,
1802 board=build_target.name,
1803 depth=1,
1804 )
1805 installed_packages = portage_util.GetPackageDependencies(
1806 target_virtual_pkg, board=build_target.name
Alex Klein1699fab2022-09-08 08:46:06 -06001807 )
1808 except cros_build_lib.RunCommandError as e:
1809 logging.warning("Unable to get package list for metadata: %s", e)
Lizzy Presland0b978e62022-09-09 16:55:29 +00001810 return ""
1811 if not candidate_packages:
1812 raise KernelVersionError("No package found in FlattenedDepsForPackage")
1813 if not installed_packages:
1814 raise KernelVersionError("No package found in GetPackageDependencies")
1815 packages = [
1816 p
1817 for p in installed_packages
1818 if p in candidate_packages and target_virtual_pkg not in p
1819 ]
1820 if len(packages) == 0:
1821 raise KernelVersionError(
1822 "No matches for installed packages were found in candidate "
1823 "packages. Did GetFlattenedDepsForPackage search all possible "
1824 "package versions?\tInstalled: %s\tCandidates: %s"
1825 % (" ".join(installed_packages), " ".join(candidate_packages))
1826 )
1827 if len(packages) > 1:
1828 raise KernelVersionError(
1829 "Too many packages found in intersection of installed packages and "
1830 "possible kernel versions (%s)" % "".join(packages)
1831 )
1832 kernel_version = package_info.SplitCPV(packages[0]).version
1833 logging.info("Found active kernel version: %s", kernel_version)
1834 return kernel_version
Michael Mortensen125bb012020-05-21 14:02:10 -06001835
1836
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001837def get_models(
Alex Klein1699fab2022-09-08 08:46:06 -06001838 build_target: "build_target_lib.BuildTarget", log_output: bool = True
1839) -> Optional[List[str]]:
1840 """Obtain a list of models supported by a unified board.
Michael Mortensen125bb012020-05-21 14:02:10 -06001841
Alex Klein1699fab2022-09-08 08:46:06 -06001842 This ignored whitelabel models since GoldenEye has no specific support for
1843 these at present.
Michael Mortensen125bb012020-05-21 14:02:10 -06001844
Alex Klein1699fab2022-09-08 08:46:06 -06001845 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001846 build_target: The build target.
1847 log_output: Whether to log the output of the cros_config_host
1848 invocation.
Michael Mortensen125bb012020-05-21 14:02:10 -06001849
Alex Klein1699fab2022-09-08 08:46:06 -06001850 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001851 A list of models supported by this board, if it is a unified build;
1852 None, if it is not a unified build.
Alex Klein1699fab2022-09-08 08:46:06 -06001853 """
1854 return _run_cros_config_host(
1855 build_target, ["list-models"], log_output=log_output
1856 )
Michael Mortensen125bb012020-05-21 14:02:10 -06001857
1858
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001859def get_key_id(
Alex Klein1699fab2022-09-08 08:46:06 -06001860 build_target: "build_target_lib.BuildTarget", model: str
1861) -> Optional[str]:
1862 """Obtain the key_id for a model within the build_target.
Michael Mortensen359c1f32020-05-28 19:35:42 -06001863
Alex Klein1699fab2022-09-08 08:46:06 -06001864 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001865 build_target: The build target.
1866 model: The model name
Michael Mortensen359c1f32020-05-28 19:35:42 -06001867
Alex Klein1699fab2022-09-08 08:46:06 -06001868 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001869 A key_id or None.
Alex Klein1699fab2022-09-08 08:46:06 -06001870 """
1871 model_arg = "--model=" + model
1872 key_id_list = _run_cros_config_host(
1873 build_target, [model_arg, "get", "/firmware-signing", "key-id"]
1874 )
1875 key_id = None
1876 if len(key_id_list) == 1:
1877 key_id = key_id_list[0]
1878 return key_id
Michael Mortensen359c1f32020-05-28 19:35:42 -06001879
1880
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001881def _run_cros_config_host(
Alex Klein1699fab2022-09-08 08:46:06 -06001882 build_target: "build_target_lib.BuildTarget",
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001883 args: List[str],
Alex Klein1699fab2022-09-08 08:46:06 -06001884 log_output: bool = True,
1885) -> Optional[List[str]]:
1886 """Run the cros_config_host tool.
Michael Mortensen125bb012020-05-21 14:02:10 -06001887
Alex Klein1699fab2022-09-08 08:46:06 -06001888 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001889 build_target: The build target.
1890 args: List of arguments to pass.
1891 log_output: Whether to log the output of the cros_config_host.
Michael Mortensen125bb012020-05-21 14:02:10 -06001892
Alex Klein1699fab2022-09-08 08:46:06 -06001893 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001894 Output of the tool
Alex Klein1699fab2022-09-08 08:46:06 -06001895 """
1896 cros_build_lib.AssertInsideChroot()
1897 tool = "/usr/bin/cros_config_host"
1898 if not os.path.isfile(tool):
1899 return None
Michael Mortensen125bb012020-05-21 14:02:10 -06001900
Alex Klein1699fab2022-09-08 08:46:06 -06001901 config_fname = build_target.full_path(
1902 "usr/share/chromeos-config/yaml/config.yaml"
1903 )
Michael Mortensen125bb012020-05-21 14:02:10 -06001904
Alex Klein1699fab2022-09-08 08:46:06 -06001905 result = cros_build_lib.run(
1906 [tool, "-c", config_fname] + args,
1907 capture_output=True,
1908 encoding="utf-8",
1909 log_output=log_output,
1910 check=False,
1911 )
1912 if result.returncode:
1913 # Show the output for debugging purposes.
1914 if "No such file or directory" not in result.stderr:
1915 logging.error("cros_config_host failed: %s\n", result.stderr)
1916 return None
1917 return result.stdout.strip().splitlines()