blob: 55c9242719573f5671c43ef1d7fe9527d9649f0a [file] [log] [blame] [edit]
"""Recipe to build and test fuchsia-cast."""
import copy
import os
import re
import tempfile
from helpers import branch_utils
from slave import base_recipe
from slave.step import cipd_upload_step
from slave.step import fuchsia_cipd_upload_step
from slave.step import fuchsia_emulator_step
from slave.step import fuchsia_unittest_step
from slave.step import gn_step
from slave.step import landmine_step
from slave.step import make_clean_step
from slave.step import ninja_step
from slave.step import shell_step
from slave.test import test_generator
BUILD_CONFIGS = {
'arm64_fuchsia': {
'architecture': 'arm64',
'build_args_product': 'fuchsia_arm64_user',
'build_args_flavor': 'Release',
'build_target': 'chromecast/internal/fuchsia:all',
'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests',
'run_gtests': False,
'run_catatester': True,
'build_args': []
},
'arm64_fuchsia_eng': {
'architecture': 'arm64',
'build_args_product': 'fuchsia_arm64_eng',
'build_args_flavor': 'Eng',
'build_target': 'chromecast/internal/fuchsia:all',
'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests',
'run_gtests': False,
'build_args': []
},
'arm64_fuchsia_eng_optimized': {
'architecture': 'arm64',
'build_args_product': 'fuchsia_arm64_eng_optimized',
'build_args_flavor': 'EngOptimized',
'build_target': 'chromecast/internal/fuchsia:all',
'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests',
'run_gtests': False,
'build_args': []
},
'x64_fuchsia': {
'architecture': 'amd64',
'build_args_product': 'fuchsia_x64_user',
'build_args_flavor': 'Release',
'build_target': 'chromecast/internal/fuchsia:all',
'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests',
'run_gtests': True,
'build_args': ['dcheck_always_on=true']
},
'x64_fuchsia_eng': {
'architecture': 'amd64',
'build_args_product': 'fuchsia_x64_eng',
'build_args_flavor': 'Eng',
'build_target': 'chromecast/internal/fuchsia:all',
'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests',
'run_gtests': True,
'build_args': []
},
'x64_fuchsia_eng_optimized': {
'architecture': 'amd64',
'build_args_product': 'fuchsia_x64_eng_optimized',
'build_args_flavor': 'EngOptimized',
'build_target': 'chromecast/internal/fuchsia:all',
'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests',
'run_gtests': True,
'build_args': []
},
}
SHORTLIVED_BRANCH_PATTERN = (
r'(?P<major>\d+)\.(?P<minor>\d+)_shortlived_(?P<build>\d+)')
CIPD_UPLOADS_FILE_NAME = 'cipd_uploads'
def GetValidBuildNames():
return list(BUILD_CONFIGS.keys())
def CreateRecipe(build_name: str, **kwargs):
"""Builds a recipe object."""
config = BUILD_CONFIGS[build_name]
return FuchsiaRecipe(config, **kwargs)
class FuchsiaRecipe(base_recipe.BaseRecipe):
"""Recipe to lint a repository."""
def __init__(self, config, **kwargs):
base_recipe.BaseRecipe.__init__(
self, enable_build_accelerator=True, **kwargs)
self._build_config = config
self._fuchsia_workdir = None
self._properties = kwargs.get('properties', {})
def get_fuchsia_bucket(self, chromium_root):
"""Get the current Fuchsia bucket to get artifacts from.
Usually, this will pull artifacts from either the public or private Fuchsia
SDK buckets. For go/feureka-dd builds, it will pull from a temporary bucket.
Args:
chromium_root: Path to chromium source directory.
Returns:
GCP bucket. For example: 'fuchsia-sdk' or 'fuchsia'.
"""
bucket_path = os.path.join(chromium_root, 'build/fuchsia/sdk-bucket.txt')
bucket = 'fuchsia'
# Only go/feureka-dd writes to the bucket file
with open(bucket_path) as f:
# Trim any whitespace on each line
bucket = f.readline().rstrip()
return bucket or 'fuchsia'
def get_num_jobs(self): # pylint:disable=method-hidden
"""Count of jobs to use."""
setup_steps = self.get_setup_steps()
return setup_steps[0].get_num_jobs(multiplier=10)
def create_temp_directory(self):
return tempfile.TemporaryDirectory().name
def get_steps(self):
# Use one of the setup steps to get chromium root
cwd = os.getcwd()
setup_steps = self.get_setup_steps()
chromium_root = setup_steps[0].get_project_path('chromium/src')
gcs_dir = setup_steps[0].get_gcs_dir()
jobs = self.get_num_jobs()
architecture = self._build_config.get('architecture')
build_args_product = self._build_config.get('build_args_product')
build_args_flavor = self._build_config.get('build_args_flavor')
build_args = copy.deepcopy(self._build_config.get('build_args'))
if self.build_system == 'catabuilder':
build_args.append('is_official_build=true')
build_target = self._build_config.get('build_target')
test_target = self._build_config.get('test_target')
run_gtests = self._build_config.get('run_gtests')
run_catatester = self._build_config.get('run_catatester', False)
post_submit_upload = self.build_system == 'catabuilder'
self._fuchsia_workdir = self.create_temp_directory()
# Extend buildargs with incremental build id
incremental_build_prop = ('cast_build_incremental="{}"'.format(
self.build_number))
build_args.append(incremental_build_prop)
out_dir = os.path.join(chromium_root, 'out_{}'.format(build_args_product),
build_args_flavor)
steps = []
if self.build_system == 'catabuilder':
steps.append(make_clean_step.MakeCleanStep(**self._step_kwargs))
else:
steps += [
landmine_step.LandmineStep(**self._step_kwargs),
]
# Generate gn gen step
gn_gen_step = gn_step.GnGenStep(
build_args_product=build_args_product,
build_args=build_args,
out_dir=out_dir,
halt_on_failure=True,
cwd=cwd,
**self._step_kwargs)
steps.append(gn_gen_step)
# Generate gn args step
gn_args_step = gn_step.GnArgsStep(
out_dir=out_dir, cwd=cwd, halt_on_failure=True, **self._step_kwargs)
steps.append(gn_args_step)
# Generate ninja build step
ninja_build_step = ninja_step.NinjaStep(
out_dir=out_dir,
target=build_target,
cwd=cwd,
jobs=jobs,
halt_on_failure=True,
**self._step_kwargs)
steps.append(ninja_build_step)
# Generate ninja build tests step
max_timeout_secs = 4 * 60 * 60
ninja_build_tests_step = ninja_step.NinjaStep(
out_dir=out_dir,
target=test_target,
halt_on_failure=True,
timeout_secs=max_timeout_secs,
cwd=cwd,
jobs=jobs,
**self._step_kwargs)
steps.append(ninja_build_tests_step)
if run_gtests:
bucket = self.get_fuchsia_bucket(chromium_root)
# Start FEMU
femu_start_step = fuchsia_emulator_step.FuchsiaEmulatorStartStep(
bucket=bucket,
chromium_root=chromium_root,
out_dir=out_dir,
fuchsia_workdir=self._fuchsia_workdir,
**self._step_kwargs)
steps.append(femu_start_step)
step = fuchsia_unittest_step.FuchsiaUnitTestStep(
out_dir=out_dir,
recipe_steps=steps,
cwd=cwd,
**self._step_kwargs)
steps.append(step)
# Upload the artifacts to CIPD
refs = {self._manifest_branch}
tags = {
'version': self.build_number,
}
far_pkg_vars = {
'targetarch': architecture
}
cipd_uploads_file = os.path.join(out_dir, 'gen', CIPD_UPLOADS_FILE_NAME)
cipd_yaml_dir = chromium_root
steps.append(fuchsia_cipd_upload_step.FuchsiaCIPDUploadStep(
steps, cipd_uploads_file, cipd_yaml_dir,
refs=refs,
tags=tags,
pkg_vars=far_pkg_vars,
**self._step_kwargs))
# Package gunit test dependencies and upload to gcs
# only if recipe is running from Catabuilder.
if post_submit_upload and run_catatester:
max_timeout_secs = 30 * 60
ninja_test_deps_archive_step = ninja_step.NinjaStep(
out_dir=out_dir,
target='chromecast_test_deps_archive',
halt_on_failure=True,
timeout_secs=max_timeout_secs,
cwd=cwd,
jobs=jobs,
**self._step_kwargs)
steps.append(ninja_test_deps_archive_step)
src_path = os.path.join(out_dir, 'test_deps.tar.gz')
dst_path = os.path.join(gcs_dir, 'artifacts', 'tests')
copy_deps_steps = [
shell_step.ShellStep(
name='Create test deps destination folder',
command=[
'mkdir',
'-p',
dst_path,
],
directory=os.getcwd(),
**self._step_kwargs),
shell_step.ShellStep(
name='Move test_deps.tar.gz to upload folder',
command=['mv', src_path, dst_path],
directory=os.getcwd(),
**self._step_kwargs)
]
steps.extend(copy_deps_steps)
return steps
def get_teardown_steps(self):
"""Returns a list of all steps that should be executed as part of teardown.
Teardown steps are always called, even if previous steps fail.
Returns:
List of slave.base_step.BaseStep commands to be executed.
"""
return [
fuchsia_emulator_step.FuchsiaEmulatorTeardownStep(**self._step_kwargs)
] + super().get_teardown_steps()