blob: 44079d54cb76fc235b28c75f72474e20b1cae9fd [file] [log] [blame] [edit]
# Copyright 2016 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module containing the Android stages."""
import logging
import os
from chromite.cbuildbot import cbuildbot_alerts
from chromite.cbuildbot import cbuildbot_run
from chromite.cbuildbot.stages import generic_stages
from chromite.lib import config_lib
from chromite.lib import constants
from chromite.lib import gs
from chromite.lib import osutils
class AndroidMetadataStage(
generic_stages.BuilderStage, generic_stages.ArchivingStageMixin
):
"""Stage that records Android container version in metadata.
This stage runs on every builder, not limited to Android PFQ. Metadata
written by this stage must reflect the actual Android version of the build
artifact.
Metadata written by this stage will be consumed by various external tools
such as GoldenEye.
"""
category = constants.PRODUCT_ANDROID_STAGE
def _UpdateBoardDictsForAndroidBuildInfo(self):
"""Updates board metadata to fill in Android build info.
Returns:
(versions, branches, targets) where:
versions: A set of Android versions used in target boards.
branches: A set of Android branch names used in target boards.
targets: A set of Android targets used in target boards.
"""
# Need to always iterate through and generate the board-specific
# Android version metadata. Each board must be handled separately
# since there might be differing builds in the same release group.
versions = set()
branches = set()
targets = set()
for builder_run in [self._run]:
for board in builder_run.config.boards:
try:
# Determine the version for each board and record metadata.
version = self._run.DetermineAndroidVersion(boards=[board])
builder_run.attrs.metadata.UpdateBoardDictWithDict(
board, {"android-container-version": version}
)
versions.add(version)
logging.info(
"Board %s has Android version %s", board, version
)
except cbuildbot_run.NoAndroidVersionError as ex:
logging.info(
"Board %s does not contain Android (%s)", board, ex
)
try:
# Determine the branch for each board and record metadata.
branch = self._run.DetermineAndroidBranch(board)
builder_run.attrs.metadata.UpdateBoardDictWithDict(
board, {"android-container-branch": branch}
)
branches.add(branch)
logging.info(
"Board %s has Android branch %s", board, branch
)
except cbuildbot_run.NoAndroidBranchError as ex:
logging.info(
"Board %s does not contain Android (%s)", board, ex
)
try:
# Determine the target for each board and record metadata.
target = self._run.DetermineAndroidTarget(board)
builder_run.attrs.metadata.UpdateBoardDictWithDict(
board, {"android-container-target": target}
)
targets.add(target)
logging.info(
"Board %s has Android target %s", board, target
)
except cbuildbot_run.NoAndroidTargetError as ex:
logging.info(
"Board %s does not contain Android (%s)", board, ex
)
arc_use = self._run.HasUseFlag(board, "arc")
logging.info(
"Board %s %s arc USE flag set.",
board,
"has" if arc_use else "does not have",
)
builder_run.attrs.metadata.UpdateBoardDictWithDict(
board, {"arc-use-set": arc_use}
)
return (versions, branches, targets)
def PerformStage(self) -> None:
with osutils.ChdirContext(self._build_root):
(
versions,
branches,
targets,
) = self._UpdateBoardDictsForAndroidBuildInfo()
# If there is a unique one across all the boards, treat it as the
# version for the build.
# TODO(nya): Represent "N/A" and "Multiple" differently in metadata.
def _Aggregate(v):
if not v:
return (None, "N/A")
elif len(v) == 1:
return (v[0], str(v[0]))
return (None, "Multiple")
metadata_version, debug_version = _Aggregate(list(versions))
metadata_branch, debug_branch = _Aggregate(list(branches))
metadata_target, debug_target = _Aggregate(list(targets))
# Update the primary metadata and upload it.
self._run.attrs.metadata.UpdateKeyDictWithDict(
"version",
{
"android": metadata_version,
"android-branch": metadata_branch,
"android-target": metadata_target,
},
)
self.UploadMetadata(filename=constants.PARTIAL_METADATA_JSON)
# Leave build info in buildbot steps page for convenience.
cbuildbot_alerts.PrintBuildbotStepText("tag %s" % debug_version)
cbuildbot_alerts.PrintBuildbotStepText("branch %s" % debug_branch)
cbuildbot_alerts.PrintBuildbotStepText("target %s" % debug_target)
class DownloadAndroidDebugSymbolsStage(
generic_stages.BoardSpecificBuilderStage, generic_stages.ArchivingStageMixin
):
"""Stage that downloads Android debug symbols.
Downloaded archive will be picked up by DebugSymbolsStage.
"""
category = constants.CI_INFRA_STAGE
def PerformStage(self) -> None:
if not config_lib.IsCanaryType(self._run.config.build_type):
logging.info("This stage runs only in release builders.")
return
# Get the Android versions set by AndroidMetadataStage.
version_dict = self._run.attrs.metadata.GetDict().get("version", {})
android_build_branch = version_dict.get("android-branch")
android_version = version_dict.get("android")
# On boards not supporting Android, versions will be None.
if not (android_build_branch and android_version):
logging.info("Android is not enabled on this board. Skipping.")
return
logging.info(
"Downloading symbols of Android %s (%s)...",
android_version,
android_build_branch,
)
with osutils.ChdirContext(self._build_root):
arch = self._run.DetermineAndroidABI(self._current_board)
variant = self._run.DetermineAndroidVariant(self._current_board)
android_target = self._run.DetermineAndroidTarget(
self._current_board
)
symbols_file_url = constants.ANDROID_SYMBOLS_URL_TEMPLATE % {
"branch": android_build_branch,
"target": android_target,
"arch": arch,
"version": android_version,
"variant": variant,
}
symbols_file = os.path.join(
self.archive_path, constants.ANDROID_SYMBOLS_FILE
)
gs_context = gs.GSContext()
gs_context.Copy(symbols_file_url, symbols_file)