blob: 6061b6d72f8ed77ebe96c49926d4526a8b815b67 [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
Alex Kleinfee86da2023-01-20 18:40:06 -0700212 # output is included (e.g. messages from bashrc scripts that run upon
213 # entering the chroot.)
Alex Klein1699fab2022-09-08 08:46:06 -0600214 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 Kleinfee86da2023-01-20 18:40:06 -0700256 PUpr for Android does not test the uprev change in CQ; instead we run
257 separate jobs to test new Android versions, and we write the latest vetted
258 version to 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
Alex Kleinfee86da2023-01-20 18:40:06 -0700283 # cros_mark_android_as_stable returns paths relative to
284 # |android.OVERLAY_DIR|.
Alex Klein1699fab2022-09-08 08:46:06 -0600285 result.add_result(
286 android_version,
287 [
288 os.path.join(android.OVERLAY_DIR, f)
289 for f in uprev_result.modified_files
290 ],
291 )
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900292 return result
293
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900294
295def define_uprev_android_lkgb_handlers():
Alex Klein1699fab2022-09-08 08:46:06 -0600296 """Dynamically define uprev handlers for each Android package"""
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900297
Alex Klein1699fab2022-09-08 08:46:06 -0600298 def define_handler(android_package):
299 """Defines the uprev handler for an Android package."""
300 full_package_name = "chromeos-base/" + android_package
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900301
Alex Klein1699fab2022-09-08 08:46:06 -0600302 @uprevs_versioned_package(full_package_name)
303 def _handler(build_targets, _refs, chroot):
304 return uprev_android_lkgb(android_package, build_targets, chroot)
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900305
Shao-Chuan Leeca2cbcc2022-11-02 08:28:31 +0900306 for android_package in android.GetAllAndroidPackages():
Alex Klein1699fab2022-09-08 08:46:06 -0600307 define_handler(android_package)
Shao-Chuan Lee05e51142021-11-24 12:27:37 +0900308
309
310define_uprev_android_lkgb_handlers()
Alex Klein4de25e82019-08-05 15:58:39 -0600311
312
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700313def uprev_build_targets(
Alex Klein1699fab2022-09-08 08:46:06 -0600314 build_targets: Optional[List["build_target_lib.BuildTarget"]],
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700315 overlay_type: str,
Alex Klein1699fab2022-09-08 08:46:06 -0600316 chroot: "chroot_lib.Chroot" = None,
317 output_dir: Optional[str] = None,
318):
319 """Uprev the set provided build targets, or all if not specified.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600320
Alex Klein1699fab2022-09-08 08:46:06 -0600321 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600322 build_targets: The build targets whose overlays should be uprevved,
323 empty or None for all.
324 overlay_type: One of the valid overlay types except None (see
325 constants.VALID_OVERLAYS).
326 chroot: The chroot to clean, if desired.
327 output_dir: The path to optionally dump result files.
Alex Klein1699fab2022-09-08 08:46:06 -0600328 """
329 # Need a valid overlay, but exclude None.
330 assert overlay_type and overlay_type in constants.VALID_OVERLAYS
Alex Kleineb77ffa2019-05-28 14:47:44 -0600331
Alex Klein1699fab2022-09-08 08:46:06 -0600332 if build_targets:
333 overlays = portage_util.FindOverlaysForBoards(
334 overlay_type, boards=[t.name for t in build_targets]
335 )
336 else:
337 overlays = portage_util.FindOverlays(overlay_type)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600338
Alex Klein1699fab2022-09-08 08:46:06 -0600339 return uprev_overlays(
340 overlays,
341 build_targets=build_targets,
342 chroot=chroot,
343 output_dir=output_dir,
344 )
Alex Kleineb77ffa2019-05-28 14:47:44 -0600345
346
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700347def uprev_overlays(
348 overlays: List[str],
Alex Klein1699fab2022-09-08 08:46:06 -0600349 build_targets: Optional[List["build_target_lib.BuildTarget"]] = None,
350 chroot: Optional["chroot_lib.Chroot"] = None,
351 output_dir: Optional[str] = None,
352) -> List[str]:
353 """Uprev the given overlays.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600354
Alex Klein1699fab2022-09-08 08:46:06 -0600355 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600356 overlays: The list of overlay paths.
357 build_targets: The build targets to clean in |chroot|, if desired. No
358 effect unless |chroot| is provided.
359 chroot: The chroot to clean, if desired.
360 output_dir: The path to optionally dump result files.
Alex Kleineb77ffa2019-05-28 14:47:44 -0600361
Alex Klein1699fab2022-09-08 08:46:06 -0600362 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600363 The paths to all the modified ebuild files. This includes the new files
364 that were added (i.e. the new versions) and all the removed files
Alex Klein1699fab2022-09-08 08:46:06 -0600365 (i.e. the old versions).
366 """
367 assert overlays
Alex Kleineb77ffa2019-05-28 14:47:44 -0600368
Alex Klein1699fab2022-09-08 08:46:06 -0600369 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600370
Alex Klein1699fab2022-09-08 08:46:06 -0600371 uprev_manager = uprev_lib.UprevOverlayManager(
372 overlays,
373 manifest,
374 build_targets=build_targets,
375 chroot=chroot,
376 output_dir=output_dir,
377 )
378 uprev_manager.uprev()
Alex Kleineb77ffa2019-05-28 14:47:44 -0600379
Alex Klein1699fab2022-09-08 08:46:06 -0600380 return uprev_manager.modified_ebuilds, uprev_manager.revved_packages
Alex Kleineb77ffa2019-05-28 14:47:44 -0600381
382
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700383def uprev_versioned_package(
384 package: package_info.CPV,
Alex Klein1699fab2022-09-08 08:46:06 -0600385 build_targets: List["build_target_lib.BuildTarget"],
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700386 refs: List[uprev_lib.GitRef],
Alex Klein1699fab2022-09-08 08:46:06 -0600387 chroot: "chroot_lib.Chroot",
388) -> "uprev_lib.UprevVersionedPackageResult":
389 """Call registered uprev handler function for the package.
Alex Klein87531182019-08-12 15:23:37 -0600390
Alex Klein1699fab2022-09-08 08:46:06 -0600391 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600392 package: The package being uprevved.
393 build_targets: The build targets to clean on a successful uprev.
394 refs:
395 chroot: The chroot to enter for cleaning.
Alex Klein87531182019-08-12 15:23:37 -0600396
Alex Klein1699fab2022-09-08 08:46:06 -0600397 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600398 The result.
Alex Klein1699fab2022-09-08 08:46:06 -0600399 """
400 assert package
Alex Klein87531182019-08-12 15:23:37 -0600401
Alex Klein1699fab2022-09-08 08:46:06 -0600402 if package.cp not in _UPREV_FUNCS:
403 raise UnknownPackageError(
404 'Package "%s" does not have a registered handler.' % package.cp
405 )
Alex Klein87531182019-08-12 15:23:37 -0600406
Alex Klein1699fab2022-09-08 08:46:06 -0600407 return _UPREV_FUNCS[package.cp](build_targets, refs, chroot)
Alex Klein87531182019-08-12 15:23:37 -0600408
409
Alex Klein1699fab2022-09-08 08:46:06 -0600410@uprevs_versioned_package("media-libs/virglrenderer")
Navil Perezf57ba872020-06-04 22:38:37 +0000411def uprev_virglrenderer(_build_targets, refs, _chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600412 """Updates virglrenderer ebuilds.
Navil Perezf57ba872020-06-04 22:38:37 +0000413
Alex Klein1699fab2022-09-08 08:46:06 -0600414 See: uprev_versioned_package.
Navil Perezf57ba872020-06-04 22:38:37 +0000415
Alex Klein1699fab2022-09-08 08:46:06 -0600416 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600417 UprevVersionedPackageResult: The result of updating virglrenderer
418 ebuilds.
Alex Klein1699fab2022-09-08 08:46:06 -0600419 """
420 overlay = os.path.join(
421 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
422 )
423 repo_path = os.path.join(
424 constants.SOURCE_ROOT, "src", "third_party", "virglrenderer"
425 )
426 manifest = git.ManifestCheckout.Cached(repo_path)
Navil Perezf57ba872020-06-04 22:38:37 +0000427
Alex Klein1699fab2022-09-08 08:46:06 -0600428 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
429 # TODO(crbug.com/1066242): Ebuilds for virglrenderer are currently
430 # denylisted. Do not force uprevs after builder is stable and ebuilds are no
431 # longer denylisted.
432 uprev_manager.uprev(package_list=["media-libs/virglrenderer"], force=True)
Navil Perezf57ba872020-06-04 22:38:37 +0000433
Alex Klein1699fab2022-09-08 08:46:06 -0600434 updated_files = uprev_manager.modified_ebuilds
435 result = uprev_lib.UprevVersionedPackageResult()
436 result.add_result(refs[-1].revision, updated_files)
437 return result
Navil Perezf57ba872020-06-04 22:38:37 +0000438
Alex Klein1699fab2022-09-08 08:46:06 -0600439
Matthew Lam59ca37d2022-10-24 18:11:06 +0000440@uprevs_versioned_package("x11-apps/igt-gpu-tools")
441def uprev_igt_gpu_tools(_build_targets, refs, _chroot):
442 """Updates igt-gpu-tools ebuilds.
443
444 See: uprev_versioned_package.
445
446 Returns:
Alex Kleinfee86da2023-01-20 18:40:06 -0700447 UprevVersionedPackageResult: The result of updating igt-gpu-tools
448 ebuilds.
Matthew Lam59ca37d2022-10-24 18:11:06 +0000449 """
450 overlay = os.path.join(
451 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
452 )
453 repo_path = os.path.join(
454 constants.SOURCE_ROOT, "src", "third_party", "igt-gpu-tools"
455 )
456 manifest = git.ManifestCheckout.Cached(repo_path)
457
458 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
459 uprev_manager.uprev(package_list=["x11-apps/igt-gpu-tools"], force=True)
460
461 updated_files = uprev_manager.modified_ebuilds
462 result = uprev_lib.UprevVersionedPackageResult()
463 result.add_result(refs[-1].revision, updated_files)
464 return result
465
466
Alex Klein1699fab2022-09-08 08:46:06 -0600467@uprevs_versioned_package("chromeos-base/drivefs")
Jose Magana03b5a842020-08-19 12:52:59 +1000468def uprev_drivefs(_build_targets, refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600469 """Updates drivefs ebuilds.
Jose Magana03b5a842020-08-19 12:52:59 +1000470
Alex Klein1699fab2022-09-08 08:46:06 -0600471 DriveFS versions follow the tag format of refs/tags/drivefs_1.2.3.
472 See: uprev_versioned_package.
Jose Magana03b5a842020-08-19 12:52:59 +1000473
Alex Klein1699fab2022-09-08 08:46:06 -0600474 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600475 UprevVersionedPackageResult: The result of updating drivefs ebuilds.
Alex Klein1699fab2022-09-08 08:46:06 -0600476 """
Jose Magana03b5a842020-08-19 12:52:59 +1000477
Alex Klein1699fab2022-09-08 08:46:06 -0600478 DRIVEFS_PATH_PREFIX = "src/private-overlays/chromeos-overlay/chromeos-base"
479 result = uprev_lib.UprevVersionedPackageResult()
480 all_changed_files = []
Jose Magana03b5a842020-08-19 12:52:59 +1000481
Alex Klein1699fab2022-09-08 08:46:06 -0600482 DRIVEFS_REFS_PREFIX = "refs/tags/drivefs_"
483 drivefs_version = _get_latest_version_from_refs(DRIVEFS_REFS_PREFIX, refs)
484 if not drivefs_version:
485 # No valid DriveFS version is identified.
486 return result
487
488 logging.debug("DriveFS version determined from refs: %s", drivefs_version)
489
490 # Attempt to uprev drivefs package.
491 pkg_path = os.path.join(DRIVEFS_PATH_PREFIX, "drivefs")
492 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
493 pkg_path, drivefs_version, chroot, allow_downrev=False
494 )
495
496 if not uprev_result:
497 return result
498 all_changed_files.extend(uprev_result.changed_files)
499 result.add_result(drivefs_version, all_changed_files)
500
Ben Reich4f3fa1b2020-12-19 08:21:26 +0000501 return result
Jose Magana03b5a842020-08-19 12:52:59 +1000502
Jose Magana03b5a842020-08-19 12:52:59 +1000503
Alex Klein1699fab2022-09-08 08:46:06 -0600504@uprevs_versioned_package("chromeos-base/perfetto")
Chinglin Yufa728552023-04-13 03:12:04 +0000505@uprevs_versioned_package("dev-go/perfetto-protos")
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800506def uprev_perfetto(_build_targets, refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600507 """Updates Perfetto ebuilds.
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800508
Alex Klein1699fab2022-09-08 08:46:06 -0600509 Perfetto versions follow the tag format of refs/tags/v1.2.
510 See: uprev_versioned_package.
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800511
Alex Klein1699fab2022-09-08 08:46:06 -0600512 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600513 UprevVersionedPackageResult: The result of updating Perfetto ebuilds.
Alex Klein1699fab2022-09-08 08:46:06 -0600514 """
515 result = uprev_lib.UprevVersionedPackageResult()
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800516
Alex Klein1699fab2022-09-08 08:46:06 -0600517 PERFETTO_REFS_PREFIX = "refs/tags/v"
Chinglin Yufa728552023-04-13 03:12:04 +0000518
519 perfetto_ebuilds = ["chromeos-base/perfetto", "dev-go/perfetto-protos"]
520 perfetto_paths = [
521 os.path.join(constants.CHROMIUMOS_OVERLAY_DIR, e)
522 for e in perfetto_ebuilds
523 ]
524 # chromeos-base/perfetto is the primary ebuild.
525 primary_ebuild_path = perfetto_paths[0]
Chinglin Yuad12a512022-10-07 17:26:12 +0800526
527 # Decide the version number to uprev to:
528 # * If |refs| contains refs/tags/v*, get the latest from them.
Alex Klein1699fab2022-09-08 08:46:06 -0600529 perfetto_version = _get_latest_version_from_refs(PERFETTO_REFS_PREFIX, refs)
Chinglin Yuad12a512022-10-07 17:26:12 +0800530 # * Or if |refs| contains only the latest trunk revisions, use the current
531 # stable ebuild version for a revision bump.
532 if refs and not perfetto_version:
Chinglin Yufa728552023-04-13 03:12:04 +0000533 perfetto_version = uprev_lib.get_stable_ebuild_version(
534 primary_ebuild_path
535 )
Chinglin Yuad12a512022-10-07 17:26:12 +0800536
Alex Klein1699fab2022-09-08 08:46:06 -0600537 if not perfetto_version:
538 # No valid Perfetto version is identified.
539 return result
540
Chinglin Yufa728552023-04-13 03:12:04 +0000541 for path in perfetto_paths:
542 # Attempt to uprev perfetto package.
543 # |perfetto_version| is only used in determining the ebuild version. The
544 # package is always updated to the latest HEAD.
545 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
546 path,
547 perfetto_version,
548 chroot,
549 allow_downrev=False,
550 # Use default ref="HEAD"
551 )
Alex Klein1699fab2022-09-08 08:46:06 -0600552
Chinglin Yufa728552023-04-13 03:12:04 +0000553 if not uprev_result:
554 return result
Alex Klein1699fab2022-09-08 08:46:06 -0600555
Chinglin Yufa728552023-04-13 03:12:04 +0000556 # Include short git sha hash in the uprev commit message.
557 # Use 9 digits to match the short hash length in `perfetto --version`.
558 short_revision = refs[-1].revision[0:9]
559 version_and_rev = f"{perfetto_version}-{short_revision}"
560 result.add_result(version_and_rev, uprev_result.changed_files)
Alex Klein1699fab2022-09-08 08:46:06 -0600561
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800562 return result
563
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800564
Denis Nikitin63613e32022-09-09 22:26:50 -0700565class AfdoMetadata(NamedTuple):
566 """Data class holding AFDO metadata."""
567
568 var_name: str
569 path: str
570
571
Alex Klein1699fab2022-09-08 08:46:06 -0600572@uprevs_versioned_package("afdo/kernel-profiles")
Yaakov Shaul395ae832019-09-09 14:45:32 -0600573def uprev_kernel_afdo(*_args, **_kwargs):
Alex Klein1699fab2022-09-08 08:46:06 -0600574 """Updates kernel ebuilds with versions from kernel_afdo.json.
Yaakov Shaul395ae832019-09-09 14:45:32 -0600575
Alex Klein1699fab2022-09-08 08:46:06 -0600576 See: uprev_versioned_package.
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600577
Alex Klein1699fab2022-09-08 08:46:06 -0600578 Raises:
Alex Klein348e7692022-10-13 17:03:37 -0600579 EbuildManifestError: When ebuild manifest does not complete
580 successfully.
581 JSONDecodeError: When json is malformed.
Alex Klein1699fab2022-09-08 08:46:06 -0600582 """
Denis Nikitin63613e32022-09-09 22:26:50 -0700583 metadata_dir = os.path.join(
Alex Klein1699fab2022-09-08 08:46:06 -0600584 constants.SOURCE_ROOT,
585 "src",
586 "third_party",
587 "toolchain-utils",
588 "afdo_metadata",
Denis Nikitin63613e32022-09-09 22:26:50 -0700589 )
590 metadata_files = (
591 AfdoMetadata(
592 var_name="AFDO_PROFILE_VERSION",
593 path=os.path.join(metadata_dir, "kernel_afdo.json"),
594 ),
595 AfdoMetadata(
596 var_name="ARM_AFDO_PROFILE_VERSION",
597 path=os.path.join(metadata_dir, "kernel_arm_afdo.json"),
598 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600599 )
Yaakov Shaul395ae832019-09-09 14:45:32 -0600600
Alex Klein1699fab2022-09-08 08:46:06 -0600601 result = uprev_lib.UprevVersionedPackageResult()
Denis Nikitin63613e32022-09-09 22:26:50 -0700602 for metadata in metadata_files:
Mike Frysinger81a98062023-02-24 15:42:04 -0500603 with open(metadata.path, "r", encoding="utf-8") as f:
Denis Nikitin63613e32022-09-09 22:26:50 -0700604 versions = json.load(f)
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600605
Denis Nikitin63613e32022-09-09 22:26:50 -0700606 for kernel_pkg, version_info in versions.items():
607 path = os.path.join(
608 constants.CHROMIUMOS_OVERLAY_DIR, "sys-kernel", kernel_pkg
609 )
610 ebuild_path = os.path.join(
611 constants.SOURCE_ROOT, path, f"{kernel_pkg}-9999.ebuild"
612 )
613 chroot_ebuild_path = os.path.join(
614 constants.CHROOT_SOURCE_ROOT, path, f"{kernel_pkg}-9999.ebuild"
615 )
616 afdo_profile_version = version_info["name"]
617 patch_ebuild_vars(
618 ebuild_path, {metadata.var_name: afdo_profile_version}
Alex Klein1699fab2022-09-08 08:46:06 -0600619 )
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600620
Denis Nikitin63613e32022-09-09 22:26:50 -0700621 try:
622 cmd = ["ebuild", chroot_ebuild_path, "manifest", "--force"]
623 cros_build_lib.run(cmd, enter_chroot=True)
624 except cros_build_lib.RunCommandError as e:
625 raise uprev_lib.EbuildManifestError(
626 "Error encountered when regenerating the manifest for "
627 f"ebuild: {chroot_ebuild_path}\n{e}",
628 e,
629 )
Yaakov Shaul1eafe832019-09-10 16:50:26 -0600630
Denis Nikitin63613e32022-09-09 22:26:50 -0700631 manifest_path = os.path.join(
632 constants.SOURCE_ROOT, path, "Manifest"
633 )
634 result.add_result(
635 afdo_profile_version, [ebuild_path, manifest_path]
636 )
Yaakov Shaul730814a2019-09-10 13:58:25 -0600637
Alex Klein1699fab2022-09-08 08:46:06 -0600638 return result
Yaakov Shaul395ae832019-09-09 14:45:32 -0600639
640
Alex Klein1699fab2022-09-08 08:46:06 -0600641@uprevs_versioned_package("chromeos-base/termina-dlc")
642@uprevs_versioned_package("chromeos-base/termina-tools-dlc")
Maciek Swiech6b12f662022-01-25 16:51:19 +0000643def uprev_termina_dlcs(_build_targets, _refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600644 """Updates shared termina-dlc and termina-tools-dlc ebuilds.
Maciek Swiech6b12f662022-01-25 16:51:19 +0000645
Alex Klein1699fab2022-09-08 08:46:06 -0600646 termina-dlc - chromeos-base/termina-dlc
647 termina-tools-dlc - chromeos-base/termina-tools-dlc
Trent Beginaf51f1b2020-03-09 17:35:31 -0600648
Alex Klein1699fab2022-09-08 08:46:06 -0600649 See: uprev_versioned_package.
650 """
651 termina_dlc_pkg = "termina-dlc"
652 termina_dlc_pkg_path = os.path.join(
653 constants.CHROMIUMOS_OVERLAY_DIR, "chromeos-base", termina_dlc_pkg
654 )
655 tools_dlc_pkg = "termina-tools-dlc"
656 tools_dlc_pkg_path = os.path.join(
657 constants.CHROMIUMOS_OVERLAY_DIR, "chromeos-base", tools_dlc_pkg
658 )
Patrick Meiring5897add2020-09-16 16:30:17 +1000659
Alex Klein1699fab2022-09-08 08:46:06 -0600660 # termina-dlc and termina-tools-dlc are pinned to the same version.
661 version_pin_src_path = _get_version_pin_src_path(termina_dlc_pkg_path)
662 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
Patrick Meiring5897add2020-09-16 16:30:17 +1000663
Alex Klein1699fab2022-09-08 08:46:06 -0600664 result = uprev_lib.uprev_ebuild_from_pin(
665 termina_dlc_pkg_path, version_no_rev, chroot
666 )
667 result += uprev_lib.uprev_ebuild_from_pin(
668 tools_dlc_pkg_path, version_no_rev, chroot
669 )
Patrick Meiring5897add2020-09-16 16:30:17 +1000670
Alex Klein1699fab2022-09-08 08:46:06 -0600671 return result
Patrick Meiring5897add2020-09-16 16:30:17 +1000672
Alex Klein1699fab2022-09-08 08:46:06 -0600673
674@uprevs_versioned_package("chromeos-base/chromeos-lacros")
Julio Hurtadof1befec2021-05-05 21:34:26 +0000675def uprev_lacros(_build_targets, refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600676 """Updates lacros ebuilds.
Julio Hurtadof1befec2021-05-05 21:34:26 +0000677
Alex Klein1699fab2022-09-08 08:46:06 -0600678 Version to uprev to is gathered from the QA qualified version tracking file
Alex Kleinfee86da2023-01-20 18:40:06 -0700679 stored in chromium/src/chrome/LACROS_QA_QUALIFIED_VERSION. Uprev is
680 triggered on modification of this file across all chromium/src branches.
Julio Hurtadof1befec2021-05-05 21:34:26 +0000681
Alex Klein1699fab2022-09-08 08:46:06 -0600682 See: uprev_versioned_package.
683 """
684 result = uprev_lib.UprevVersionedPackageResult()
685 path = os.path.join(
686 constants.CHROMIUMOS_OVERLAY_DIR, "chromeos-base", "chromeos-lacros"
687 )
688 lacros_version = refs[0].revision
689 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
690 path, lacros_version, chroot, allow_downrev=False
691 )
Julio Hurtadoa994e002021-07-07 17:57:45 +0000692
Alex Klein1699fab2022-09-08 08:46:06 -0600693 if not uprev_result:
694 return result
695
696 result.add_result(lacros_version, uprev_result.changed_files)
Julio Hurtadoa994e002021-07-07 17:57:45 +0000697 return result
698
Julio Hurtadof1befec2021-05-05 21:34:26 +0000699
Alex Klein1699fab2022-09-08 08:46:06 -0600700@uprevs_versioned_package("chromeos-base/chromeos-lacros-parallel")
Julio Hurtado870ed322021-12-03 18:22:40 +0000701def uprev_lacros_in_parallel(
Alex Klein1699fab2022-09-08 08:46:06 -0600702 _build_targets: Optional[List["build_target_lib.BuildTarget"]],
Julio Hurtado870ed322021-12-03 18:22:40 +0000703 refs: List[uprev_lib.GitRef],
Alex Klein1699fab2022-09-08 08:46:06 -0600704 chroot: "chroot_lib.Chroot",
705) -> "uprev_lib.UprevVersionedPackageResult":
706 """Updates lacros ebuilds in parallel with ash-chrome.
Julio Hurtado870ed322021-12-03 18:22:40 +0000707
Alex Kleinfee86da2023-01-20 18:40:06 -0700708 This handler is going to be used temporarily while lacros transitions to
709 being uprevved atomically with ash-chrome. Unlike a standalone lacros uprev,
710 this handler will not need to look at the QA qualified file. Rather, it will
Alex Klein1699fab2022-09-08 08:46:06 -0600711 function identical to ash-chrome using git tags.
Julio Hurtado870ed322021-12-03 18:22:40 +0000712
Alex Klein1699fab2022-09-08 08:46:06 -0600713 See: uprev_versioned_package.
Julio Hurtado870ed322021-12-03 18:22:40 +0000714
Alex Klein1699fab2022-09-08 08:46:06 -0600715 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600716 UprevVersionedPackageResult: The result.
Alex Klein1699fab2022-09-08 08:46:06 -0600717 """
718 result = uprev_lib.UprevVersionedPackageResult()
719 path = os.path.join(
720 constants.CHROMIUMOS_OVERLAY_DIR, "chromeos-base", "chromeos-lacros"
721 )
722 lacros_version = uprev_lib.get_version_from_refs(refs)
723 uprev_result = uprev_lib.uprev_workon_ebuild_to_version(
724 path, lacros_version, chroot, allow_downrev=False
725 )
Julio Hurtado870ed322021-12-03 18:22:40 +0000726
Alex Klein1699fab2022-09-08 08:46:06 -0600727 if not uprev_result:
728 return result
729
730 result.add_result(lacros_version, uprev_result.changed_files)
Julio Hurtado870ed322021-12-03 18:22:40 +0000731 return result
732
Julio Hurtado870ed322021-12-03 18:22:40 +0000733
Alex Klein1699fab2022-09-08 08:46:06 -0600734@uprevs_versioned_package("app-emulation/parallels-desktop")
Patrick Meiring5897add2020-09-16 16:30:17 +1000735def uprev_parallels_desktop(_build_targets, _refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600736 """Updates Parallels Desktop ebuild - app-emulation/parallels-desktop.
Patrick Meiring5897add2020-09-16 16:30:17 +1000737
Alex Klein1699fab2022-09-08 08:46:06 -0600738 See: uprev_versioned_package
Patrick Meiring5897add2020-09-16 16:30:17 +1000739
Alex Klein1699fab2022-09-08 08:46:06 -0600740 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600741 UprevVersionedPackageResult: The result.
Alex Klein1699fab2022-09-08 08:46:06 -0600742 """
743 package = "parallels-desktop"
744 package_path = os.path.join(
745 constants.CHROMEOS_PARTNER_OVERLAY_DIR, "app-emulation", package
746 )
747 version_pin_src_path = _get_version_pin_src_path(package_path)
Patrick Meiring5897add2020-09-16 16:30:17 +1000748
Alex Klein1699fab2022-09-08 08:46:06 -0600749 # Expect a JSON blob like the following:
750 # {
751 # "version": "1.2.3",
752 # "test_image": { "url": "...", "size": 12345678,
753 # "sha256sum": "<32 bytes of hexadecimal>" }
754 # }
Mike Frysinger81a98062023-02-24 15:42:04 -0500755 with open(version_pin_src_path, "r", encoding="utf-8") as f:
Alex Klein1699fab2022-09-08 08:46:06 -0600756 pinned = json.load(f)
Patrick Meiring5897add2020-09-16 16:30:17 +1000757
Alex Klein1699fab2022-09-08 08:46:06 -0600758 if "version" not in pinned or "test_image" not in pinned:
759 raise UprevError(
760 "VERSION-PIN for %s missing version and/or "
761 "test_image field" % package
762 )
Patrick Meiring5897add2020-09-16 16:30:17 +1000763
Alex Klein1699fab2022-09-08 08:46:06 -0600764 version = pinned["version"]
765 if not isinstance(version, str):
766 raise UprevError("version in VERSION-PIN for %s not a string" % package)
Patrick Meiring5897add2020-09-16 16:30:17 +1000767
Alex Klein1699fab2022-09-08 08:46:06 -0600768 # Update the ebuild.
769 result = uprev_lib.uprev_ebuild_from_pin(package_path, version, chroot)
Patrick Meiring5897add2020-09-16 16:30:17 +1000770
Alex Klein1699fab2022-09-08 08:46:06 -0600771 # Update the VM image used for testing.
772 test_image_path = (
773 "src/platform/tast-tests-private/src/chromiumos/tast/"
774 "local/bundles/crosint/pita/data/"
775 "pluginvm_image.zip.external"
776 )
777 test_image_src_path = os.path.join(constants.SOURCE_ROOT, test_image_path)
Mike Frysinger81a98062023-02-24 15:42:04 -0500778 with open(test_image_src_path, "w", encoding="utf-8") as f:
Alex Klein1699fab2022-09-08 08:46:06 -0600779 json.dump(pinned["test_image"], f, indent=2)
780 result.add_result(version, [test_image_src_path])
Patrick Meiring5897add2020-09-16 16:30:17 +1000781
Alex Klein1699fab2022-09-08 08:46:06 -0600782 return result
Trent Beginaf51f1b2020-03-09 17:35:31 -0600783
784
Alex Klein1699fab2022-09-08 08:46:06 -0600785@uprevs_versioned_package("chromeos-base/chromeos-dtc-vm")
Trent Beginaf51f1b2020-03-09 17:35:31 -0600786def uprev_sludge(_build_targets, _refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600787 """Updates sludge VM - chromeos-base/chromeos-dtc-vm.
Trent Begin315d9d92019-12-03 21:55:53 -0700788
Alex Klein1699fab2022-09-08 08:46:06 -0600789 See: uprev_versioned_package.
790 """
791 package = "chromeos-dtc-vm"
792 package_path = os.path.join(
793 "src",
794 "private-overlays",
795 "project-wilco-private",
796 "chromeos-base",
797 package,
798 )
799 version_pin_src_path = _get_version_pin_src_path(package_path)
800 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
Trent Begin315d9d92019-12-03 21:55:53 -0700801
Alex Klein1699fab2022-09-08 08:46:06 -0600802 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
Trent Begin315d9d92019-12-03 21:55:53 -0700803
804
Alex Klein1699fab2022-09-08 08:46:06 -0600805@uprevs_versioned_package("chromeos-base/borealis-dlc")
David Riley8513c1f2021-10-14 17:07:41 -0700806def uprev_borealis_dlc(_build_targets, _refs, chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600807 """Updates shared borealis-dlc ebuild - chromeos-base/borealis-dlc.
David Riley8513c1f2021-10-14 17:07:41 -0700808
Alex Klein1699fab2022-09-08 08:46:06 -0600809 See: uprev_versioned_package.
810 """
811 package_path = os.path.join(
812 "src",
813 "private-overlays",
814 "chromeos-partner-overlay",
815 "chromeos-base",
816 "borealis-dlc",
817 )
David Riley8513c1f2021-10-14 17:07:41 -0700818
Alex Klein1699fab2022-09-08 08:46:06 -0600819 version_pin_src_path = _get_version_pin_src_path(package_path)
820 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
David Riley8513c1f2021-10-14 17:07:41 -0700821
Alex Klein1699fab2022-09-08 08:46:06 -0600822 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
David Riley8513c1f2021-10-14 17:07:41 -0700823
824
Po-Hsien Wang92fb1e52023-04-27 11:35:04 -0700825@uprevs_versioned_package("chromeos-base/borealis-dlc-nvidia")
826def uprev_borealis_dlc_nvidia(_build_targets, _refs, chroot):
827 """Updates shared borealis-dlc-nvidia ebuild - chromeos-base/borealis-dlc-nvidia.
828
829 See: uprev_versioned_package.
830 """
831 package_path = os.path.join(
832 "src",
833 "private-overlays",
834 "chromeos-partner-overlay",
835 "chromeos-base",
836 "borealis-dlc-nvidia",
837 )
838
839 version_pin_src_path = _get_version_pin_src_path(package_path)
840 version_no_rev = osutils.ReadFile(version_pin_src_path).strip()
841
842 return uprev_lib.uprev_ebuild_from_pin(package_path, version_no_rev, chroot)
843
844
Patrick Meiring5897add2020-09-16 16:30:17 +1000845def _get_version_pin_src_path(package_path):
Alex Klein1699fab2022-09-08 08:46:06 -0600846 """Returns the path to the VERSION-PIN file for the given package."""
847 return os.path.join(constants.SOURCE_ROOT, package_path, "VERSION-PIN")
Patrick Meiring5897add2020-09-16 16:30:17 +1000848
849
Alex Klein87531182019-08-12 15:23:37 -0600850@uprevs_versioned_package(constants.CHROME_CP)
Alex Klein4e839252022-01-06 13:29:18 -0700851def uprev_chrome_from_ref(build_targets, refs, _chroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600852 """Uprev chrome and its related packages.
Alex Klein87531182019-08-12 15:23:37 -0600853
Alex Klein1699fab2022-09-08 08:46:06 -0600854 See: uprev_versioned_package.
855 """
Alex Kleinfee86da2023-01-20 18:40:06 -0700856 # Determine the version from the refs (tags), i.e. the chrome versions are
857 # the tag names.
Alex Klein1699fab2022-09-08 08:46:06 -0600858 chrome_version = uprev_lib.get_version_from_refs(refs)
859 logging.debug("Chrome version determined from refs: %s", chrome_version)
Alex Klein87531182019-08-12 15:23:37 -0600860
Alex Klein1699fab2022-09-08 08:46:06 -0600861 return uprev_chrome(chrome_version, build_targets, None)
Alex Kleinf69bd802021-06-22 15:43:49 -0600862
863
Alex Klein9ce3f682021-06-23 15:06:44 -0600864def revbump_chrome(
Alex Klein1699fab2022-09-08 08:46:06 -0600865 build_targets: List["build_target_lib.BuildTarget"] = None,
866 chroot: Optional["chroot_lib.Chroot"] = None,
Alex Klein9ce3f682021-06-23 15:06:44 -0600867) -> uprev_lib.UprevVersionedPackageResult:
Alex Klein1699fab2022-09-08 08:46:06 -0600868 """Attempt to revbump chrome.
Alex Kleinf69bd802021-06-22 15:43:49 -0600869
Alex Klein1699fab2022-09-08 08:46:06 -0600870 Revbumps are done by executing an uprev using the current stable version.
871 E.g. if chrome is on 1.2.3.4 and has a 1.2.3.4_rc-r2.ebuild, performing an
872 uprev on version 1.2.3.4 when there are applicable changes (e.g. to the 9999
873 ebuild) will result in a revbump to 1.2.3.4_rc-r3.ebuild.
874 """
875 chrome_version = uprev_lib.get_stable_chrome_version()
876 return uprev_chrome(chrome_version, build_targets, chroot)
Alex Kleinf69bd802021-06-22 15:43:49 -0600877
878
Alex Klein9ce3f682021-06-23 15:06:44 -0600879def uprev_chrome(
Alex Klein16ea1b32021-10-01 15:48:50 -0600880 chrome_version: str,
Alex Klein1699fab2022-09-08 08:46:06 -0600881 build_targets: Optional[List["build_target_lib.BuildTarget"]],
882 chroot: Optional["chroot_lib.Chroot"],
Alex Klein9ce3f682021-06-23 15:06:44 -0600883) -> uprev_lib.UprevVersionedPackageResult:
Alex Klein1699fab2022-09-08 08:46:06 -0600884 """Attempt to uprev chrome and its related packages to the given version."""
885 uprev_manager = uprev_lib.UprevChromeManager(
886 chrome_version, build_targets=build_targets, chroot=chroot
887 )
888 result = uprev_lib.UprevVersionedPackageResult()
889 # TODO(crbug.com/1080429): Handle all possible outcomes of a Chrome uprev
890 # attempt. The expected behavior is documented in the following table:
891 #
892 # Outcome of Chrome uprev attempt:
893 # NEWER_VERSION_EXISTS:
894 # Do nothing.
895 # SAME_VERSION_EXISTS or REVISION_BUMP:
896 # Uprev followers
897 # Assert not VERSION_BUMP (any other outcome is fine)
898 # VERSION_BUMP or NEW_EBUILD_CREATED:
899 # Uprev followers
900 # Assert that Chrome & followers are at same package version
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600901
Alex Klein1699fab2022-09-08 08:46:06 -0600902 # Start with chrome itself so we can proceed accordingly.
903 chrome_result = uprev_manager.uprev(constants.CHROME_CP)
904 if chrome_result.newer_version_exists:
905 # Cannot use the given version (newer version already exists).
906 return result
907
908 # Also uprev related packages.
909 for package in constants.OTHER_CHROME_PACKAGES:
910 follower_result = uprev_manager.uprev(package)
911 if chrome_result.stable_version and follower_result.version_bump:
912 logging.warning(
913 "%s had a version bump, but no more than a revision bump "
914 "should have been possible.",
915 package,
916 )
917
918 if uprev_manager.modified_ebuilds:
919 # Record changes when we have them.
920 return result.add_result(chrome_version, uprev_manager.modified_ebuilds)
921
David Burger37f48672019-09-18 17:07:56 -0600922 return result
Alex Klein87531182019-08-12 15:23:37 -0600923
Alex Klein87531182019-08-12 15:23:37 -0600924
Alex Klein1699fab2022-09-08 08:46:06 -0600925def _get_latest_version_from_refs(
926 refs_prefix: str, refs: List[uprev_lib.GitRef]
927) -> str:
928 """Get the latest version from refs
Alex Klein0b2ec2d2021-06-23 15:56:45 -0600929
Alex Klein1699fab2022-09-08 08:46:06 -0600930 Versions are compared using |distutils.version.LooseVersion| and
931 the latest version is returned.
Alex Klein87531182019-08-12 15:23:37 -0600932
Alex Klein1699fab2022-09-08 08:46:06 -0600933 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600934 refs_prefix: The refs prefix of the tag format.
935 refs: The tags to parse for the latest version.
Alex Klein87531182019-08-12 15:23:37 -0600936
Alex Klein1699fab2022-09-08 08:46:06 -0600937 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600938 The latest version to use as string.
Alex Klein1699fab2022-09-08 08:46:06 -0600939 """
940 valid_refs = []
941 for gitiles in refs:
942 if gitiles.ref.startswith(refs_prefix):
943 valid_refs.append(gitiles.ref)
Ben Reiche779cf42020-12-15 03:21:31 +0000944
Alex Klein1699fab2022-09-08 08:46:06 -0600945 if not valid_refs:
946 return None
Ben Reiche779cf42020-12-15 03:21:31 +0000947
Alex Klein1699fab2022-09-08 08:46:06 -0600948 # Sort by version and take the latest version.
949 target_version_ref = sorted(valid_refs, key=LooseVersion, reverse=True)[0]
950 return target_version_ref.replace(refs_prefix, "")
Harvey Yang9c61e9c2021-03-02 16:32:43 +0800951
952
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -0700953def _generate_platform_c_files(
954 replication_config: replication_config_pb2.ReplicationConfig,
Alex Klein1699fab2022-09-08 08:46:06 -0600955 chroot: "chroot_lib.Chroot",
956) -> List[str]:
957 """Generates platform C files from a platform JSON payload.
Andrew Lamb9563a152019-12-04 11:42:18 -0700958
Alex Klein1699fab2022-09-08 08:46:06 -0600959 Args:
Alex Klein348e7692022-10-13 17:03:37 -0600960 replication_config: A ReplicationConfig that has already been run. If it
961 produced a build_config.json file, that file will be used to
962 generate platform C files. Otherwise, nothing will be generated.
963 chroot: The chroot to use to generate.
Andrew Lamb9563a152019-12-04 11:42:18 -0700964
Alex Klein1699fab2022-09-08 08:46:06 -0600965 Returns:
Alex Klein348e7692022-10-13 17:03:37 -0600966 A list of generated files.
Alex Klein1699fab2022-09-08 08:46:06 -0600967 """
968 # Generate the platform C files from the build config. Note that it would be
969 # more intuitive to generate the platform C files from the platform config;
Alex Kleinfee86da2023-01-20 18:40:06 -0700970 # however, cros_config_schema does not allow this, because the platform
971 # config payload is not always valid input. For example, if a property is
972 # both 'required' and 'build-only', it will fail schema validation. Thus,
973 # use the build config, and use '-f' to filter.
Alex Klein1699fab2022-09-08 08:46:06 -0600974 build_config_path = [
975 rule.destination_path
976 for rule in replication_config.file_replication_rules
977 if rule.destination_path.endswith("build_config.json")
978 ]
Andrew Lamb9563a152019-12-04 11:42:18 -0700979
Alex Klein1699fab2022-09-08 08:46:06 -0600980 if not build_config_path:
981 logging.info(
982 "No build_config.json found, will not generate platform C files. "
983 "Replication config: %s",
984 replication_config,
985 )
986 return []
Andrew Lamb9563a152019-12-04 11:42:18 -0700987
Alex Klein1699fab2022-09-08 08:46:06 -0600988 if len(build_config_path) > 1:
989 raise ValueError(
990 "Expected at most one build_config.json destination path. "
991 "Replication config: %s" % replication_config
992 )
Andrew Lamb9563a152019-12-04 11:42:18 -0700993
Alex Klein1699fab2022-09-08 08:46:06 -0600994 build_config_path = build_config_path[0]
Andrew Lamb9563a152019-12-04 11:42:18 -0700995
Alex Klein1699fab2022-09-08 08:46:06 -0600996 # Paths to the build_config.json and dir to output C files to, in the
997 # chroot.
998 build_config_chroot_path = os.path.join(
999 constants.CHROOT_SOURCE_ROOT, build_config_path
1000 )
1001 generated_output_chroot_dir = os.path.join(
1002 constants.CHROOT_SOURCE_ROOT, os.path.dirname(build_config_path)
1003 )
Andrew Lamb9563a152019-12-04 11:42:18 -07001004
Alex Klein1699fab2022-09-08 08:46:06 -06001005 command = [
1006 "cros_config_schema",
1007 "-m",
1008 build_config_chroot_path,
1009 "-g",
1010 generated_output_chroot_dir,
1011 "-f",
1012 '"TRUE"',
1013 ]
Andrew Lamb9563a152019-12-04 11:42:18 -07001014
Alex Klein1699fab2022-09-08 08:46:06 -06001015 cros_build_lib.run(
1016 command, enter_chroot=True, chroot_args=chroot.get_enter_args()
1017 )
Andrew Lamb9563a152019-12-04 11:42:18 -07001018
Alex Klein1699fab2022-09-08 08:46:06 -06001019 # A relative (to the source root) path to the generated C files.
1020 generated_output_dir = os.path.dirname(build_config_path)
1021 generated_files = []
1022 expected_c_files = ["config.c", "ec_config.c", "ec_config.h"]
1023 for f in expected_c_files:
1024 if os.path.exists(
1025 os.path.join(constants.SOURCE_ROOT, generated_output_dir, f)
1026 ):
1027 generated_files.append(os.path.join(generated_output_dir, f))
Andrew Lamb9563a152019-12-04 11:42:18 -07001028
Alex Klein1699fab2022-09-08 08:46:06 -06001029 if len(expected_c_files) != len(generated_files):
1030 raise GeneratedCrosConfigFilesError(expected_c_files, generated_files)
Andrew Lamb9563a152019-12-04 11:42:18 -07001031
Alex Klein1699fab2022-09-08 08:46:06 -06001032 return generated_files
Andrew Lamb9563a152019-12-04 11:42:18 -07001033
1034
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001035def _get_private_overlay_package_root(ref: uprev_lib.GitRef, package: str):
Alex Klein1699fab2022-09-08 08:46:06 -06001036 """Returns the absolute path to the root of a given private overlay.
Andrew Lambe836f222019-12-09 12:27:38 -07001037
Alex Klein1699fab2022-09-08 08:46:06 -06001038 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001039 ref: GitRef for the private overlay.
1040 package: Path to the package in the overlay.
Alex Klein1699fab2022-09-08 08:46:06 -06001041 """
1042 # There might be a cleaner way to map from package -> path within the source
1043 # tree. For now, just use string patterns.
1044 private_overlay_ref_pattern = (
1045 r"/chromeos\/overlays\/overlay-([\w-]+)-private"
1046 )
1047 match = re.match(private_overlay_ref_pattern, ref.path)
1048 if not match:
1049 raise ValueError(
1050 "ref.path must match the pattern: %s. Actual ref: %s"
1051 % (private_overlay_ref_pattern, ref)
1052 )
Andrew Lambe836f222019-12-09 12:27:38 -07001053
Alex Klein1699fab2022-09-08 08:46:06 -06001054 overlay = match.group(1)
Andrew Lambe836f222019-12-09 12:27:38 -07001055
Alex Klein1699fab2022-09-08 08:46:06 -06001056 return os.path.join(
1057 constants.SOURCE_ROOT,
1058 "src/private-overlays/overlay-%s-private" % overlay,
1059 package,
1060 )
Andrew Lambe836f222019-12-09 12:27:38 -07001061
1062
Alex Klein1699fab2022-09-08 08:46:06 -06001063@uprevs_versioned_package("chromeos-base/chromeos-config-bsp")
Andrew Lambea9a8a22019-12-12 14:03:43 -07001064def replicate_private_config(_build_targets, refs, chroot):
Alex Kleinfee86da2023-01-20 18:40:06 -07001065 """Replicate private cros_config change to the corresponding public config.
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001066
Alex Klein1699fab2022-09-08 08:46:06 -06001067 See uprev_versioned_package for args
1068 """
1069 package = "chromeos-base/chromeos-config-bsp"
Andrew Lambea9a8a22019-12-12 14:03:43 -07001070
Alex Klein1699fab2022-09-08 08:46:06 -06001071 if len(refs) != 1:
1072 raise ValueError("Expected exactly one ref, actual %s" % refs)
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001073
Alex Klein1699fab2022-09-08 08:46:06 -06001074 # Expect a replication_config.jsonpb in the package root.
1075 package_root = _get_private_overlay_package_root(refs[0], package)
1076 replication_config_path = os.path.join(
1077 package_root, "replication_config.jsonpb"
1078 )
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001079
Alex Klein1699fab2022-09-08 08:46:06 -06001080 try:
1081 replication_config = json_format.Parse(
1082 osutils.ReadFile(replication_config_path),
1083 replication_config_pb2.ReplicationConfig(),
1084 )
1085 except IOError:
1086 raise ValueError(
1087 "Expected ReplicationConfig missing at %s" % replication_config_path
1088 )
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001089
Alex Klein1699fab2022-09-08 08:46:06 -06001090 replication_lib.Replicate(replication_config)
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001091
Alex Klein1699fab2022-09-08 08:46:06 -06001092 modified_files = [
1093 rule.destination_path
1094 for rule in replication_config.file_replication_rules
1095 ]
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001096
Alex Kleinfee86da2023-01-20 18:40:06 -07001097 # The generated platform C files are not easily filtered by replication
1098 # rules, i.e. JSON / proto filtering can be described by a FieldMask,
1099 # arbitrary C files cannot. Therefore, replicate and filter the JSON
1100 # payloads, and then generate filtered C files from the JSON payload.
Alex Klein1699fab2022-09-08 08:46:06 -06001101 modified_files.extend(
1102 _generate_platform_c_files(replication_config, chroot)
1103 )
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001104
Alex Klein1699fab2022-09-08 08:46:06 -06001105 # Use the private repo's commit hash as the new version.
1106 new_private_version = refs[0].revision
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001107
Alex Klein1699fab2022-09-08 08:46:06 -06001108 # modified_files should contain only relative paths at this point, but the
1109 # returned UprevVersionedPackageResult must contain only absolute paths.
1110 for i, modified_file in enumerate(modified_files):
1111 assert not os.path.isabs(modified_file)
1112 modified_files[i] = os.path.join(constants.SOURCE_ROOT, modified_file)
Andrew Lamb988f4da2019-12-10 10:16:43 -07001113
Alex Klein1699fab2022-09-08 08:46:06 -06001114 return uprev_lib.UprevVersionedPackageResult().add_result(
1115 new_private_version, modified_files
1116 )
Andrew Lamb2bde9e42019-11-04 13:24:09 -07001117
1118
Alex Klein1699fab2022-09-08 08:46:06 -06001119@uprevs_versioned_package("chromeos-base/crosvm")
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001120def uprev_crosvm(_build_targets, refs, _chroot):
Alex Klein1699fab2022-09-08 08:46:06 -06001121 """Updates crosvm ebuilds to latest revision
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001122
Alex Klein1699fab2022-09-08 08:46:06 -06001123 crosvm is not versioned. We are updating to the latest commit on the main
1124 branch.
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001125
Alex Klein1699fab2022-09-08 08:46:06 -06001126 See: uprev_versioned_package.
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001127
Alex Klein1699fab2022-09-08 08:46:06 -06001128 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001129 UprevVersionedPackageResult: The result of updating crosvm ebuilds.
Alex Klein1699fab2022-09-08 08:46:06 -06001130 """
1131 overlay = os.path.join(
1132 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
1133 )
1134 repo_path = os.path.join(constants.SOURCE_ROOT, "src", "crosvm")
1135 manifest = git.ManifestCheckout.Cached(repo_path)
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001136
Alex Klein1699fab2022-09-08 08:46:06 -06001137 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1138 uprev_manager.uprev(
1139 package_list=[
1140 "chromeos-base/crosvm",
1141 "dev-rust/assertions",
1142 "dev-rust/cros_async",
1143 "dev-rust/cros_fuzz",
1144 "dev-rust/data_model",
1145 "dev-rust/enumn",
1146 "dev-rust/io_uring",
1147 "dev-rust/p9",
1148 "dev-rust/sync",
1149 "dev-rust/sys_util",
1150 "dev-rust/tempfile",
1151 "media-sound/audio_streams",
1152 ],
1153 force=True,
1154 )
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001155
Alex Klein1699fab2022-09-08 08:46:06 -06001156 updated_files = uprev_manager.modified_ebuilds
1157 result = uprev_lib.UprevVersionedPackageResult()
1158 result.add_result(refs[0].revision, updated_files)
1159 return result
Dennis Kempinef05f2b2021-09-08 16:36:49 -07001160
1161
Yi Choua4854ac2022-11-14 10:54:24 +08001162@uprevs_versioned_package("chromeos-base/ti50-emulator")
1163def uprev_ti50_emulator(_build_targets, refs, _chroot):
1164 """Updates ti50-emulator ebuilds to latest revision
1165
1166 ti50-emulator is not versioned. We are updating to the latest commit on the
1167 main branch.
1168
1169 See: uprev_versioned_package.
1170
1171 Returns:
1172 UprevVersionedPackageResult: The result of updating ti50-emulator
1173 ebuild.
1174 """
1175 overlay = os.path.join(
1176 constants.SOURCE_ROOT, constants.CHROMEOS_OVERLAY_DIR
1177 )
1178
1179 # The ti50-emulator will touch multiple repos.
1180 manifest = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
1181
1182 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1183 uprev_manager.uprev(
1184 package_list=["chromeos-base/ti50-emulator"],
1185 force=True,
1186 )
1187
1188 updated_files = uprev_manager.modified_ebuilds
1189 result = uprev_lib.UprevVersionedPackageResult()
1190 result.add_result(refs[-1].revision, updated_files)
1191 return result
1192
1193
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001194@uprevs_versioned_package("chromeos-base/ec-devutils")
Jeremy Bettis0186d252023-01-19 14:47:46 -07001195def uprev_ecdevutils(_build_targets, refs, _chroot):
1196 """Updates ec-devutils ebuilds to latest revision
1197
Alex Kleinfee86da2023-01-20 18:40:06 -07001198 ec-devutils is not versioned. We are updating to the latest commit on the
1199 main branch.
Jeremy Bettis0186d252023-01-19 14:47:46 -07001200
1201 See: uprev_versioned_package.
1202
1203 Returns:
1204 UprevVersionedPackageResult: The result of updating ec-devutils ebuilds.
1205 """
1206 overlay = os.path.join(
1207 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
1208 )
1209 repo_path = os.path.join(constants.SOURCE_ROOT, "src", "platform", "ec")
1210 manifest = git.ManifestCheckout.Cached(repo_path)
1211
1212 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1213 uprev_manager.uprev(
1214 package_list=[
1215 "chromeos-base/ec-devutils",
1216 ],
1217 force=True,
1218 )
1219
1220 updated_files = uprev_manager.modified_ebuilds
1221 result = uprev_lib.UprevVersionedPackageResult()
1222 result.add_result(refs[0].revision, updated_files)
1223 return result
1224
1225
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001226@uprevs_versioned_package("chromeos-base/ec-utils")
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001227def uprev_ecutils(_build_targets, refs, _chroot):
1228 """Updates ec-utils ebuilds to latest revision
1229
1230 ec-utils is not versioned. We are updating to the latest commit on the main
1231 branch.
1232
1233 See: uprev_versioned_package.
1234
1235 Returns:
1236 UprevVersionedPackageResult: The result of updating ec-utils ebuilds.
1237 """
1238 overlay = os.path.join(
1239 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
1240 )
1241 repo_path = os.path.join(constants.SOURCE_ROOT, "src", "platform", "ec")
1242 manifest = git.ManifestCheckout.Cached(repo_path)
1243
1244 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1245 uprev_manager.uprev(
1246 package_list=[
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001247 "chromeos-base/ec-utils",
Jeremy Bettis0186d252023-01-19 14:47:46 -07001248 ],
1249 force=True,
1250 )
1251
1252 updated_files = uprev_manager.modified_ebuilds
1253 result = uprev_lib.UprevVersionedPackageResult()
1254 result.add_result(refs[0].revision, updated_files)
1255 return result
1256
1257
1258@uprevs_versioned_package("chromeos-base/ec-utils-test")
1259def uprev_ecutilstest(_build_targets, refs, _chroot):
1260 """Updates ec-utils-test ebuilds to latest revision
1261
Alex Kleinfee86da2023-01-20 18:40:06 -07001262 ec-utils-test is not versioned. We are updating to the latest commit on the
1263 main branch.
Jeremy Bettis0186d252023-01-19 14:47:46 -07001264
1265 See: uprev_versioned_package.
1266
1267 Returns:
Alex Kleinfee86da2023-01-20 18:40:06 -07001268 UprevVersionedPackageResult: The result of updating ec-utils-test
1269 ebuilds.
Jeremy Bettis0186d252023-01-19 14:47:46 -07001270 """
1271 overlay = os.path.join(
1272 constants.SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
1273 )
1274 repo_path = os.path.join(constants.SOURCE_ROOT, "src", "platform", "ec")
1275 manifest = git.ManifestCheckout.Cached(repo_path)
1276
1277 uprev_manager = uprev_lib.UprevOverlayManager([overlay], manifest)
1278 uprev_manager.uprev(
1279 package_list=[
Jeremy Bettisaf96afb2023-01-11 16:09:58 -07001280 "chromeos-base/ec-utils-test",
1281 ],
1282 force=True,
1283 )
1284
1285 updated_files = uprev_manager.modified_ebuilds
1286 result = uprev_lib.UprevVersionedPackageResult()
1287 result.add_result(refs[0].revision, updated_files)
1288 return result
1289
1290
Alex Klein5caab872021-09-10 11:44:37 -06001291def get_best_visible(
Alex Klein1699fab2022-09-08 08:46:06 -06001292 atom: str, build_target: Optional["build_target_lib.BuildTarget"] = None
Alex Klein5caab872021-09-10 11:44:37 -06001293) -> package_info.PackageInfo:
Alex Klein1699fab2022-09-08 08:46:06 -06001294 """Returns the best visible CPV for the given atom.
Alex Kleinbbef2b32019-08-27 10:38:50 -06001295
Alex Klein1699fab2022-09-08 08:46:06 -06001296 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001297 atom: The atom to look up.
1298 build_target: The build target whose sysroot should be searched, or the
1299 SDK if not provided.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001300
Alex Klein1699fab2022-09-08 08:46:06 -06001301 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001302 The best visible package, or None if none are visible.
Alex Klein1699fab2022-09-08 08:46:06 -06001303 """
1304 assert atom
Alex Kleinbbef2b32019-08-27 10:38:50 -06001305
Alex Klein1699fab2022-09-08 08:46:06 -06001306 return portage_util.PortageqBestVisible(
1307 atom,
1308 board=build_target.name if build_target else None,
1309 sysroot=build_target.root if build_target else None,
1310 )
Alex Kleinda39c6d2019-09-16 14:36:36 -06001311
1312
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001313def has_prebuilt(
1314 atom: str,
Alex Klein1699fab2022-09-08 08:46:06 -06001315 build_target: "build_target_lib.BuildTarget" = None,
1316 useflags: Union[Iterable[str], str] = None,
1317) -> bool:
1318 """Check if a prebuilt exists.
Alex Kleinda39c6d2019-09-16 14:36:36 -06001319
Alex Klein1699fab2022-09-08 08:46:06 -06001320 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001321 atom: The package whose prebuilt is being queried.
1322 build_target: The build target whose sysroot should be searched, or the
1323 SDK if not provided.
1324 useflags: Any additional USE flags that should be set. May be a string
1325 of properly formatted USE flags, or an iterable of individual flags.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001326
Alex Klein1699fab2022-09-08 08:46:06 -06001327 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001328 True if there is an available prebuilt, False otherwise.
Alex Klein1699fab2022-09-08 08:46:06 -06001329 """
1330 assert atom
Alex Kleinda39c6d2019-09-16 14:36:36 -06001331
Alex Klein1699fab2022-09-08 08:46:06 -06001332 board = build_target.name if build_target else None
1333 extra_env = None
1334 if useflags:
1335 new_flags = useflags
1336 if not isinstance(useflags, str):
1337 new_flags = " ".join(useflags)
Alex Klein149fd3b2019-12-16 16:01:05 -07001338
Alex Klein1699fab2022-09-08 08:46:06 -06001339 existing = os.environ.get("USE", "")
1340 final_flags = "%s %s" % (existing, new_flags)
1341 extra_env = {"USE": final_flags.strip()}
1342 return portage_util.HasPrebuilt(atom, board=board, extra_env=extra_env)
Alex Klein36b117f2019-09-30 15:13:46 -06001343
1344
David Burger0f9dd4e2019-10-08 12:33:42 -06001345def builds(atom, build_target, packages=None):
Alex Klein1699fab2022-09-08 08:46:06 -06001346 """Check if |build_target| builds |atom| (has it in its depgraph)."""
1347 cros_build_lib.AssertInsideChroot()
Alex Klein36b117f2019-09-30 15:13:46 -06001348
Alex Klein1699fab2022-09-08 08:46:06 -06001349 pkgs = tuple(packages) if packages else None
1350 # TODO(crbug/1081828): Receive and use sysroot.
1351 graph, _sdk_graph = dependency.GetBuildDependency(
1352 build_target.root, build_target.name, pkgs
1353 )
1354 return any(atom in package for package in graph["package_deps"])
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001355
1356
Alex Klein6becabc2020-09-11 14:03:05 -06001357def needs_chrome_source(
Alex Klein1699fab2022-09-08 08:46:06 -06001358 build_target: "build_target_lib.BuildTarget",
Alex Klein6becabc2020-09-11 14:03:05 -06001359 compile_source=False,
1360 packages: Optional[List[package_info.PackageInfo]] = None,
Alex Klein1699fab2022-09-08 08:46:06 -06001361 useflags=None,
1362):
1363 """Check if the chrome source is needed.
Alex Klein6becabc2020-09-11 14:03:05 -06001364
Alex Klein1699fab2022-09-08 08:46:06 -06001365 The chrome source is needed if the build target builds chrome or any of its
1366 follower packages, and can't use a prebuilt for them either because it's not
1367 available, or because we can't use prebuilts because it must build from
1368 source.
1369 """
1370 cros_build_lib.AssertInsideChroot()
Alex Klein6becabc2020-09-11 14:03:05 -06001371
Alex Klein1699fab2022-09-08 08:46:06 -06001372 # Check if it builds chrome and/or a follower package.
1373 graph = depgraph.get_sysroot_dependency_graph(build_target.root, packages)
1374 builds_chrome = constants.CHROME_CP in graph
1375 builds_follower = {
1376 pkg: pkg in graph for pkg in constants.OTHER_CHROME_PACKAGES
1377 }
Alex Klein6becabc2020-09-11 14:03:05 -06001378
Alex Klein1699fab2022-09-08 08:46:06 -06001379 local_uprev = builds_chrome and revbump_chrome([build_target])
Alex Klein9ce3f682021-06-23 15:06:44 -06001380
Alex Kleinfee86da2023-01-20 18:40:06 -07001381 # When we are compiling source set False since we do not use prebuilts. When
1382 # not compiling from source, start with True, i.e. we have every prebuilt
Alex Klein1699fab2022-09-08 08:46:06 -06001383 # we've checked for up to this point.
1384 has_chrome_prebuilt = not compile_source
1385 has_follower_prebuilts = not compile_source
1386 # Save packages that need prebuilts for reporting.
1387 pkgs_needing_prebuilts = []
1388 if compile_source:
1389 # Need everything.
Alex Klein6becabc2020-09-11 14:03:05 -06001390 pkgs_needing_prebuilts.append(constants.CHROME_CP)
Alex Klein1699fab2022-09-08 08:46:06 -06001391 pkgs_needing_prebuilts.extend(
1392 [pkg for pkg, builds_pkg in builds_follower.items() if builds_pkg]
1393 )
1394 else:
1395 # Check chrome itself.
1396 if builds_chrome:
1397 has_chrome_prebuilt = has_prebuilt(
1398 constants.CHROME_CP,
1399 build_target=build_target,
1400 useflags=useflags,
1401 )
1402 if not has_chrome_prebuilt:
1403 pkgs_needing_prebuilts.append(constants.CHROME_CP)
1404 # Check follower packages.
1405 for pkg, builds_pkg in builds_follower.items():
1406 if not builds_pkg:
1407 continue
1408 prebuilt = has_prebuilt(
1409 pkg, build_target=build_target, useflags=useflags
1410 )
1411 has_follower_prebuilts &= prebuilt
1412 if not prebuilt:
1413 pkgs_needing_prebuilts.append(pkg)
Alex Kleinfee86da2023-01-20 18:40:06 -07001414 # Postcondition: has_chrome_prebuilt and has_follower_prebuilts now
1415 # correctly reflect whether we actually have the corresponding prebuilts for
1416 # the build.
Alex Klein6becabc2020-09-11 14:03:05 -06001417
Alex Klein1699fab2022-09-08 08:46:06 -06001418 needs_chrome = builds_chrome and not has_chrome_prebuilt
1419 needs_follower = (
1420 any(builds_follower.values()) and not has_follower_prebuilts
1421 )
Alex Klein6becabc2020-09-11 14:03:05 -06001422
Alex Klein1699fab2022-09-08 08:46:06 -06001423 return NeedsChromeSourceResult(
1424 needs_chrome_source=needs_chrome or needs_follower,
1425 builds_chrome=builds_chrome,
1426 packages=[package_info.parse(p) for p in pkgs_needing_prebuilts],
1427 missing_chrome_prebuilt=not has_chrome_prebuilt,
1428 missing_follower_prebuilt=not has_follower_prebuilts,
1429 local_uprev=local_uprev,
1430 )
Alex Klein6becabc2020-09-11 14:03:05 -06001431
1432
Alex Klein68a28712021-11-08 11:08:30 -07001433class TargetVersions(NamedTuple):
Alex Klein1699fab2022-09-08 08:46:06 -06001434 """Data class for the info that makes up the "target versions"."""
1435
1436 android_version: str
1437 android_branch: str
1438 android_target: str
1439 chrome_version: str
1440 platform_version: str
1441 milestone_version: str
1442 full_version: str
Gilberto Contreras4f2d1452023-01-30 23:22:58 +00001443 lacros_version: str
Alex Klein68a28712021-11-08 11:08:30 -07001444
1445
1446def get_target_versions(
Alex Klein1699fab2022-09-08 08:46:06 -06001447 build_target: "build_target_lib.BuildTarget",
1448 packages: List[package_info.PackageInfo] = None,
Alex Klein68a28712021-11-08 11:08:30 -07001449) -> TargetVersions:
Alex Klein1699fab2022-09-08 08:46:06 -06001450 """Aggregate version info for a few key packages and the OS as a whole."""
1451 # Android version.
1452 android_version = determine_android_version(build_target.name)
1453 logging.info("Found android version: %s", android_version)
1454 # Android branch version.
1455 android_branch = determine_android_branch(build_target.name)
1456 logging.info("Found android branch version: %s", android_branch)
1457 # Android target version.
1458 android_target = determine_android_target(build_target.name)
1459 logging.info("Found android target version: %s", android_target)
Alex Klein68a28712021-11-08 11:08:30 -07001460
Alex Klein1699fab2022-09-08 08:46:06 -06001461 # TODO(crbug/1019770): Investigate cases where builds_chrome is true but
1462 # chrome_version is None.
Alex Klein68a28712021-11-08 11:08:30 -07001463
Alex Klein1699fab2022-09-08 08:46:06 -06001464 builds_chrome = builds(constants.CHROME_CP, build_target, packages=packages)
1465 chrome_version = None
1466 if builds_chrome:
1467 # Chrome version fetch.
Gilberto Contreras4f2d1452023-01-30 23:22:58 +00001468 chrome_version = determine_package_version(
1469 constants.CHROME_CP, build_target
1470 )
Alex Klein1699fab2022-09-08 08:46:06 -06001471 logging.info("Found chrome version: %s", chrome_version)
Alex Klein68a28712021-11-08 11:08:30 -07001472
Gilberto Contreras4f2d1452023-01-30 23:22:58 +00001473 builds_lacros = builds(constants.LACROS_CP, build_target, packages=packages)
1474 lacros_version = None
1475 if builds_lacros:
1476 # LaCrOS version fetch.
1477 lacros_version = determine_package_version(
1478 constants.LACROS_CP, build_target
1479 )
1480 logging.info("Found LaCrOS version: %s", lacros_version)
1481
Alex Klein1699fab2022-09-08 08:46:06 -06001482 # The ChromeOS version info.
1483 platform_version = determine_platform_version()
1484 milestone_version = determine_milestone_version()
1485 full_version = determine_full_version()
Alex Klein68a28712021-11-08 11:08:30 -07001486
Alex Klein1699fab2022-09-08 08:46:06 -06001487 return TargetVersions(
1488 android_version,
1489 android_branch,
1490 android_target,
1491 chrome_version,
1492 platform_version,
1493 milestone_version,
1494 full_version,
Gilberto Contreras4f2d1452023-01-30 23:22:58 +00001495 lacros_version,
Alex Klein1699fab2022-09-08 08:46:06 -06001496 )
Alex Klein68a28712021-11-08 11:08:30 -07001497
1498
Gilberto Contreras4f2d1452023-01-30 23:22:58 +00001499def determine_package_version(
1500 cpv_name: str,
Alex Klein1699fab2022-09-08 08:46:06 -06001501 build_target: "build_target_lib.BuildTarget",
1502) -> Optional[str]:
Gilberto Contreras4f2d1452023-01-30 23:22:58 +00001503 """Returns the current package version for the board (or in buildroot).
Michael Mortensenc2615b72019-10-15 08:12:24 -06001504
Alex Klein1699fab2022-09-08 08:46:06 -06001505 Args:
Gilberto Contreras4f2d1452023-01-30 23:22:58 +00001506 cpv_name: the name of the ebuild CPV
Alex Klein348e7692022-10-13 17:03:37 -06001507 build_target: The board build target.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001508
Alex Klein1699fab2022-09-08 08:46:06 -06001509 Returns:
Gilberto Contreras4f2d1452023-01-30 23:22:58 +00001510 The version of the package, if available.
Alex Klein1699fab2022-09-08 08:46:06 -06001511 """
1512 # TODO(crbug/1019770): Long term we should not need the try/catch here once
1513 # the builds function above only returns True for chrome when
1514 # determine_chrome_version will succeed.
1515 try:
1516 pkg_info = portage_util.PortageqBestVisible(
Gilberto Contreras4f2d1452023-01-30 23:22:58 +00001517 cpv_name, build_target.name, cwd=constants.SOURCE_ROOT
Alex Klein1699fab2022-09-08 08:46:06 -06001518 )
1519 except cros_build_lib.RunCommandError as e:
1520 # Return None because portage failed when trying to determine the chrome
1521 # version.
1522 logging.warning("Caught exception in determine_chrome_package: %s", e)
1523 return None
1524 # Something like 78.0.3877.4_rc -> 78.0.3877.4
1525 return pkg_info.version.partition("_")[0]
Michael Mortensenc2615b72019-10-15 08:12:24 -06001526
1527
Alex Klein68a28712021-11-08 11:08:30 -07001528@functools.lru_cache()
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001529def determine_android_package(board: str) -> Optional[str]:
Alex Klein1699fab2022-09-08 08:46:06 -06001530 """Returns the active Android container package in use by the board.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001531
Alex Klein1699fab2022-09-08 08:46:06 -06001532 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001533 board: The board name this is specific to.
Alex Kleinad6b48a2020-01-08 16:57:41 -07001534
Alex Klein1699fab2022-09-08 08:46:06 -06001535 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001536 The android package string if there is one.
Alex Klein1699fab2022-09-08 08:46:06 -06001537 """
1538 try:
1539 packages = portage_util.GetPackageDependencies(
1540 "virtual/target-os", board=board
1541 )
1542 except cros_build_lib.RunCommandError as e:
1543 # Return None because a command (likely portage) failed when trying to
1544 # determine the package.
1545 logging.warning("Caught exception in determine_android_package: %s", e)
1546 return None
1547
1548 # We assume there is only one Android package in the depgraph.
1549 for package in packages:
1550 if package.startswith(
1551 "chromeos-base/android-container-"
1552 ) or package.startswith("chromeos-base/android-vm-"):
1553 return package
Michael Mortensene0f4b542019-10-24 15:30:23 -06001554 return None
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001555
1556
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001557def determine_android_version(board: str, package: str = None):
Alex Klein1699fab2022-09-08 08:46:06 -06001558 """Determine the current Android version in buildroot now and return it.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001559
Alex Klein1699fab2022-09-08 08:46:06 -06001560 This uses the typical portage logic to determine which version of Android
1561 is active right now in the buildroot.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001562
Alex Klein1699fab2022-09-08 08:46:06 -06001563 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001564 board: The board name this is specific to.
1565 package: The Android package, if already computed.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001566
Alex Klein1699fab2022-09-08 08:46:06 -06001567 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001568 The Android build ID of the container for the board.
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001569
Alex Klein1699fab2022-09-08 08:46:06 -06001570 Raises:
Alex Klein348e7692022-10-13 17:03:37 -06001571 NoAndroidVersionError: if no unique Android version can be determined.
Alex Klein1699fab2022-09-08 08:46:06 -06001572 """
1573 if not package:
1574 package = determine_android_package(board)
1575 if not package:
1576 return None
1577 cpv = package_info.SplitCPV(package)
1578 if not cpv:
1579 raise NoAndroidVersionError(
1580 "Android version could not be determined for %s" % board
1581 )
1582 return cpv.version_no_rev
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001583
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001584
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001585def determine_android_branch(board, package=None):
Alex Klein1699fab2022-09-08 08:46:06 -06001586 """Returns the Android branch in use by the active container ebuild."""
1587 if not package:
1588 package = determine_android_package(board)
1589 if not package:
1590 return None
1591 ebuild_path = portage_util.FindEbuildForBoardPackage(package, board)
1592 # We assume all targets pull from the same branch and that we always
1593 # have at least one of the following targets.
Shao-Chuan Leeca2cbcc2022-11-02 08:28:31 +09001594 # TODO(b/187795671): Do this in a less hacky way.
1595 targets = android.GetAllAndroidEbuildTargets()
Alex Klein1699fab2022-09-08 08:46:06 -06001596 ebuild_content = osutils.SourceEnvironment(ebuild_path, targets)
1597 for target in targets:
1598 if target in ebuild_content:
1599 branch = re.search(r"(.*?)-linux-", ebuild_content[target])
1600 if branch is not None:
1601 return branch.group(1)
1602 raise NoAndroidBranchError(
1603 "Android branch could not be determined for %s (ebuild empty?)" % board
1604 )
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001605
1606
Mike Frysinger8e1c99a2021-03-05 00:58:11 -05001607def determine_android_target(board, package=None):
Alex Klein1699fab2022-09-08 08:46:06 -06001608 """Returns the Android target in use by the active container ebuild."""
1609 if not package:
1610 package = determine_android_package(board)
1611 if not package:
1612 return None
1613 if package.startswith("chromeos-base/android-vm-"):
1614 return "bertha"
1615 elif package.startswith("chromeos-base/android-container-"):
1616 return "cheets"
Michael Mortensenb70e8a82019-10-10 18:43:41 -06001617
Alex Klein1699fab2022-09-08 08:46:06 -06001618 raise NoAndroidTargetError(
1619 "Android Target cannot be determined for the package: %s" % package
1620 )
Michael Mortensen9fdb14b2019-10-17 11:17:30 -06001621
1622
1623def determine_platform_version():
Alex Klein1699fab2022-09-08 08:46:06 -06001624 """Returns the platform version from the source root."""
1625 # Platform version is something like '12575.0.0'.
1626 version = chromeos_version.VersionInfo.from_repo(constants.SOURCE_ROOT)
1627 return version.VersionString()
Michael Mortensen009cb662019-10-21 11:38:43 -06001628
1629
1630def determine_milestone_version():
Alex Klein1699fab2022-09-08 08:46:06 -06001631 """Returns the platform version from the source root."""
1632 # Milestone version is something like '79'.
1633 version = chromeos_version.VersionInfo.from_repo(constants.SOURCE_ROOT)
1634 return version.chrome_branch
Michael Mortensen009cb662019-10-21 11:38:43 -06001635
Alex Klein7a3a7dd2020-01-08 16:44:38 -07001636
Michael Mortensen009cb662019-10-21 11:38:43 -06001637def determine_full_version():
Alex Klein1699fab2022-09-08 08:46:06 -06001638 """Returns the full version from the source root."""
1639 # Full version is something like 'R79-12575.0.0'.
1640 milestone_version = determine_milestone_version()
1641 platform_version = determine_platform_version()
1642 full_version = "R%s-%s" % (milestone_version, platform_version)
1643 return full_version
Michael Mortensen71ef5682020-05-07 14:29:24 -06001644
1645
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001646def find_fingerprints(
Alex Klein1699fab2022-09-08 08:46:06 -06001647 build_target: "build_target_lib.BuildTarget",
1648) -> List[str]:
1649 """Returns a list of fingerprints for this build.
Michael Mortensende716a12020-05-15 11:27:00 -06001650
Alex Klein1699fab2022-09-08 08:46:06 -06001651 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001652 build_target: The build target.
Michael Mortensende716a12020-05-15 11:27:00 -06001653
Alex Klein1699fab2022-09-08 08:46:06 -06001654 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001655 List of fingerprint strings.
Alex Klein1699fab2022-09-08 08:46:06 -06001656 """
1657 cros_build_lib.AssertInsideChroot()
1658 fp_file = "cheets-fingerprint.txt"
1659 fp_path = os.path.join(
1660 image_lib.GetLatestImageLink(build_target.name), fp_file
1661 )
1662 if not os.path.isfile(fp_path):
1663 logging.info("Fingerprint file not found: %s", fp_path)
1664 return []
1665 logging.info("Reading fingerprint file: %s", fp_path)
1666 fingerprints = osutils.ReadFile(fp_path).splitlines()
1667 return fingerprints
Michael Mortensende716a12020-05-15 11:27:00 -06001668
1669
Alex Klein1699fab2022-09-08 08:46:06 -06001670def get_all_firmware_versions(build_target: "build_target_lib.BuildTarget"):
1671 """Extract firmware version for all models present.
Michael Mortensen59e30872020-05-18 14:12:49 -06001672
Alex Klein1699fab2022-09-08 08:46:06 -06001673 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001674 build_target: The build target.
Michael Mortensen59e30872020-05-18 14:12:49 -06001675
Alex Klein1699fab2022-09-08 08:46:06 -06001676 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001677 A dict of FirmwareVersions namedtuple instances by model.
1678 Each element will be populated based on whether it was present in the
1679 command output.
Alex Klein1699fab2022-09-08 08:46:06 -06001680 """
1681 cros_build_lib.AssertInsideChroot()
1682 result = {}
1683 # Note that example output for _get_firmware_version_cmd_result is available
1684 # in the packages_unittest.py for testing get_all_firmware_versions.
1685 cmd_result = _get_firmware_version_cmd_result(build_target)
Michael Mortensen59e30872020-05-18 14:12:49 -06001686
Alex Klein1699fab2022-09-08 08:46:06 -06001687 if cmd_result:
1688 # There is a blank line between the version info for each model.
1689 firmware_version_payloads = cmd_result.split("\n\n")
1690 for firmware_version_payload in firmware_version_payloads:
1691 if "BIOS" in firmware_version_payload:
1692 firmware_version = _find_firmware_versions(
1693 firmware_version_payload
1694 )
1695 result[firmware_version.model] = firmware_version
1696 return result
Michael Mortensen59e30872020-05-18 14:12:49 -06001697
1698
Benjamin Shai0858cd32022-01-10 20:23:49 +00001699class FirmwareVersions(NamedTuple):
Alex Klein1699fab2022-09-08 08:46:06 -06001700 """Tuple to hold firmware versions, with truthiness."""
Benjamin Shai0858cd32022-01-10 20:23:49 +00001701
Alex Klein1699fab2022-09-08 08:46:06 -06001702 model: Optional[str]
1703 main: Optional[str]
1704 main_rw: Optional[str]
1705 ec: Optional[str]
1706 ec_rw: Optional[str]
1707
1708 def __bool__(self):
1709 return bool(
1710 self.model or self.main or self.main_rw or self.ec or self.ec_rw
1711 )
Michael Mortensen71ef5682020-05-07 14:29:24 -06001712
1713
Alex Klein1699fab2022-09-08 08:46:06 -06001714def get_firmware_versions(build_target: "build_target_lib.BuildTarget"):
1715 """Extract version information from the firmware updater, if one exists.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001716
Alex Klein1699fab2022-09-08 08:46:06 -06001717 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001718 build_target: The build target.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001719
Alex Klein1699fab2022-09-08 08:46:06 -06001720 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001721 A FirmwareVersions namedtuple instance.
1722 Each element will either be set to the string output by the firmware
1723 updater shellball, or None if there is no firmware updater.
Alex Klein1699fab2022-09-08 08:46:06 -06001724 """
1725 cros_build_lib.AssertInsideChroot()
1726 cmd_result = _get_firmware_version_cmd_result(build_target)
1727 if cmd_result:
1728 return _find_firmware_versions(cmd_result)
1729 else:
1730 return FirmwareVersions(None, None, None, None, None)
Michael Mortensen71ef5682020-05-07 14:29:24 -06001731
1732
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001733def _get_firmware_version_cmd_result(
Alex Klein1699fab2022-09-08 08:46:06 -06001734 build_target: "build_target_lib.BuildTarget",
1735) -> Optional[str]:
1736 """Gets the raw result output of the firmware updater version command.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001737
Alex Klein1699fab2022-09-08 08:46:06 -06001738 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001739 build_target: The build target.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001740
Alex Klein1699fab2022-09-08 08:46:06 -06001741 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001742 Command execution result.
Alex Klein1699fab2022-09-08 08:46:06 -06001743 """
1744 updater = os.path.join(
1745 build_target.root, "usr/sbin/chromeos-firmwareupdate"
1746 )
1747 logging.info("Calling updater %s", updater)
1748 # Call the updater using the chroot-based path.
1749 try:
1750 return cros_build_lib.run(
1751 [updater, "-V"],
1752 capture_output=True,
1753 log_output=True,
1754 encoding="utf-8",
1755 ).stdout
1756 except cros_build_lib.RunCommandError:
1757 # Updater probably doesn't exist (e.g. betty).
1758 return None
Michael Mortensen71ef5682020-05-07 14:29:24 -06001759
1760
1761def _find_firmware_versions(cmd_output):
Alex Klein1699fab2022-09-08 08:46:06 -06001762 """Finds firmware version output via regex matches against the cmd_output.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001763
Alex Klein1699fab2022-09-08 08:46:06 -06001764 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001765 cmd_output: The raw output to search against.
Michael Mortensen71ef5682020-05-07 14:29:24 -06001766
Alex Klein1699fab2022-09-08 08:46:06 -06001767 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001768 FirmwareVersions namedtuple with results.
1769 Each element will either be set to the string output by the firmware
1770 updater shellball, or None if there is no match.
Alex Klein1699fab2022-09-08 08:46:06 -06001771 """
Michael Mortensen71ef5682020-05-07 14:29:24 -06001772
Alex Klein1699fab2022-09-08 08:46:06 -06001773 # Sometimes a firmware bundle includes a special combination of RO+RW
1774 # firmware. In this case, the RW firmware version is indicated with a "(RW)
1775 # version" field. In other cases, the "(RW) version" field is not present.
1776 # Therefore, search for the "(RW)" fields first and if they aren't present,
1777 # fallback to the other format. e.g. just "BIOS version:".
1778 # TODO(mmortensen): Use JSON once the firmware updater supports it.
1779 main = None
1780 main_rw = None
1781 ec = None
1782 ec_rw = None
1783 model = None
Michael Mortensen71ef5682020-05-07 14:29:24 -06001784
Alex Klein1699fab2022-09-08 08:46:06 -06001785 match = re.search(r"BIOS version:\s*(?P<version>.*)", cmd_output)
1786 if match:
1787 main = match.group("version")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001788
Alex Klein1699fab2022-09-08 08:46:06 -06001789 match = re.search(r"BIOS \(RW\) version:\s*(?P<version>.*)", cmd_output)
1790 if match:
1791 main_rw = match.group("version")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001792
Alex Klein1699fab2022-09-08 08:46:06 -06001793 match = re.search(r"EC version:\s*(?P<version>.*)", cmd_output)
1794 if match:
1795 ec = match.group("version")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001796
Alex Klein1699fab2022-09-08 08:46:06 -06001797 match = re.search(r"EC \(RW\) version:\s*(?P<version>.*)", cmd_output)
1798 if match:
1799 ec_rw = match.group("version")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001800
Alex Klein1699fab2022-09-08 08:46:06 -06001801 match = re.search(r"Model:\s*(?P<model>.*)", cmd_output)
1802 if match:
1803 model = match.group("model")
Michael Mortensen71ef5682020-05-07 14:29:24 -06001804
Alex Klein1699fab2022-09-08 08:46:06 -06001805 return FirmwareVersions(model, main, main_rw, ec, ec_rw)
Michael Mortensena4af79e2020-05-06 16:18:48 -06001806
1807
Benjamin Shai0858cd32022-01-10 20:23:49 +00001808class MainEcFirmwareVersions(NamedTuple):
Alex Klein1699fab2022-09-08 08:46:06 -06001809 """Tuple to hold main and ec firmware versions, with truthiness."""
Benjamin Shai0858cd32022-01-10 20:23:49 +00001810
Alex Klein1699fab2022-09-08 08:46:06 -06001811 main_fw_version: Optional[str]
1812 ec_fw_version: Optional[str]
1813
1814 def __bool__(self):
1815 return bool(self.main_fw_version or self.ec_fw_version)
Benjamin Shai0858cd32022-01-10 20:23:49 +00001816
Michael Mortensena4af79e2020-05-06 16:18:48 -06001817
Alex Klein1699fab2022-09-08 08:46:06 -06001818def determine_firmware_versions(build_target: "build_target_lib.BuildTarget"):
1819 """Returns a namedtuple with main and ec firmware versions.
Michael Mortensena4af79e2020-05-06 16:18:48 -06001820
Alex Klein1699fab2022-09-08 08:46:06 -06001821 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001822 build_target: The build target.
Michael Mortensena4af79e2020-05-06 16:18:48 -06001823
Alex Klein1699fab2022-09-08 08:46:06 -06001824 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001825 MainEcFirmwareVersions namedtuple with results.
Alex Klein1699fab2022-09-08 08:46:06 -06001826 """
1827 fw_versions = get_firmware_versions(build_target)
1828 main_fw_version = fw_versions.main_rw or fw_versions.main
1829 ec_fw_version = fw_versions.ec_rw or fw_versions.ec
Michael Mortensena4af79e2020-05-06 16:18:48 -06001830
Alex Klein1699fab2022-09-08 08:46:06 -06001831 return MainEcFirmwareVersions(main_fw_version, ec_fw_version)
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001832
Benjamin Shai0858cd32022-01-10 20:23:49 +00001833
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001834def determine_kernel_version(
Alex Klein1699fab2022-09-08 08:46:06 -06001835 build_target: "build_target_lib.BuildTarget",
Lizzy Presland0b978e62022-09-09 16:55:29 +00001836) -> str:
Alex Klein1699fab2022-09-08 08:46:06 -06001837 """Returns a string containing the kernel version for this build target.
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001838
Alex Klein1699fab2022-09-08 08:46:06 -06001839 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001840 build_target: The build target.
Michael Mortensenfbf2b2d2020-05-14 16:33:06 -06001841
Alex Klein1699fab2022-09-08 08:46:06 -06001842 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001843 The kernel versions, or empty string.
Alex Klein1699fab2022-09-08 08:46:06 -06001844 """
Lizzy Presland0b978e62022-09-09 16:55:29 +00001845 target_virtual_pkg = "virtual/linux-sources"
Alex Klein1699fab2022-09-08 08:46:06 -06001846 try:
Lizzy Presland0b978e62022-09-09 16:55:29 +00001847 candidate_packages = portage_util.GetFlattenedDepsForPackage(
1848 target_virtual_pkg,
1849 sysroot=build_target.root,
1850 board=build_target.name,
1851 depth=1,
1852 )
1853 installed_packages = portage_util.GetPackageDependencies(
1854 target_virtual_pkg, board=build_target.name
Alex Klein1699fab2022-09-08 08:46:06 -06001855 )
1856 except cros_build_lib.RunCommandError as e:
1857 logging.warning("Unable to get package list for metadata: %s", e)
Lizzy Presland0b978e62022-09-09 16:55:29 +00001858 return ""
1859 if not candidate_packages:
1860 raise KernelVersionError("No package found in FlattenedDepsForPackage")
1861 if not installed_packages:
1862 raise KernelVersionError("No package found in GetPackageDependencies")
1863 packages = [
1864 p
1865 for p in installed_packages
1866 if p in candidate_packages and target_virtual_pkg not in p
1867 ]
1868 if len(packages) == 0:
1869 raise KernelVersionError(
1870 "No matches for installed packages were found in candidate "
1871 "packages. Did GetFlattenedDepsForPackage search all possible "
1872 "package versions?\tInstalled: %s\tCandidates: %s"
1873 % (" ".join(installed_packages), " ".join(candidate_packages))
1874 )
1875 if len(packages) > 1:
1876 raise KernelVersionError(
1877 "Too many packages found in intersection of installed packages and "
1878 "possible kernel versions (%s)" % "".join(packages)
1879 )
1880 kernel_version = package_info.SplitCPV(packages[0]).version
1881 logging.info("Found active kernel version: %s", kernel_version)
1882 return kernel_version
Michael Mortensen125bb012020-05-21 14:02:10 -06001883
1884
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001885def get_models(
Alex Klein1699fab2022-09-08 08:46:06 -06001886 build_target: "build_target_lib.BuildTarget", log_output: bool = True
1887) -> Optional[List[str]]:
1888 """Obtain a list of models supported by a unified board.
Michael Mortensen125bb012020-05-21 14:02:10 -06001889
Alex Klein1699fab2022-09-08 08:46:06 -06001890 This ignored whitelabel models since GoldenEye has no specific support for
1891 these at present.
Michael Mortensen125bb012020-05-21 14:02:10 -06001892
Alex Klein1699fab2022-09-08 08:46:06 -06001893 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001894 build_target: The build target.
1895 log_output: Whether to log the output of the cros_config_host
1896 invocation.
Michael Mortensen125bb012020-05-21 14:02:10 -06001897
Alex Klein1699fab2022-09-08 08:46:06 -06001898 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001899 A list of models supported by this board, if it is a unified build;
1900 None, if it is not a unified build.
Alex Klein1699fab2022-09-08 08:46:06 -06001901 """
1902 return _run_cros_config_host(
1903 build_target, ["list-models"], log_output=log_output
1904 )
Michael Mortensen125bb012020-05-21 14:02:10 -06001905
1906
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001907def get_key_id(
Alex Klein1699fab2022-09-08 08:46:06 -06001908 build_target: "build_target_lib.BuildTarget", model: str
1909) -> Optional[str]:
1910 """Obtain the key_id for a model within the build_target.
Michael Mortensen359c1f32020-05-28 19:35:42 -06001911
Alex Klein1699fab2022-09-08 08:46:06 -06001912 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001913 build_target: The build target.
1914 model: The model name
Michael Mortensen359c1f32020-05-28 19:35:42 -06001915
Alex Klein1699fab2022-09-08 08:46:06 -06001916 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001917 A key_id or None.
Alex Klein1699fab2022-09-08 08:46:06 -06001918 """
1919 model_arg = "--model=" + model
1920 key_id_list = _run_cros_config_host(
1921 build_target, [model_arg, "get", "/firmware-signing", "key-id"]
1922 )
1923 key_id = None
1924 if len(key_id_list) == 1:
1925 key_id = key_id_list[0]
1926 return key_id
Michael Mortensen359c1f32020-05-28 19:35:42 -06001927
1928
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001929def _run_cros_config_host(
Alex Klein1699fab2022-09-08 08:46:06 -06001930 build_target: "build_target_lib.BuildTarget",
Matthias Kaehlckebf7d1772021-11-04 16:01:36 -07001931 args: List[str],
Alex Klein1699fab2022-09-08 08:46:06 -06001932 log_output: bool = True,
1933) -> Optional[List[str]]:
1934 """Run the cros_config_host tool.
Michael Mortensen125bb012020-05-21 14:02:10 -06001935
Alex Klein1699fab2022-09-08 08:46:06 -06001936 Args:
Alex Klein348e7692022-10-13 17:03:37 -06001937 build_target: The build target.
1938 args: List of arguments to pass.
1939 log_output: Whether to log the output of the cros_config_host.
Michael Mortensen125bb012020-05-21 14:02:10 -06001940
Alex Klein1699fab2022-09-08 08:46:06 -06001941 Returns:
Alex Klein348e7692022-10-13 17:03:37 -06001942 Output of the tool
Alex Klein1699fab2022-09-08 08:46:06 -06001943 """
1944 cros_build_lib.AssertInsideChroot()
1945 tool = "/usr/bin/cros_config_host"
1946 if not os.path.isfile(tool):
1947 return None
Michael Mortensen125bb012020-05-21 14:02:10 -06001948
Alex Klein1699fab2022-09-08 08:46:06 -06001949 config_fname = build_target.full_path(
1950 "usr/share/chromeos-config/yaml/config.yaml"
1951 )
Michael Mortensen125bb012020-05-21 14:02:10 -06001952
Alex Klein1699fab2022-09-08 08:46:06 -06001953 result = cros_build_lib.run(
1954 [tool, "-c", config_fname] + args,
1955 capture_output=True,
1956 encoding="utf-8",
1957 log_output=log_output,
1958 check=False,
1959 )
1960 if result.returncode:
1961 # Show the output for debugging purposes.
1962 if "No such file or directory" not in result.stderr:
1963 logging.error("cros_config_host failed: %s\n", result.stderr)
1964 return None
1965 return result.stdout.strip().splitlines()