| # 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 |