blob: 610d9707a9becb75e29b31d297f47f0f9e825244 [file] [log] [blame]
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from PB.go.chromium.org.luci.buildbucket.proto.common import FAILURE, SUCCESS
from PB.recipe_engine.result import RawResult
DEPS = [
'depot_tools/bot_update',
'depot_tools/depot_tools',
'depot_tools/gclient',
'depot_tools/osx_sdk',
'recipe_engine/buildbucket',
'recipe_engine/context',
'recipe_engine/defer',
'recipe_engine/file',
'recipe_engine/json',
'recipe_engine/path',
'recipe_engine/platform',
'recipe_engine/properties',
'recipe_engine/resultdb',
'recipe_engine/runtime',
'recipe_engine/step',
'infra_checkout',
'infra_cipd',
]
# Mapping from a builder name to a list of CIPD platforms it should build
# packages for.
#
# See https://pkg.go.dev/go.chromium.org/luci/cipd/client/cipd/ensure for the
# list of supported CIPD platforms.
#
# Additionally, a value may have a sequence of options appended to it,
# separated by colons. e.g. 'VALUE:option:option'. Currently the supported
# options are:
# * 'test' - Run CIPD package tests. By default no package tests are run.
# * 'legacy' - Switch the builder that builds this variant to use go "legacy"
# Go version instead of the "bleeding_edge" version. This was primarily
# needed by builders targeting OSX amd64 that need to produce binaries that
# can run on OSX 10.10 and OSX 10.11. What exact versions correspond to
# "legacy" and "bleeding_edge" is defined in bootstrap.py in infra.git. Note
# that this option applies to the entire builder (not only the individual
# CIPD platforms).
#
# If the builder is not in this set, or the list of CIPD platforms for it is
# empty, it won't be used for building CIPD packages.
#
# Only builders named '*-packager-*' builders will actually upload CIPD
# packages, while '*-continuous-*' builders merely verify that CIPD packages can
# be built.
#
# Note this is a **subset** of builders that use infra_continuous recipe. Other
# builders not mentioned here just don't build CIPD packages at all (they just
# run post-submit tests).
#
# TODO(iannucci): make packager role explicit with `package=cipd_prefix` option.
# TODO(iannucci): remove this dict and put this all configuration as explicit
# property inputs to the recipe :)
CIPD_PACKAGE_BUILDERS = {
# infra-continuous-* builders just build infra.git CIPD packages without
# uploading them anywhere. They run immediately after CL lands and just
# confirm all CIPD package YAMLs are valid, cross-compilation works, etc.
# Variants with ":test" also run post-packaging tests. This ":test" has
# nothing to do with regular post-submit tests: continuous builders always
# run them.
'infra-continuous-jammy-64': [
'linux-amd64:test',
'linux-arm64',
],
'infra-continuous-win10-64': [
'windows-386',
'windows-amd64:test',
'windows-arm64',
],
'infra-continuous-mac': ['mac-amd64',],
# infra-internal-continuous-* just build infra_internal.git packages without
# uploading them. The same deal as infra-continuous-*, but for the internal
# repo.
'infra-internal-continuous-linux-64': [
'linux-amd64:test',
'linux-arm64',
],
'infra-internal-continuous-win-64': [
'windows-386',
'windows-amd64:test',
'windows-arm64',
],
'infra-internal-continuous-mac-12-64': ['mac-amd64:test',],
# infra-packager-* builders build and upload infra.git production CIPD
# packages. They do not run any tests. 'xc' stands for "cross-compilation".
# Various CIPD platforms are spread across multiple builders in effort to
# balance the load across them (to make them all finish at approximately the
# same time).
'infra-packager-linux-64': ['linux-amd64',],
'infra-packager-linux-xc1': [
'dragonfly-amd64',
'freebsd-386',
'freebsd-amd64',
'freebsd-arm64',
'freebsd-armv7l',
'freebsd-riscv64',
'illumos-amd64',
'linux-386',
'linux-arm64',
'linux-armv6l',
'openbsd-386',
'openbsd-amd64',
'openbsd-arm64',
'openbsd-armv7l',
'openbsd-ppc64',
'openbsd-riscv64',
'solaris-amd64',
],
'infra-packager-linux-xc2': [
'aix-ppc64',
'linux-loong64',
'linux-mips',
'linux-mips64',
'linux-mips64le',
'linux-mipsle',
'linux-ppc64',
'linux-ppc64le',
'linux-riscv64',
'linux-s390x',
'netbsd-386',
'netbsd-amd64',
'netbsd-arm64',
'netbsd-armv7l',
],
'infra-packager-win-64': [
'windows-386',
'windows-amd64',
'windows-arm64',
],
# NOTE: Mac packages need to be codesigned and so can ONLY be packaged
# on Mac.
'infra-packager-mac-64': ['mac-amd64',],
'infra-packager-mac-arm64': ['mac-arm64',],
# infra-internal-packager-* builders build and upload infra_internal.git
# production CIPD packages. The same deal as infra-packager-*, but for the
# internal repo.
'infra-internal-packager-linux-64': [
'linux-amd64',
'linux-arm64',
'linux-armv6l',
],
'infra-internal-packager-win-64': [
'windows-386',
'windows-amd64',
'windows-arm64',
],
# NOTE: Mac packages need to be codesigned and so can ONLY be packaged
# on Mac.
'infra-internal-packager-mac-64': ['mac-amd64',],
'infra-internal-packager-mac-arm64': ['mac-arm64',],
# Temporary experimental builders to test new VMs. Copies of corresponding
# non-exp builders.
'infra-packager-linux-64-exp': ['linux-amd64',],
'infra-packager-win-64-exp': [
'windows-386',
'windows-amd64',
'windows-arm64',
],
}
INFRA_INTERNAL_REPO = 'https://chrome-internal.googlesource.com/infra/infra_internal'
INFRA_REPO = 'https://chromium.googlesource.com/infra/infra'
def should_run_python_tests(api, builder_name):
# Do not run python tests on packager builders, since most of them are
# irrelevant to the produced packages. Relevant portion of tests will be run
# from api.infra_cipd.test() below, when testing packages that pack python
# code.
return api.platform.arch != 'arm' and 'packager' not in builder_name
def RunSteps(api):
buildername: str = api.buildbucket.builder_name
if buildername.startswith((
'infra-internal-continuous',
'infra-internal-packager',
)):
project_name = 'infra_internal'
repo_url = INFRA_INTERNAL_REPO
gclient_config = 'infra_internal'
elif buildername.startswith((
'infra-continuous',
'infra-packager',
)):
project_name = 'infra'
repo_url = INFRA_REPO
gclient_config = 'infra'
else: # pragma: no cover
raise ValueError(
'This recipe is not intended for builder %s. ' % buildername)
# Use the latest bleeding edge version of Go unless asked for the legacy one.
go_version_variant = 'bleeding_edge'
for variant in CIPD_PACKAGE_BUILDERS.get(buildername, []):
if 'legacy' in variant.split(':'): # pragma: no cover
go_version_variant = 'legacy'
break
internal = project_name == 'infra_internal'
co = api.infra_checkout.checkout(
gclient_config_name=gclient_config,
internal=internal,
go_version_variant=go_version_variant)
co.gclient_runhooks()
# Whatever is checked out by bot_update. It is usually equal to
# api.buildbucket.gitiles_commit.id except when the build was triggered
# manually (commit id is empty in that case).
rev = co.bot_update_step.properties['got_revision']
return build_main(api, co, buildername, project_name, repo_url, rev)
def build_main(api, checkout, buildername, project_name, repo_url, rev):
is_packager = 'packager' in buildername
if should_run_python_tests(api, buildername):
run_python_tests(api, checkout, project_name)
# Some third_party go packages on OSX rely on cgo and thus a configured
# clang toolchain.
with api.osx_sdk('mac'), checkout.go_env():
if not is_packager:
with api.depot_tools.on_path():
# Some go tests test interactions with depot_tools binaries, so put
# depot_tools on the path.
api.step(
'infra go tests',
api.resultdb.wrap([
'vpython3', '-u',
checkout.path / project_name / 'go' / 'test.py'
],
module_name='infra/%s > //go:go_tests' %
(project_name),
module_scheme='go',
base_variant={'platform': api.platform.name},
include=True))
fails = []
for plat in sort_variants(CIPD_PACKAGE_BUILDERS.get(buildername, [])):
options = plat.split(':')
plat = options.pop(0)
# Mac packages can only be produced by a mac builder.
if plat.startswith('mac-') and is_packager and not api.platform.is_mac:
api.step.empty(
'Invalid package configuration',
status=api.step.EXCEPTION,
step_text=(
'Mac packages require codesign and can not run on %s.'
% (api.platform.name,)
),
)
try:
# TODO(vadimsh): Upload packages asynchronously in parallel. When
# building for multiple platforms it should be possible to build stuff
# and upload stuff in parallel, since these activities do not interfere
# with one another (unlike e.g. building stuff for multiple platforms in
# parallel).
with api.infra_cipd.context(checkout.path / project_name, plat):
if api.platform.is_mac:
api.infra_cipd.build(api.properties.get('signing_identity'))
else:
api.infra_cipd.build()
if 'test' in options:
api.infra_cipd.test()
if is_packager:
if api.runtime.is_experimental or buildername.endswith('-exp'):
api.step('no CIPD package upload in experimental mode', cmd=None)
else:
api.infra_cipd.upload(api.infra_cipd.tags(repo_url, rev))
except api.step.StepFailure:
fails.append(plat)
status = SUCCESS
summary = []
if fails:
status = FAILURE
summary.append('Failed to build some CIPD packages for platform(s):')
summary.extend(' * %s' % f for f in fails)
return RawResult(status=status, summary_markdown='\n'.join(summary))
def sort_variants(p):
"""Sorts a list of CIPD build variants by "most interesting first".
So that we don't spend time waiting for some exotic platform to build first
before we discover that e.g. amd64 is broken.
"""
def score(variant):
options = variant.split(':')
plat = options.pop(0)
score = 0
if plat.startswith(('linux-', 'windows-', 'mac-')):
score += 500
if plat.endswith('-amd64'):
score += 100
if plat.endswith('-arm64'):
score += 50
if 'test' in options:
score += 1000
return score
return sorted(p, key=score, reverse=True)
def run_python_tests(api, checkout, project_name):
deferred = []
with api.context(cwd=checkout.path / project_name):
# Run Linux tests everywhere, Windows tests only on public CI.
if api.platform.is_linux or project_name == 'infra':
deferred.append(
api.defer(api.step, 'infra python tests',
['vpython3', 'test.py', 'test']))
if project_name == 'infra':
# The infra project runs py3 tests separately.
deferred.append(
api.defer(api.step, 'infra python tests (py3)',
['vpython3', 'test.py', 'test', '--py3']))
if ((api.platform.is_linux or api.platform.is_mac) and
project_name == 'infra'):
for app in ['predator', 'findit']:
cwd = checkout.path / project_name / 'appengine' / app
if app == 'predator':
cwd = cwd / 'app'
with api.context(cwd=cwd):
deferred.append(
api.defer(api.step, '%s python tests' % app,
['vpython3', 'test.py']))
# Validate ccompute configs.
if api.platform.is_linux and project_name == 'infra_internal':
ccompute_config = checkout.path.joinpath(project_name, 'ccompute',
'scripts', 'ccompute_config.py')
deferred.append(
api.defer(api.step, 'ccompute config test',
['python3', ccompute_config, 'test']))
api.defer.collect(deferred)
def GenTests(api):
# This allows us to test potential misconfigurations. As long as this runs
# before the yield statement for the test that needs it, it will be added to
# the module global by the time the test runs.
#
# We put it here so that ALL tests have a consistent view of
# CIPD_PACKAGE_BUILDERS.
CIPD_PACKAGE_BUILDERS['infra-packager-TEST-linux-xcMac'] = [
'mac-arm64',
]
def test(name,
builder,
repo,
project,
bucket,
plat,
is_experimental=False,
arch='intel',
status='SUCCESS'):
return (api.test(name, status=status) + api.platform(plat, 64, arch) +
api.runtime(is_experimental=is_experimental) +
api.buildbucket.ci_build(
project, bucket, builder, git_repo=repo, build_number=123))
yield test('public-ci-linux', 'infra-continuous-bionic-64', INFRA_REPO,
'infra', 'ci', 'linux')
yield test(
'public-ci-linux-arm64',
'infra-continuous-bionic-64',
INFRA_REPO,
'infra',
'ci',
'linux',
arch='arm')
yield test('public-ci-win', 'infra-continuous-win10-64', INFRA_REPO, 'infra',
'ci', 'win')
yield test('internal-ci-linux', 'infra-internal-continuous-bionic-64',
INFRA_INTERNAL_REPO, 'infra-internal', 'ci', 'linux')
yield test('internal-ci-mac', 'infra-internal-continuous-mac-12-64',
INFRA_INTERNAL_REPO, 'infra-internal', 'ci', 'mac')
yield test('public-packager-mac', 'infra-packager-mac-64', INFRA_REPO,
'infra', 'prod', 'mac')
yield test(
'public-packager-mac_experimental',
'infra-packager-mac-64',
INFRA_REPO,
'infra',
'prod',
'mac',
is_experimental=True)
yield test('public-packager-mac_codesign', 'infra-packager-mac-64',
INFRA_REPO, 'infra', 'prod', 'mac') + api.properties(
signing_identity='AAAAAAAAAAAAABBBBBBBBBBBBBXXXXXXXXXXXXXX')
yield test('public-packager-mac-arm64_codesign', 'infra-packager-mac-arm64',
INFRA_REPO, 'infra', 'prod', 'mac') + api.properties(
signing_identity='AAAAAAAAAAAAABBBBBBBBBBBBBXXXXXXXXXXXXXX')
yield test('public-packager-win', 'infra-packager-win-64', INFRA_REPO,
'infra', 'prod', 'win')
yield test('internal-packager-linux', 'infra-internal-packager-linux-64',
INFRA_INTERNAL_REPO, 'infra-internal', 'prod', 'linux')
yield test('internal-packager-mac-arm64_codesign',
'infra-internal-packager-mac-arm64', INFRA_INTERNAL_REPO,
'infra_internal', 'prod', 'mac') + api.properties(
signing_identity='AAAAAAAAAAAAABBBBBBBBBBBBBXXXXXXXXXXXXXX')
yield (
test('packager-cipd-fail', 'infra-packager-linux-xc1', INFRA_REPO,
'infra', 'prod', 'linux', status='FAILURE') +
api.step_data('cipd linux-armv6l: build', retcode=1))
yield test('cross-packager-mac-fail', 'infra-packager-TEST-linux-xcMac',
INFRA_REPO, 'infra', 'prod', 'linux', status='INFRA_FAILURE')