blob: 1d9e03d6388c244d13d4984aa3ddc70003c2ff96 [file] [log] [blame]
# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Downloads AEMU artifacts from go/ab then uploads to CIPD."""
from PB.recipe_engine.result import RawResult
from PB.go.chromium.org.luci.buildbucket.proto import common
PYTHON_VERSION_COMPATIBILITY = "PY3"
DEPS = [
"fuchsia/aemu_downloader",
"fuchsia/buildbucket_util",
"fuchsia/status_check",
"recipe_engine/archive",
"recipe_engine/cipd",
"recipe_engine/file",
"recipe_engine/path",
"recipe_engine/raw_io",
"recipe_engine/step",
]
CIPD_PKG_ROOT = "fuchsia/third_party/android/aemu"
DEFAULT_PKG_TO_SEARCH = "%s/release/linux-amd64" % CIPD_PKG_ROOT
ANDROID_TARGET_TO_CIPD_PLATFORM = {
"sdk_tools_linux": "linux-amd64",
"sdk_tools_mac": "mac-amd64",
"aarch64_sdk_tools_linux": "linux-arm64",
"aarch64_sdk_tools_mac": "mac-arm64",
}
def RunSteps(api):
"""Checks latest AEMU artifact version and upload new version if not latest.
This recipe does the following
1. Check the latest Android BuildID (bid) from go/ab that contains all targets.
2. Search CIPD packages based on tag bid:<bid> from (1).
3. If CIPD search returns empty, download all artifacts from go/ab, and upload to CIPD using
the mapping:
sdk_tools_linux/sdk-repo-linux-emulator-<bid>.zip
-> /fuchsia/third_party/android/aemu/release/linux-amd64
sdk_tools_linux/sdk-repo-linux-emulator-full-debug<bid>.zip
-> /fuchsia/third_party/android/aemu/full-debug/linux-amd64
sdk_tools_mac/sdk-repo-darwin-emulator-<bid>.zip
-> /fuchsia/third_party/android/aemu/release/mac-amd64
sdk_tools_mac/sdk-repo-darwin-emulator-full-debug-<bid>.zip
-> /fuchsia/third_party/android/aemu/full-debug/mac-amd64
aarch64_sdk_tools_linux/sdk-repo-linux_aarch64-emulator-<bid>.zip
-> /fuchsia/third_party/android/aemu/release/linux-arm64
aarch64_sdk_tools_linux/sdk-repo-linux_aarch64-emulator-full-debug-<bid>.zip
-> /fuchsia/third_party/android/aemu/full-debug/linux-arm64
aarch64_sdk_tools_mac/sdk-repo-darwin_aarch64-emulator-<bid>.zip
-> /fuchsia/third_party/android/aemu/release/mac-arm64
aarch64_sdk_tools_mac/sdk-repo-darwin_aarch64-emulator-full-debug-<bid>.zip
-> /fuchsia/third_party/android/aemu/full-debug/mac-arm64
"""
with api.step.nest("check latest versions"):
step = api.aemu_downloader.get_latest_build_id(
step_name="get latest bid from Android build",
stdout=api.raw_io.output_text(),
step_test_data=lambda: api.raw_io.test_api.stream_output_text("1234567"),
)
bid = step.stdout.strip()
error_msg = None
if not bid:
error_msg = "did not find any build id to download"
elif not bid.isdigit():
error_msg = "got invalid bid: %s, expect a number" % bid
if error_msg:
step.presentation.status = api.step.EXCEPTION
raise api.step.InfraFailure(error_msg)
instances = api.cipd.search(
package_name=DEFAULT_PKG_TO_SEARCH,
tag="bid:%s" % bid,
test_instances=None,
)
do_download = not instances
if do_download:
with api.step.nest("download AEMU artifacts and upload to CIPD"):
download_root = api.path["cleanup"].join(bid)
api.file.ensure_directory("ensure download dir", download_root)
api.aemu_downloader.download(
step_name="download bid: %s" % bid,
android_build_id=bid,
output_root=download_root,
)
# The downloaded artifacts follow the file directory pattern
# [download_root]/target/artifact. An example would be
# [download_root]/sdk_tools_linux/sdk-repo-linux-emulator-1234567.zip where
# sdk_tools_linux is the target and sdk-repo-linux-emulator-1234567.zip is the artifact
for target in api.file.listdir(
"list downloaded targets",
download_root,
test_data=[
"aarch64_sdk_tools_linux",
"aarch64_sdk_tools_mac",
"sdk_tools_linux",
"sdk_tools_mac",
],
):
target_name = api.path.basename(target)
cipd_platform = ANDROID_TARGET_TO_CIPD_PLATFORM[target_name]
for artifact in api.file.listdir(
"list target in %s" % target_name,
target,
test_data=[
"sdk-repo-linux-emulator-1234567.zip",
"sdk-repo-linux-emulator-full-debug-1234567.zip",
],
):
artifact_filename = api.path.basename(artifact)
extract_output_root, ext = api.path.splitext(artifact_filename)
if ext != ".zip":
raise api.step.InfraFailure(
"Invalid file %s. Expected a .zip file" % artifact_filename
)
extract_output_root = target.join(extract_output_root)
api.archive.extract(
step_name="unzip %s" % artifact_filename,
archive_file=artifact,
output=extract_output_root,
)
# When we unzip, a subdir named 'emulator' is expected. We want to flatten
# the file structure by uploading only the contents under 'emulator' dir.
# So its important that we fail fast if this structure changes at android
# build side.
emulator_dir = extract_output_root.join("emulator")
api.path.mock_add_directory(emulator_dir)
assert api.path.isdir(emulator_dir)
if "full-debug" in artifact_filename:
pkg_subdir = "full-debug"
else:
pkg_subdir = "release"
cipd_pkg_dest = "%s/%s/%s" % (
CIPD_PKG_ROOT,
pkg_subdir,
cipd_platform,
)
if not api.buildbucket_util.is_tryjob:
pkg_def = api.cipd.PackageDefinition(
package_name=cipd_pkg_dest,
package_root=emulator_dir,
install_mode="copy",
)
pkg_def.add_dir(emulator_dir)
api.cipd.create_from_pkg(
pkg_def=pkg_def,
refs=["latest"],
tags={"bid": bid},
)
return RawResult(
status=common.SUCCESS,
summary_markdown="Uploaded bid:%s" % bid,
)
def GenTests(api):
yield (
api.status_check.test("aemu_downloader_do_download")
+ api.step_data(
"check latest versions.cipd search "
+ DEFAULT_PKG_TO_SEARCH
+ " bid:1234567",
api.cipd.example_search(DEFAULT_PKG_TO_SEARCH, []),
)
)
yield (
api.status_check.test(
"aemu_downloader_invalid_download", status="infra_failure"
)
+ api.step_data(
"check latest versions.cipd search "
+ DEFAULT_PKG_TO_SEARCH
+ " bid:1234567",
api.cipd.example_search(DEFAULT_PKG_TO_SEARCH, []),
)
+ api.step_data(
"download AEMU artifacts and upload to CIPD.list target in aarch64_sdk_tools_linux",
api.file.listdir(
["sdk-repo-linux-emulator-1234567.zip", "invalid_file.json"]
),
)
)
yield (
api.status_check.test("aemu_downloader_no_download")
+ api.step_data(
"check latest versions.cipd search "
+ DEFAULT_PKG_TO_SEARCH
+ " bid:1234567",
api.cipd.example_search(DEFAULT_PKG_TO_SEARCH, ["bid:1234567"]),
)
)
yield (
api.status_check.test("aemu_downloader_invalid_bid", status="infra_failure")
+ api.step_data(
"check latest versions.get latest bid from Android build",
stdout=api.raw_io.output_text("abcd1234"),
)
)
yield (
api.status_check.test("aemu_downloader_failed_bid", status="failure")
+ api.step_data(
"check latest versions.get latest bid from Android build",
retcode=1,
stdout=api.raw_io.output_text(""),
)
)
yield (
api.status_check.test("aemu_downloader_empty_bid", status="infra_failure")
+ api.step_data(
"check latest versions.get latest bid from Android build",
stdout=api.raw_io.output_text(""),
)
)