blob: 263a336168351dd58d6b6786bca9b8407e9ffab8 [file] [log] [blame]
# Copyright 2020 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.
"""Recipe for triggering toolchain buildbucket builds."""
from recipe_engine.config import List
from recipe_engine.recipe_api import Property
from PB.go.chromium.org.luci.buildbucket.proto import rpc as rpc_pb2
from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2
DEPS = [
'fuchsia/status_check',
'fuchsia/buildbucket_util',
'recipe_engine/buildbucket',
'recipe_engine/json',
'recipe_engine/properties',
'recipe_engine/raw_io',
'recipe_engine/scheduler',
'recipe_engine/step',
'recipe_engine/swarming',
]
PROPERTIES = {
'builders':
Property(
kind=List(basestring),
help='List of toolchain builders to trigger',
default=[]),
'triggers':
Property(
kind=List(basestring),
help='List of triggers to trigger',
default=[]),
'bucket':
Property(kind=str, help='bucket for builders', default=None),
'interval':
Property(
kind=int, help='Delay between requests when waiting', default=None),
'timeout':
Property(
kind=int, help='Time to wait for the builds to end', default=None),
'enforce_output':
Property(
kind=bool,
help='enforce child build has revision output',
default=False),
}
def retrieve_revision(api, results):
revision = None
for result in results:
output = result.output.properties
if 'git_revision' not in output:
raise api.step.StepFailure('revision not found in build')
output_revision = output['git_revision']
if revision is None:
revision = output_revision
elif revision != output_revision:
raise api.step.StepFailure('revisions not unified: %s:%s' %
(revision, output_revision))
return revision
def RunSteps(api, builders, triggers, bucket, interval, timeout,
enforce_output):
# Trigger the builders.
build_results = api.buildbucket.run(
[
api.buildbucket.schedule_request(
builder,
bucket=bucket,
swarming_parent_run_id=api.swarming.task_id)
for builder in builders
],
collect_interval=interval,
timeout=timeout,
step_name='schedule builders',
)
api.buildbucket_util.display_builds(
step_name='display builds', builds=build_results, raise_on_failure=True)
properties = {}
if enforce_output:
revision = retrieve_revision(api, build_results)
properties = {'version': 'git_revision:' + revision}
# Trigger next stage builders
api.scheduler.emit_trigger(
api.scheduler.BuildbucketTrigger(properties=properties),
project='fuchsia',
jobs=triggers,
)
def GenTests(api):
default_properties = api.properties(
builders=['clang-linux-x64', 'clang-mac-x64'],
triggers=['clang-trigger'],
enforce_output=True)
test_build = api.buildbucket.ci_build_message(status='SUCCESS')
test_build.output.properties['git_revision'] = 'a' * 40
mock_schedule_data = api.buildbucket.simulated_schedule_output(
step_name='schedule builders.schedule',
batch_response=rpc_pb2.BatchResponse(
responses=[dict(schedule_build=dict(id=test_build.id))],))
mock_collect_data = api.buildbucket.simulated_collect_output(
step_name='schedule builders.collect',
builds=[test_build],
)
yield (api.test('default') + api.buildbucket.ci_build(
bucket='ci',
git_repo='https://fuchsia.googlesource.com/example',
revision='a' * 40,
)) + default_properties + mock_collect_data + mock_schedule_data
test_build_mismatch = api.buildbucket.ci_build_message(
build_id=test_build.id + 1, status='SUCCESS')
test_build_mismatch.output.properties['git_revision'] = 'b' * 40
mock_schedule_data_mismatch = api.buildbucket.simulated_schedule_output(
step_name='schedule builders.schedule',
batch_response=rpc_pb2.BatchResponse(
responses=[
dict(schedule_build=dict(id=test_build.id)),
dict(schedule_build=dict(id=test_build_mismatch.id))
],))
mock_collect_data_mismatch = api.buildbucket.simulated_collect_output(
step_name='schedule builders.collect',
builds=[test_build, test_build_mismatch],
)
yield (api.test('mismatch') + api.buildbucket.ci_build(
bucket='ci',
git_repo='https://fuchsia.googlesource.com/example',
revision='a' * 40,
)) + default_properties + mock_schedule_data_mismatch + mock_collect_data_mismatch
test_build_no_output = api.buildbucket.ci_build_message(status='SUCCESS')
mock_schedule_data_no_output = api.buildbucket.simulated_schedule_output(
step_name='schedule builders.schedule',
batch_response=rpc_pb2.BatchResponse(
responses=[dict(schedule_build=dict(id=test_build_no_output.id))],))
mock_collect_data_no_output = api.buildbucket.simulated_collect_output(
step_name='schedule builders.collect',
builds=[test_build_no_output],
)
no_output_properties = api.properties(
builders=['clang-linux-x64', 'clang-mac-x64'],
triggers=['clang-trigger'],
enforce_output=False)
yield (api.test('no_output') + api.buildbucket.ci_build(
bucket='ci',
git_repo='https://fuchsia.googlesource.com/example',
revision='a' * 40,
)) + no_output_properties + mock_schedule_data_no_output + mock_collect_data_no_output
yield (api.test('no_output_with_enforce') + api.buildbucket.ci_build(
bucket='ci',
git_repo='https://fuchsia.googlesource.com/example',
revision='a' * 40,
)) + default_properties + mock_schedule_data_no_output + mock_collect_data_no_output
test_build_failure = api.buildbucket.ci_build_message(status='FAILURE')
mock_failure_schedule_data = api.buildbucket.simulated_schedule_output(
step_name='schedule builders.schedule',
batch_response=rpc_pb2.BatchResponse(
responses=[dict(schedule_build=dict(id=test_build_failure.id))],))
mock_failure_collect_data = api.buildbucket.simulated_collect_output(
step_name='schedule builders.collect',
builds=[test_build_failure],
)
yield (
api.status_check.test('default fail', status='failure') +
api.buildbucket.ci_build(
bucket='ci',
git_repo='https://fuchsia.googlesource.com/example',
revision='a' * 40,
)
) + default_properties + mock_failure_schedule_data + mock_failure_collect_data