| # 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', |
| 'recipe_engine/buildbucket', |
| 'recipe_engine/json', |
| 'recipe_engine/properties', |
| 'recipe_engine/raw_io', |
| 'recipe_engine/step', |
| 'recipe_engine/swarming', |
| ] |
| |
| PROPERTIES = { |
| 'toolchain_builders': |
| Property( |
| kind=List(basestring), |
| help='List of toolchain builders to trigger', |
| default=[]), |
| 'goma_builders': |
| Property( |
| kind=List(basestring), |
| help='List of goma toolchain builders to trigger', |
| default=[]), |
| 'package': |
| Property(kind=str, help='CIPD path of toolchain package', default=None), |
| 'toolchain': |
| Property(kind=str, help='toolchain name', 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), |
| } |
| |
| |
| def RunSteps(api, toolchain_builders, goma_builders, package, toolchain, |
| interval, timeout): |
| # Trigger the CI build. |
| ci_build_results = api.buildbucket.run( |
| [ |
| api.buildbucket.schedule_request( |
| builder, bucket='ci', swarming_parent_run_id=api.swarming.task_id) |
| for builder in toolchain_builders |
| ], |
| collect_interval=interval, |
| timeout=timeout, |
| step_name='schedule ci builders', |
| ) |
| for result in ci_build_results: |
| if result.status != common_pb2.SUCCESS: |
| raise api.step.StepFailure('toolchain ci task(s) failed') |
| # Trigger the PROD build. |
| prod_build_results = api.buildbucket.run( |
| [ |
| api.buildbucket.schedule_request( |
| builder, |
| bucket='prod', |
| swarming_parent_run_id=api.swarming.task_id) |
| for builder in toolchain_builders |
| ], |
| collect_interval=interval, |
| timeout=timeout, |
| step_name='schedule prod builders', |
| ) |
| for result in prod_build_results: |
| if result.status != common_pb2.SUCCESS: |
| raise api.step.StepFailure('toolchain prod task(s) failed') |
| # Trigger goma builder. |
| revision = '' |
| for result in prod_build_results: |
| output = result.output.properties |
| if 'git_revision' in output: |
| if not revision: |
| revision = output['git_revision'] |
| else: |
| if revision != output['git_revision']: |
| raise api.step.StepFailure( |
| '%s revision not unified, %s:%s' % |
| (toolchain, revision, output['git_revision'])) |
| if not revision: |
| api.step('git_revision output property not set', None) |
| return |
| goma_properties = { |
| 'package': package, |
| 'toolchain': toolchain, |
| 'project': 'fuchsia-toolchain-images-gcr', |
| 'version': 'git_revision:' + revision, |
| } |
| goma_results = api.buildbucket.run( |
| [ |
| api.buildbucket.schedule_request( |
| # TODO(haowei): toolchain bots are currently in ci, |
| # change it to prod in the future. |
| builder, |
| bucket='ci', |
| properties=goma_properties, |
| swarming_parent_run_id=api.swarming.task_id) |
| for builder in goma_builders |
| ], |
| collect_interval=interval, |
| timeout=timeout, |
| step_name='schedule goma builders', |
| ) |
| for result in goma_results: |
| if result.status != common_pb2.SUCCESS: |
| raise api.step.StepFailure('goma task(s) failed') |
| |
| |
| def GenTests(api): |
| default_properties = api.properties( |
| toolchain_builders=["clang-linux-x64", "clang-mac-x64"], |
| goma_builders=["clang-goma"], |
| package='fuchsia/third_party/clang', |
| toolchain='clang') |
| yield (api.test('default') + api.buildbucket.ci_build( |
| bucket='ci', |
| git_repo='https://fuchsia.googlesource.com/example', |
| revision='a' * 40, |
| )) |
| |
| ci_build = api.buildbucket.ci_build_message(status='SUCCESS') |
| mock_ci_schedule_data = api.buildbucket.simulated_schedule_output( |
| step_name='schedule ci builders.schedule', |
| batch_response=rpc_pb2.BatchResponse( |
| responses=[dict(schedule_build=dict(id=ci_build.id))],)) |
| mock_ci_collect_data = api.buildbucket.simulated_collect_output( |
| step_name='schedule ci builders.collect', |
| builds=[ci_build], |
| ) |
| |
| ci_build_failure = api.buildbucket.ci_build_message(status='FAILURE') |
| mock_ci_failure_schedule_data = api.buildbucket.simulated_schedule_output( |
| step_name='schedule ci builders.schedule', |
| batch_response=rpc_pb2.BatchResponse( |
| responses=[dict(schedule_build=dict(id=ci_build_failure.id))],)) |
| mock_ci_failure_collect_data = api.buildbucket.simulated_collect_output( |
| step_name='schedule ci builders.collect', |
| builds=[ci_build_failure], |
| ) |
| |
| prod_build = api.buildbucket.ci_build_message( |
| build_id=ci_build.id + 1, status='SUCCESS') |
| prod_build.output.properties['git_revision'] = 'a' * 40 |
| mock_prod_schedule_data = api.buildbucket.simulated_schedule_output( |
| step_name='schedule prod builders.schedule', |
| batch_response=rpc_pb2.BatchResponse( |
| responses=[dict(schedule_build=dict(id=prod_build.id))],)) |
| mock_prod_collect_data = api.buildbucket.simulated_collect_output( |
| step_name='schedule prod builders.collect', |
| builds=[prod_build], |
| ) |
| |
| prod_build_failure = api.buildbucket.ci_build_message( |
| build_id=ci_build.id + 1, status='FAILURE') |
| mock_prod_failure_schedule_data = api.buildbucket.simulated_schedule_output( |
| step_name='schedule prod builders.schedule', |
| batch_response=rpc_pb2.BatchResponse( |
| responses=[dict(schedule_build=dict(id=prod_build_failure.id))],)) |
| mock_prod_failure_collect_data = api.buildbucket.simulated_collect_output( |
| step_name='schedule prod builders.collect', |
| builds=[prod_build_failure], |
| ) |
| |
| goma_build_failure = api.buildbucket.ci_build_message(status='FAILURE') |
| mock_goma_failure_schedule_data = api.buildbucket.simulated_schedule_output( |
| step_name='schedule goma builders.schedule', |
| batch_response=rpc_pb2.BatchResponse( |
| responses=[dict(schedule_build=dict(id=goma_build_failure.id))],)) |
| mock_goma_failure_collect_data = api.buildbucket.simulated_collect_output( |
| step_name='schedule goma builders.collect', |
| builds=[goma_build_failure], |
| ) |
| |
| yield (api.test('default with goma') + api.buildbucket.ci_build( |
| bucket='ci', |
| git_repo='https://fuchsia.googlesource.com/example', |
| revision='a' * 40, |
| ) + default_properties + mock_ci_schedule_data + mock_ci_collect_data + |
| mock_prod_schedule_data + mock_prod_collect_data) |
| |
| yield (api.status_check.test('default with ci failure', status='failure') + |
| api.buildbucket.ci_build( |
| bucket='ci', |
| git_repo='https://fuchsia.googlesource.com/example', |
| revision='a' * 40, |
| ) + default_properties + mock_ci_failure_schedule_data + |
| mock_ci_failure_collect_data) |
| |
| yield (api.status_check.test('default with prod failure', status='failure') + |
| api.buildbucket.ci_build( |
| bucket='ci', |
| git_repo='https://fuchsia.googlesource.com/example', |
| revision='a' * 40, |
| ) + default_properties + mock_ci_schedule_data + mock_ci_collect_data + |
| mock_prod_failure_schedule_data + mock_prod_failure_collect_data) |
| |
| yield (api.status_check.test('default with goma failures', status='failure') + |
| api.buildbucket.ci_build( |
| bucket='ci', |
| git_repo='https://fuchsia.googlesource.com/example', |
| revision='a' * 40, |
| ) + default_properties + mock_ci_schedule_data + mock_ci_collect_data + |
| mock_prod_schedule_data + mock_prod_collect_data + |
| mock_goma_failure_schedule_data + mock_goma_failure_collect_data) |
| |
| prod_build_mismatch = api.buildbucket.ci_build_message( |
| build_id=prod_build.id + 1, status='SUCCESS') |
| prod_build_mismatch.output.properties['git_revision'] = 'b' * 40 |
| mock_schedule_data_mismatch = api.buildbucket.simulated_schedule_output( |
| step_name='schedule prod builders.schedule', |
| batch_response=rpc_pb2.BatchResponse( |
| responses=[ |
| dict(schedule_build=dict(id=prod_build.id)), |
| dict(schedule_build=dict(id=prod_build_mismatch.id)) |
| ],)) |
| mock_collect_data_mismatch = api.buildbucket.simulated_collect_output( |
| step_name='schedule prod builders.collect', |
| builds=[prod_build, prod_build_mismatch], |
| ) |
| yield (api.status_check.test( |
| 'default with revision mismatch', status='failure') + |
| api.buildbucket.ci_build( |
| bucket='ci', |
| git_repo='https://fuchsia.googlesource.com/example', |
| revision='a' * 40, |
| ) + default_properties + mock_ci_schedule_data + mock_ci_collect_data + |
| mock_schedule_data_mismatch + mock_collect_data_mismatch) |