Add child_build_id property
This will be used when re-running tests to skip the sub-build and
go straight to testing.
See design doc:
https://docs.google.com/document/d/1Jv6rHFwvXdafzpQik-a9fiv3G6YGL9ata_FT8RezOXM/edit#heading=h.ypsbql4vhbwa
Bug: 39904
Change-Id: I86432ba5f9a405d92ee71cf8dd8c600b50213e8f
diff --git a/recipes/fuchsia/fuchsia.expected/successful_build_and_test_not_in_shards.json b/recipes/fuchsia/fuchsia.expected/child_build_provided__test_not_in_shards.json
similarity index 84%
rename from recipes/fuchsia/fuchsia.expected/successful_build_and_test_not_in_shards.json
rename to recipes/fuchsia/fuchsia.expected/child_build_provided__test_not_in_shards.json
index 14111b7..6b2c41b 100644
--- a/recipes/fuchsia/fuchsia.expected/successful_build_and_test_not_in_shards.json
+++ b/recipes/fuchsia/fuchsia.expected/child_build_provided__test_not_in_shards.json
@@ -146,6 +146,7 @@
"cmd": [],
"name": "build",
"~followup_annotations": [
+ "@@@STEP_TEXT@Reusing child build instead of triggering@@@",
"@@@STEP_LINK@builder-subbuild@https://ci.chromium.org/b/8945511751514863184@@@",
"@@@SET_BUILD_PROPERTY@integration-revision-count@1@@@"
]
@@ -158,106 +159,10 @@
"cr-buildbucket.appspot.com"
],
"infra_step": true,
- "name": "build.schedule",
- "stdin": "{\"requests\": [{\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"builder-subbuild\", \"project\": \"fuchsia\"}, \"experimental\": \"NO\", \"fields\": \"builder,createTime,createdBy,critical,endTime,id,input,number,output,startTime,status,updateTime\", \"gitilesCommit\": {\"host\": \"fuchsia.googlesource.com\", \"id\": \"2d72510e447ab60a9728aeea2362d8be2cbd7789\", \"project\": \"fuchsia\", \"ref\": \"refs/heads/master\"}, \"properties\": {\"$recipe_engine/source_manifest\": {\"debug_dir\": null}, \"gcs_bucket\": \"###fuchsia-build###\", \"manifest\": \"manifest/minimal\", \"packages\": [\"//bundles/buildbot:core\"], \"parent_id\": \"8945511751514863184\", \"project\": \"integration\", \"remote\": \"https://fuchsia.googlesource.com/integration\", \"spec_revision\": \"deadbeef\", \"target\": \"x64\"}, \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-000000001337\", \"swarming\": {\"parentRunId\": \"fake-task-id\"}, \"tags\": [{\"key\": \"user_agent\", \"value\": \"recipe\"}]}}]}",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@",
- "@@@STEP_LOG_LINE@json.output@{@@@",
- "@@@STEP_LOG_LINE@json.output@ \"responses\": [@@@",
- "@@@STEP_LOG_LINE@json.output@ {@@@",
- "@@@STEP_LOG_LINE@json.output@ \"scheduleBuild\": {@@@",
- "@@@STEP_LOG_LINE@json.output@ \"id\": \"8945511751514863184\"@@@",
- "@@@STEP_LOG_LINE@json.output@ }@@@",
- "@@@STEP_LOG_LINE@json.output@ }@@@",
- "@@@STEP_LOG_LINE@json.output@ ]@@@",
- "@@@STEP_LOG_LINE@json.output@}@@@",
- "@@@STEP_LOG_END@json.output@@@",
- "@@@STEP_LOG_LINE@request@{@@@",
- "@@@STEP_LOG_LINE@request@ \"requests\": [@@@",
- "@@@STEP_LOG_LINE@request@ {@@@",
- "@@@STEP_LOG_LINE@request@ \"scheduleBuild\": {@@@",
- "@@@STEP_LOG_LINE@request@ \"builder\": {@@@",
- "@@@STEP_LOG_LINE@request@ \"bucket\": \"ci\", @@@",
- "@@@STEP_LOG_LINE@request@ \"builder\": \"builder-subbuild\", @@@",
- "@@@STEP_LOG_LINE@request@ \"project\": \"fuchsia\"@@@",
- "@@@STEP_LOG_LINE@request@ }, @@@",
- "@@@STEP_LOG_LINE@request@ \"experimental\": \"NO\", @@@",
- "@@@STEP_LOG_LINE@request@ \"fields\": \"builder,createTime,createdBy,critical,endTime,id,input,number,output,startTime,status,updateTime\", @@@",
- "@@@STEP_LOG_LINE@request@ \"gitilesCommit\": {@@@",
- "@@@STEP_LOG_LINE@request@ \"host\": \"fuchsia.googlesource.com\", @@@",
- "@@@STEP_LOG_LINE@request@ \"id\": \"2d72510e447ab60a9728aeea2362d8be2cbd7789\", @@@",
- "@@@STEP_LOG_LINE@request@ \"project\": \"fuchsia\", @@@",
- "@@@STEP_LOG_LINE@request@ \"ref\": \"refs/heads/master\"@@@",
- "@@@STEP_LOG_LINE@request@ }, @@@",
- "@@@STEP_LOG_LINE@request@ \"properties\": {@@@",
- "@@@STEP_LOG_LINE@request@ \"$recipe_engine/source_manifest\": {@@@",
- "@@@STEP_LOG_LINE@request@ \"debug_dir\": null@@@",
- "@@@STEP_LOG_LINE@request@ }, @@@",
- "@@@STEP_LOG_LINE@request@ \"gcs_bucket\": \"###fuchsia-build###\", @@@",
- "@@@STEP_LOG_LINE@request@ \"manifest\": \"manifest/minimal\", @@@",
- "@@@STEP_LOG_LINE@request@ \"packages\": [@@@",
- "@@@STEP_LOG_LINE@request@ \"//bundles/buildbot:core\"@@@",
- "@@@STEP_LOG_LINE@request@ ], @@@",
- "@@@STEP_LOG_LINE@request@ \"parent_id\": \"8945511751514863184\", @@@",
- "@@@STEP_LOG_LINE@request@ \"project\": \"integration\", @@@",
- "@@@STEP_LOG_LINE@request@ \"remote\": \"https://fuchsia.googlesource.com/integration\", @@@",
- "@@@STEP_LOG_LINE@request@ \"spec_revision\": \"deadbeef\", @@@",
- "@@@STEP_LOG_LINE@request@ \"target\": \"x64\"@@@",
- "@@@STEP_LOG_LINE@request@ }, @@@",
- "@@@STEP_LOG_LINE@request@ \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-000000001337\", @@@",
- "@@@STEP_LOG_LINE@request@ \"swarming\": {@@@",
- "@@@STEP_LOG_LINE@request@ \"parentRunId\": \"fake-task-id\"@@@",
- "@@@STEP_LOG_LINE@request@ }, @@@",
- "@@@STEP_LOG_LINE@request@ \"tags\": [@@@",
- "@@@STEP_LOG_LINE@request@ {@@@",
- "@@@STEP_LOG_LINE@request@ \"key\": \"user_agent\", @@@",
- "@@@STEP_LOG_LINE@request@ \"value\": \"recipe\"@@@",
- "@@@STEP_LOG_LINE@request@ }@@@",
- "@@@STEP_LOG_LINE@request@ ]@@@",
- "@@@STEP_LOG_LINE@request@ }@@@",
- "@@@STEP_LOG_LINE@request@ }@@@",
- "@@@STEP_LOG_LINE@request@ ]@@@",
- "@@@STEP_LOG_LINE@request@}@@@",
- "@@@STEP_LOG_END@request@@@",
- "@@@STEP_LINK@8945511751514863184@https://cr-buildbucket.appspot.com/build/8945511751514863184@@@"
- ]
- },
- {
- "cmd": [],
- "name": "build.collect",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "bb",
- "collect",
- "-host",
- "cr-buildbucket.appspot.com",
- "-interval",
- "60s",
- "8945511751514863184"
- ],
- "infra_step": true,
- "name": "build.collect.wait",
- "timeout": 86400,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "bb",
- "batch",
- "-host",
- "cr-buildbucket.appspot.com"
- ],
- "infra_step": true,
- "name": "build.collect.get",
+ "name": "build.buildbucket.get",
"stdin": "{\"requests\": [{\"getBuild\": {\"fields\": \"builder,createTime,createdBy,critical,endTime,id,input,number,output,startTime,status,updateTime\", \"id\": \"8945511751514863184\"}}]}",
"~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_NEST_LEVEL@1@@@",
"@@@STEP_LOG_LINE@json.output@{@@@",
"@@@STEP_LOG_LINE@json.output@ \"responses\": [@@@",
"@@@STEP_LOG_LINE@json.output@ {@@@",
diff --git a/recipes/fuchsia/fuchsia.py b/recipes/fuchsia/fuchsia.py
index 08877fe..6aa9fc5 100644
--- a/recipes/fuchsia/fuchsia.py
+++ b/recipes/fuchsia/fuchsia.py
@@ -62,6 +62,12 @@
]
PROPERTIES = {
+ 'child_build_id':
+ Property(
+ kind=long,
+ help=('The buildbucket ID of the child build. If set, '
+ 'will use this build instead of launching a new one.'),
+ default=None),
'spec_remote':
Property(
kind=str,
@@ -70,7 +76,7 @@
}
-def RunSteps(api, spec_remote):
+def RunSteps(api, child_build_id, spec_remote):
# Resolve the build input to always contain a Gitiles commit.
api.build_input_resolver.resolve(
default_project_url='https://fuchsia.googlesource.com/fuchsia')
@@ -98,8 +104,8 @@
'if not running tests, use the fuchsia/build recipe directly')
with api.step.nest('build') as presentation:
- child_build = run_build_steps(api, presentation, spec_revision,
- orchestrator_id)
+ child_build = run_build_steps(api, presentation, child_build_id,
+ spec_revision, orchestrator_id)
child_props = json_format.MessageToDict(child_build.output.properties)
orchestration_inputs = collect_test_orchestration_inputs(api, child_props)
# Copy to our own properties so the results uploader in google3 can find
@@ -115,42 +121,49 @@
run_test_steps(api, orchestration_inputs, spec)
-def run_build_steps(api, presentation, spec_revision, orchestrator_id):
- parent_properties = api.properties.thaw()
- # These are reserved by kitchen and swarming. See
- # https://chromium.googlesource.com/infra/infra/+/2c2389a00fcdb93d90a628f941814f2abd34428e/go/src/infra/tools/kitchen/cook.go#266
- # and https://chromium.googlesource.com/infra/infra/+/7fcd559afa7a866a5ad039019e6ef6a91922e09c/appengine/cr-buildbucket/validation.py#36.
- # We also should not override the 'recipe' of the child builder.
- reject_keys = {
- '$recipe_engine/path', '$recipe_engine/step', 'bot_id', 'path_config',
- 'buildbucket', '$recipe_engine/buildbucket', 'buildername', 'branch',
- 'repository', '$recipe_engine/runtime', 'recipe'
- }
- properties = {
- key: val
- for key, val in parent_properties.items()
- if key and key not in reject_keys
- }
- properties.update({
- 'spec_revision': spec_revision,
- 'parent_id': orchestrator_id,
- })
+def run_build_steps(api, presentation, child_build_id, spec_revision,
+ orchestrator_id):
builder_name = '{}-subbuild'.format(api.buildbucket.build.builder.builder)
- # If this task was launched by led, we launch the child with led as well.
- # This lets us ensure that the parent and child use the same version of
- # the recipes code. That is a requirement for testing this recipe, as well as
- # for avoiding the need to do soft transitions when updating the interface
- # between the parent and child recipes.
- if api.led.launched_by_led:
- output_build, build_url = build_with_led(api, builder_name, properties,
- presentation)
+ if child_build_id:
+ # Text is meant to avoid confusion.
+ presentation.step_text = 'Reusing child build instead of triggering'
+ output_build = api.buildbucket.get(child_build_id)
+ build_url = 'https://ci.chromium.org/b/%d' % child_build_id
else:
- output_build, build_url = build_with_buildbucket(api, builder_name,
- properties)
+ parent_properties = api.properties.thaw()
+ # These are reserved by kitchen and swarming. See
+ # https://chromium.googlesource.com/infra/infra/+/2c2389a00fcdb93d90a628f941814f2abd34428e/go/src/infra/tools/kitchen/cook.go#266
+ # and https://chromium.googlesource.com/infra/infra/+/7fcd559afa7a866a5ad039019e6ef6a91922e09c/appengine/cr-buildbucket/validation.py#36.
+ # We also should not override the 'recipe' of the child builder.
+ reject_keys = {
+ '$recipe_engine/path', '$recipe_engine/step', 'bot_id', 'path_config',
+ 'buildbucket', '$recipe_engine/buildbucket', 'buildername', 'branch',
+ 'repository', '$recipe_engine/runtime', 'recipe'
+ }
+ properties = {
+ key: val
+ for key, val in parent_properties.items()
+ if key and key not in reject_keys
+ }
+ properties.update({
+ 'spec_revision': spec_revision,
+ 'parent_id': orchestrator_id,
+ })
+ # If this task was launched by led, we launch the child with led as well.
+ # This lets us ensure that the parent and child use the same version of
+ # the recipes code. That is a requirement for testing this recipe, as well as
+ # for avoiding the need to do soft transitions when updating the interface
+ # between the parent and child recipes.
+ if api.led.launched_by_led:
+ output_build, build_url = build_with_led(api, builder_name, properties,
+ presentation)
+ else:
+ output_build, build_url = build_with_buildbucket(api, builder_name,
+ properties)
presentation.links[builder_name] = build_url
if output_build.status == common_pb2.INFRA_FAILURE:
raise api.step.InfraFailure('build raised infra failure')
- if output_build.status != common_pb2.SUCCESS:
+ elif output_build.status != common_pb2.SUCCESS:
raise api.step.StepFailure('build failed')
return output_build
@@ -478,21 +491,20 @@
]) + spec_data(
gcs_bucket='gcs-bucket', variants=('profile',)) + test_step_data()
+ child_build = ci_build_message(
+ api=api,
+ output_props={
+ 'integration-revision-count': 1,
+ 'test_orchestration_inputs_hash': 'abc',
+ },
+ status='SUCCESS',
+ )
yield api.fuchsia.test(
- 'successful_build_and_test_not_in_shards',
+ 'child_build_provided__test_not_in_shards',
clear_default_steps=True,
steps=[
- child_build_steps(
- api=api,
- build=ci_build_message(
- api=api,
- output_props={
- 'integration-revision-count': 1,
- 'test_orchestration_inputs_hash': 'abc',
- },
- status='SUCCESS',
- ),
- ),
+ api.buildbucket.simulated_get(
+ child_build, step_name='build.buildbucket.get'),
api.override_step_data(
'run tests.attempt 0.collect',
api.swarming.collect([
@@ -503,8 +515,9 @@
),
])),
]) + spec_data(
- gcs_bucket='gcs-bucket',
- test_in_shards=False) + test_step_data(test_in_shards=False)
+ gcs_bucket='gcs-bucket', test_in_shards=False) + test_step_data(
+ test_in_shards=False) + api.properties(
+ child_build_id=child_build.id)
yield api.fuchsia.test(
'build_only_failed',