| # Copyright 2019 The ChromiumOS Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Android operations.""" |
| |
| import logging |
| import os |
| from typing import TYPE_CHECKING |
| |
| from chromite.api import faux |
| from chromite.api import validate |
| from chromite.api.controller import controller_util |
| from chromite.api.gen.chromite.api import android_pb2 |
| from chromite.lib import constants |
| from chromite.lib import osutils |
| from chromite.lib.parser import package_info |
| from chromite.service import android |
| from chromite.service import packages |
| |
| |
| if TYPE_CHECKING: |
| from chromite.api import api_config |
| |
| |
| ANDROIDPIN_MASK_PATH = os.path.join( |
| constants.SOURCE_ROOT, |
| constants.CHROMIUMOS_OVERLAY_DIR, |
| "profiles", |
| "default", |
| "linux", |
| "package.mask", |
| "androidpin", |
| ) |
| |
| |
| def _GetLatestBuildResponse(_request, response, _config) -> None: |
| """Fake GetLatestBuild response.""" |
| response.android_version = "7123456" |
| |
| |
| @faux.success(_GetLatestBuildResponse) |
| @faux.empty_error |
| @validate.require("android_package") |
| @validate.validation_complete |
| def GetLatestBuild(request, response, _config) -> None: |
| build_id, _ = android.GetLatestBuild( |
| request.android_package, |
| build_branch=request.android_build_branch, |
| ) |
| response.android_version = build_id |
| |
| |
| def _MarkStableResponse(_request, response, _config) -> None: |
| """Add fake status to a successful response.""" |
| response.android_atom.category = "category" |
| response.android_atom.package_name = "android-package-name" |
| response.android_atom.version = "1.2" |
| response.status = android_pb2.MARK_STABLE_STATUS_SUCCESS |
| |
| |
| @faux.success(_MarkStableResponse) |
| @faux.empty_error |
| @validate.require("package_name") |
| @validate.validation_complete |
| def MarkStable( |
| request: android_pb2.MarkStableRequest, |
| response: android_pb2.MarkStableResponse, |
| _config: "api_config.ApiConfig", |
| ) -> None: |
| """Uprev Android, if able. |
| |
| Uprev Android, verify that the newly uprevved package can be emerged, and |
| return the new package info. |
| |
| See AndroidService documentation in api/proto/android.proto. |
| |
| Args: |
| request: The input proto. |
| response: The output proto. |
| _config: The call config. |
| """ |
| chroot = controller_util.ParseChroot(request.chroot) |
| build_targets = controller_util.ParseBuildTargets(request.build_targets) |
| package_name = request.package_name |
| android_build_branch = request.android_build_branch |
| android_version = request.android_version |
| skip_commit = request.skip_commit |
| ignore_data_collector_artifacts = request.ignore_data_collector_artifacts |
| |
| # Assume success. |
| response.status = android_pb2.MARK_STABLE_STATUS_SUCCESS |
| # TODO(crbug/904939): This should move to service/android.py and the port |
| # should be finished. |
| android_atom_to_build = None |
| try: |
| result = packages.uprev_android( |
| android_package=package_name, |
| chroot=chroot, |
| build_targets=build_targets, |
| android_build_branch=android_build_branch, |
| android_version=android_version, |
| skip_commit=skip_commit, |
| ignore_data_collector_artifacts=ignore_data_collector_artifacts, |
| ) |
| if result.revved: |
| android_atom_to_build = result.android_atom |
| except packages.AndroidIsPinnedUprevError as e: |
| # If the uprev failed due to a pin, CI needs to unpin and retry. |
| android_atom_to_build = e.new_android_atom |
| response.status = android_pb2.MARK_STABLE_STATUS_PINNED |
| |
| if android_atom_to_build: |
| pkg = package_info.parse(android_atom_to_build) |
| controller_util.serialize_package_info(pkg, response.android_atom) |
| else: |
| response.status = android_pb2.MARK_STABLE_STATUS_EARLY_EXIT |
| |
| |
| # We don't use @faux.success for UnpinVersion because response is unused. |
| @faux.all_empty |
| @validate.validation_complete |
| def UnpinVersion( |
| _request: android_pb2.UnpinVersionRequest, |
| _response: android_pb2.UnpinVersionResponse, |
| _config: "api_config.ApiConfig", |
| ) -> None: |
| """Unpin the Android version. |
| |
| See AndroidService documentation in api/proto/android.proto. |
| |
| Args: |
| _request: The input proto. (not used.) |
| _response: The output proto. (not used.) |
| _config: The call config. |
| """ |
| osutils.SafeUnlink(ANDROIDPIN_MASK_PATH) |
| |
| |
| def _WriteLKGBResponse(_request, response, _config) -> None: |
| """Fake WriteLKGB response.""" |
| response.modified_files.append("fake_file") |
| |
| |
| @faux.success(_WriteLKGBResponse) |
| @faux.empty_error |
| @validate.require("android_package", "android_version") |
| @validate.validation_complete |
| def WriteLKGB(request, response, _config) -> None: |
| android_package = request.android_package |
| android_version = request.android_version |
| android_branch = ( |
| request.android_branch |
| or android.GetAndroidBranchForPackage(android_package) |
| ) |
| android_package_dir = android.GetAndroidPackageDir(android_package) |
| |
| # Attempt to read current LKGB, if available. |
| current_lkgb = None |
| try: |
| current_lkgb = android.ReadLKGB(android_package_dir) |
| except android.MissingLKGBError: |
| logging.info("LKGB file is missing, creating a new one.") |
| except android.InvalidLKGBError: |
| logging.warning("Current LKGB file is invalid, overwriting.") |
| |
| # For release branches: check if the runtime artifacts pin exists. |
| milestone = packages.determine_milestone_version() |
| runtime_artifacts_pin = android.FindRuntimeArtifactsPin( |
| android_package, milestone |
| ) |
| if runtime_artifacts_pin is not None: |
| logging.info( |
| "Found runtime artifacts pin for M%s: %s", |
| milestone, |
| runtime_artifacts_pin, |
| ) |
| |
| lkgb = android.LKGB( |
| build_id=android_version, |
| branch=android_branch, |
| runtime_artifacts_pin=runtime_artifacts_pin, |
| ) |
| |
| # Do nothing if LKGB is already set to the requested version. |
| if current_lkgb == lkgb: |
| logging.warning( |
| "LKGB of %s is already %s, doing nothing.", |
| android_package, |
| android_version, |
| ) |
| return |
| |
| # Actually update LKGB. |
| modified = android.WriteLKGB(android_package_dir, lkgb) |
| response.modified_files.append(modified) |