blob: 08e457f5dca11cb1e9a156683b8d9a1a255ac252 [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 PB.go.chromium.org.luci.buildbucket.proto import (
builds_service as builds_service_pb2,
)
from PB.recipes.fuchsia.contrib.toolchain_trigger import InputProperties
DEPS = [
"fuchsia/buildbucket_util",
"recipe_engine/buildbucket",
"recipe_engine/properties",
"recipe_engine/scheduler",
"recipe_engine/step",
"recipe_engine/swarming",
]
PROPERTIES = InputProperties
def RunSteps(api, props):
# Trigger the builders.
builds = api.buildbucket.schedule(
[
api.buildbucket.schedule_request(
builder,
bucket=props.bucket,
swarming_parent_run_id=api.swarming.task_id,
)
for builder in props.builders
]
+ [
api.buildbucket.schedule_request(
builder,
bucket=props.bucket,
)
for builder in props.nonblocking_builders
],
step_name="schedule builds",
)
build_ids = [b.id for b in builds if b.builder.builder in props.builders]
build_dict = api.buildbucket.collect_builds(
build_ids,
interval=props.interval,
timeout=props.timeout,
step_name="collect builds",
)
build_results = [build_dict[id] for id in build_ids]
api.buildbucket_util.display_builds(
step_name="display builds", builds=build_results, raise_on_failure=True
)
properties = {}
if props.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=api.buildbucket.build.builder.project,
jobs=props.triggers,
)
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 GenTests(api):
default_properties = api.properties(
builders=["clang-linux-x64", "clang-mac-x64"],
nonblocking_builders=["clang-windows-x64"],
triggers=["clang-trigger"],
enforce_output=True,
)
test_build = api.buildbucket.ci_build_message(
status="SUCCESS", builder="clang-linux-x64"
)
test_build.output.properties["git_revision"] = "a" * 40
mock_schedule_data = api.buildbucket.simulated_schedule_output(
step_name="schedule builds",
batch_response=builds_service_pb2.BatchResponse(
responses=[
dict(
schedule_build=dict(
id=test_build.id,
builder=dict(builder=test_build.builder.builder),
)
)
],
),
)
mock_collect_data = api.buildbucket.simulated_collect_output(
step_name="collect builds",
builds=[test_build],
)
yield (
api.buildbucket_util.test("default", repo="example", revision="a" * 40)
) + default_properties + mock_schedule_data + mock_collect_data
test_build_mismatch = api.buildbucket.ci_build_message(
build_id=test_build.id + 1, status="SUCCESS", builder="clang-linux-x64"
)
test_build_mismatch.output.properties["git_revision"] = "b" * 40
mock_schedule_data_mismatch = api.buildbucket.simulated_schedule_output(
step_name="schedule builds",
batch_response=builds_service_pb2.BatchResponse(
responses=[
dict(
schedule_build=dict(
id=test_build.id,
builder=dict(builder=test_build.builder.builder),
)
),
dict(
schedule_build=dict(
id=test_build_mismatch.id,
builder=dict(builder=test_build_mismatch.builder.builder),
)
),
],
),
)
mock_collect_data_mismatch = api.buildbucket.simulated_collect_output(
step_name="collect builds",
builds=[test_build, test_build_mismatch],
)
yield (
api.buildbucket_util.test(
"mismatch", repo="example", revision="a" * 40, status="failure"
)
) + default_properties + mock_schedule_data_mismatch + mock_collect_data_mismatch
test_build_no_output = api.buildbucket.ci_build_message(
status="SUCCESS", builder="clang-linux-x64"
)
mock_schedule_data_no_output = api.buildbucket.simulated_schedule_output(
step_name="schedule builds",
batch_response=builds_service_pb2.BatchResponse(
responses=[
dict(
schedule_build=dict(
id=test_build_no_output.id,
builder=dict(builder=test_build.builder.builder),
)
)
],
),
)
mock_collect_data_no_output = api.buildbucket.simulated_collect_output(
step_name="collect builds",
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.buildbucket_util.test("no_output", repo="example", revision="a" * 40)
) + no_output_properties + mock_schedule_data_no_output + mock_collect_data_no_output
yield (
api.buildbucket_util.test(
"no_output_with_enforce",
repo="example",
revision="a" * 40,
status="failure",
)
) + default_properties + mock_schedule_data_no_output + mock_collect_data_no_output
test_build_failure = api.buildbucket.ci_build_message(
status="FAILURE", builder="clang-linux-x64"
)
mock_failure_schedule_data = api.buildbucket.simulated_schedule_output(
step_name="schedule builds",
batch_response=builds_service_pb2.BatchResponse(
responses=[
dict(
schedule_build=dict(
id=test_build_failure.id,
builder=dict(builder=test_build_failure.builder.builder),
)
)
],
),
)
mock_failure_collect_data = api.buildbucket.simulated_collect_output(
step_name="collect builds",
builds=[test_build_failure],
)
yield (
api.buildbucket_util.test(
"default_fail", repo="example", revision="a" * 40, status="failure"
)
) + default_properties + mock_failure_schedule_data + mock_failure_collect_data