[sdk] Improve log for missing subbuild output property

Theoretically, if an SDK subbuild fails to finish, and thus doesn't set
the isolated output hash property for the orchestrator to read, the
subbuild's status should not be successful, which would cause the
orchestrator to fail before trying to read any output properties.
However, crbug.com/1116249 is a bbagent bug that causes a step to fail
and end the build early, even while the overall build turns green.

To better handle this (and the general case where there's a bug in the
subbuild recipe and it doesn't set the output property), raise an
explicit message about the missing output property instead of failing
with an unclear ValueError (e.g. ci.chromium.org/b/8865062909937848576),
and apply the same message to similar failures in the fuchsia recipe.

Also start using status_check in all sdk recipe unit tests to make
assertions about the build status.

Fixed: 63233
Change-Id: I9ff1606b24d97c47496e553a946b18ad39316ae6
Reviewed-on: https://fuchsia-review.googlesource.com/c/infra/recipes/+/445476
Fuchsia-Auto-Submit: Oliver Newman <olivernewman@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Reviewed-by: Anthony Fandrianto <atyfto@google.com>
diff --git a/recipe_modules/subbuild/__init__.py b/recipe_modules/subbuild/__init__.py
index 25ba7e1..8c504e1 100644
--- a/recipe_modules/subbuild/__init__.py
+++ b/recipe_modules/subbuild/__init__.py
@@ -9,5 +9,6 @@
     "recipe_engine/json",
     "recipe_engine/path",
     "recipe_engine/properties",
+    "recipe_engine/step",
     "recipe_engine/swarming",
 ]
diff --git a/recipe_modules/subbuild/api.py b/recipe_modules/subbuild/api.py
index 8560998..89d1307 100644
--- a/recipe_modules/subbuild/api.py
+++ b/recipe_modules/subbuild/api.py
@@ -50,7 +50,6 @@
           launched_builds (dict): The launched_builds is a map from builder name
           to the corresponding SubbuildResult.
         """
-        launched_builds = {}
         parent_properties = self.m.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
@@ -178,6 +177,19 @@
             builds = self._collect_from_buildbucket(build_ids)
         return builds
 
+    def get_property(self, build_proto, property_name):
+        """Retrieve an output property from a subbuild's Build proto.
+
+        Ensures a clear and unified missing property error message across all
+        builders that use this recipe module.
+        """
+        try:
+            return build_proto.output.properties[property_name]
+        except ValueError:
+            raise self.m.step.InfraFailure(
+                "Subbuild did not set the %r output property" % property_name
+            )
+
     def _collect_from_led(self, task_ids, presentation):
         swarming_results = self.m.swarming.collect(
             "collect", task_ids, output_dir=self.m.path["cleanup"]
diff --git a/recipe_modules/subbuild/examples/full.expected/missing_property.json b/recipe_modules/subbuild/examples/full.expected/missing_property.json
new file mode 100644
index 0000000..16c9db7
--- /dev/null
+++ b/recipe_modules/subbuild/examples/full.expected/missing_property.json
@@ -0,0 +1,247 @@
+[
+  {
+    "cmd": [],
+    "name": "launch builds",
+    "~followup_annotations": [
+      "@@@STEP_LINK@builder-subbuild2@https://ci.chromium.org/b/8945511751514863187@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "bb",
+      "batch",
+      "-host",
+      "cr-buildbucket.appspot.com"
+    ],
+    "infra_step": true,
+    "name": "launch builds.schedule",
+    "stdin": "{\"requests\": [{\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"builder-subbuild1\", \"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\": {\"builder_names\": [\"builder-subbuild1\", \"builder-subbuild2\"], \"extra_properties\": {\"parent_id\": \"parentid\"}, \"gcs_bucket\": \"###fuchsia-build###\", \"manifest\": \"manifest/minimal\", \"packages\": [\"//bundles/buildbot:core\"], \"parent_id\": \"parentid\", \"project\": \"integration\", \"remote\": \"https://fuchsia.googlesource.com/integration\", \"target\": \"x64\"}, \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-000000001337\", \"swarming\": {\"parentRunId\": \"fake-task-id\"}, \"tags\": [{\"key\": \"skip-retry-in-gerrit\", \"value\": \"subbuild\"}, {\"key\": \"user_agent\", \"value\": \"recipe\"}]}}, {\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"builder-subbuild2\", \"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\": {\"builder_names\": [\"builder-subbuild1\", \"builder-subbuild2\"], \"extra_properties\": {\"parent_id\": \"parentid\"}, \"gcs_bucket\": \"###fuchsia-build###\", \"manifest\": \"manifest/minimal\", \"packages\": [\"//bundles/buildbot:core\"], \"parent_id\": \"parentid\", \"project\": \"integration\", \"remote\": \"https://fuchsia.googlesource.com/integration\", \"target\": \"x64\"}, \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-00000000133a\", \"swarming\": {\"parentRunId\": \"fake-task-id\"}, \"tags\": [{\"key\": \"skip-retry-in-gerrit\", \"value\": \"subbuild\"}, {\"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@        \"builder\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@          \"bucket\": \"try\", @@@",
+      "@@@STEP_LOG_LINE@json.output@          \"builder\": \"builder-subbuild2\", @@@",
+      "@@@STEP_LOG_LINE@json.output@          \"project\": \"fuchsia\"@@@",
+      "@@@STEP_LOG_LINE@json.output@        }, @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"id\": \"8945511751514863187\"@@@",
+      "@@@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-subbuild1\", @@@",
+      "@@@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@          \"builder_names\": [@@@",
+      "@@@STEP_LOG_LINE@request@            \"builder-subbuild1\", @@@",
+      "@@@STEP_LOG_LINE@request@            \"builder-subbuild2\"@@@",
+      "@@@STEP_LOG_LINE@request@          ], @@@",
+      "@@@STEP_LOG_LINE@request@          \"extra_properties\": {@@@",
+      "@@@STEP_LOG_LINE@request@            \"parent_id\": \"parentid\"@@@",
+      "@@@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\": \"parentid\", @@@",
+      "@@@STEP_LOG_LINE@request@          \"project\": \"integration\", @@@",
+      "@@@STEP_LOG_LINE@request@          \"remote\": \"https://fuchsia.googlesource.com/integration\", @@@",
+      "@@@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\": \"skip-retry-in-gerrit\", @@@",
+      "@@@STEP_LOG_LINE@request@            \"value\": \"subbuild\"@@@",
+      "@@@STEP_LOG_LINE@request@          }, @@@",
+      "@@@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@      \"scheduleBuild\": {@@@",
+      "@@@STEP_LOG_LINE@request@        \"builder\": {@@@",
+      "@@@STEP_LOG_LINE@request@          \"bucket\": \"ci\", @@@",
+      "@@@STEP_LOG_LINE@request@          \"builder\": \"builder-subbuild2\", @@@",
+      "@@@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@          \"builder_names\": [@@@",
+      "@@@STEP_LOG_LINE@request@            \"builder-subbuild1\", @@@",
+      "@@@STEP_LOG_LINE@request@            \"builder-subbuild2\"@@@",
+      "@@@STEP_LOG_LINE@request@          ], @@@",
+      "@@@STEP_LOG_LINE@request@          \"extra_properties\": {@@@",
+      "@@@STEP_LOG_LINE@request@            \"parent_id\": \"parentid\"@@@",
+      "@@@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\": \"parentid\", @@@",
+      "@@@STEP_LOG_LINE@request@          \"project\": \"integration\", @@@",
+      "@@@STEP_LOG_LINE@request@          \"remote\": \"https://fuchsia.googlesource.com/integration\", @@@",
+      "@@@STEP_LOG_LINE@request@          \"target\": \"x64\"@@@",
+      "@@@STEP_LOG_LINE@request@        }, @@@",
+      "@@@STEP_LOG_LINE@request@        \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-00000000133a\", @@@",
+      "@@@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\": \"skip-retry-in-gerrit\", @@@",
+      "@@@STEP_LOG_LINE@request@            \"value\": \"subbuild\"@@@",
+      "@@@STEP_LOG_LINE@request@          }, @@@",
+      "@@@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@8945511751514863187@https://cr-buildbucket.appspot.com/build/8945511751514863187@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "collect builds",
+    "~followup_annotations": [
+      "@@@STEP_EXCEPTION@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "collect builds.collect",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "bb",
+      "collect",
+      "-host",
+      "cr-buildbucket.appspot.com",
+      "-interval",
+      "20s",
+      "8945511751514863187"
+    ],
+    "infra_step": true,
+    "name": "collect builds.collect.wait",
+    "timeout": 86400,
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@2@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "bb",
+      "batch",
+      "-host",
+      "cr-buildbucket.appspot.com"
+    ],
+    "infra_step": true,
+    "name": "collect builds.collect.get",
+    "stdin": "{\"requests\": [{\"getBuild\": {\"fields\": \"builder,createTime,createdBy,critical,endTime,id,input,number,output,startTime,status,summaryMarkdown,updateTime\", \"id\": \"8945511751514863187\"}}]}",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@2@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"responses\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@    {@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"getBuild\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"builder\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@          \"bucket\": \"try\", @@@",
+      "@@@STEP_LOG_LINE@json.output@          \"builder\": \"builder-subbuild2\", @@@",
+      "@@@STEP_LOG_LINE@json.output@          \"project\": \"fuchsia\"@@@",
+      "@@@STEP_LOG_LINE@json.output@        }, @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"createTime\": \"2018-05-25T23:50:17Z\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"createdBy\": \"user:commit-bot@chromium.org\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"id\": \"8945511751514863187\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"infra\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@          \"resultdb\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@            \"invocation\": \"invocations/build:8945511751514863187\"@@@",
+      "@@@STEP_LOG_LINE@json.output@          }, @@@",
+      "@@@STEP_LOG_LINE@json.output@          \"swarming\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@            \"priority\": 30@@@",
+      "@@@STEP_LOG_LINE@json.output@          }@@@",
+      "@@@STEP_LOG_LINE@json.output@        }, @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"input\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@          \"gerritChanges\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@            {@@@",
+      "@@@STEP_LOG_LINE@json.output@              \"change\": \"123456\", @@@",
+      "@@@STEP_LOG_LINE@json.output@              \"host\": \"chromium-review.googlesource.com\", @@@",
+      "@@@STEP_LOG_LINE@json.output@              \"patchset\": \"7\", @@@",
+      "@@@STEP_LOG_LINE@json.output@              \"project\": \"fuchsia\"@@@",
+      "@@@STEP_LOG_LINE@json.output@            }@@@",
+      "@@@STEP_LOG_LINE@json.output@          ]@@@",
+      "@@@STEP_LOG_LINE@json.output@        }, @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"status\": \"SUCCESS\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"tags\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@          {@@@",
+      "@@@STEP_LOG_LINE@json.output@            \"key\": \"cq_experimental\", @@@",
+      "@@@STEP_LOG_LINE@json.output@            \"value\": \"false\"@@@",
+      "@@@STEP_LOG_LINE@json.output@          }@@@",
+      "@@@STEP_LOG_LINE@json.output@        ]@@@",
+      "@@@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@      \"getBuild\": {@@@",
+      "@@@STEP_LOG_LINE@request@        \"fields\": \"builder,createTime,createdBy,critical,endTime,id,input,number,output,startTime,status,summaryMarkdown,updateTime\", @@@",
+      "@@@STEP_LOG_LINE@request@        \"id\": \"8945511751514863187\"@@@",
+      "@@@STEP_LOG_LINE@request@      }@@@",
+      "@@@STEP_LOG_LINE@request@    }@@@",
+      "@@@STEP_LOG_LINE@request@  ]@@@",
+      "@@@STEP_LOG_LINE@request@}@@@",
+      "@@@STEP_LOG_END@request@@@",
+      "@@@STEP_LINK@8945511751514863187@https://cr-buildbucket.appspot.com/build/8945511751514863187@@@"
+    ]
+  },
+  {
+    "failure": {
+      "humanReason": "Subbuild did not set the 'test_orchestration_inputs_hash' output property"
+    },
+    "name": "$result"
+  }
+]
\ No newline at end of file
diff --git a/recipe_modules/subbuild/examples/full.py b/recipe_modules/subbuild/examples/full.py
index ee3cf29..23496ee 100644
--- a/recipe_modules/subbuild/examples/full.py
+++ b/recipe_modules/subbuild/examples/full.py
@@ -2,13 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from google.protobuf import json_format
-from google.protobuf import text_format
-
 from recipe_engine.recipe_api import Property
 from recipe_engine.config import List
-from PB.go.chromium.org.luci.buildbucket.proto import build as build_pb2
-from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2
 from PB.recipe_modules.recipe_engine.led.properties import (
     InputProperties as LedInputProperties,
 )
@@ -41,6 +36,8 @@
         builds = api.subbuild.collect(
             [build.build_id for build in builds.values()], presentation
         )
+        for build in builds.itervalues():
+            assert api.subbuild.get_property(build.build_proto, "test_orchestration_inputs_hash")
 
 
 def GenTests(api):
@@ -68,6 +65,12 @@
         output_props={"test_orchestration_inputs_hash": "abc",},
         status="SUCCESS",
     )
+    subbuild_missing_property = api.subbuild.try_build_message(
+        build_id=8945511751514863187,
+        builder="builder-subbuild2",
+        output_props={},
+        status="SUCCESS",
+    )
 
     properties = api.properties(
         builder_names=["builder-subbuild1", "builder-subbuild2"],
@@ -83,6 +86,17 @@
             ),
         ],
     ) + properties
+    yield api.fuchsia.test(
+        "missing_property",
+        status="infra_failure",
+        steps=[
+            api.subbuild.child_build_steps(
+                builds=[subbuild_missing_property],
+                launch_step="launch builds",
+                collect_step="collect builds",
+            ),
+        ],
+    ) + properties
 
     yield api.fuchsia.test(
         "launch_builds_with_led_ci",
diff --git a/recipes/fuchsia/fuchsia.expected/build_passed_but_hash_is_missing.json b/recipes/fuchsia/fuchsia.expected/build_passed_but_hash_is_missing.json
deleted file mode 100644
index 41f7b88..0000000
--- a/recipes/fuchsia/fuchsia.expected/build_passed_but_hash_is_missing.json
+++ /dev/null
@@ -1,365 +0,0 @@
-[
-  {
-    "cmd": [],
-    "name": "load spec",
-    "~followup_annotations": [
-      "@@@STEP_LOG_LINE@textproto@checkout {@@@",
-      "@@@STEP_LOG_LINE@textproto@  manifest: \"manifest\"@@@",
-      "@@@STEP_LOG_LINE@textproto@  remote: \"remote\"@@@",
-      "@@@STEP_LOG_LINE@textproto@}@@@",
-      "@@@STEP_LOG_LINE@textproto@build {@@@",
-      "@@@STEP_LOG_LINE@textproto@  build_type: \"debug\"@@@",
-      "@@@STEP_LOG_LINE@textproto@  board: \"boards/x64.gni\"@@@",
-      "@@@STEP_LOG_LINE@textproto@  product: \"products/core.gni\"@@@",
-      "@@@STEP_LOG_LINE@textproto@  run_tests: true@@@",
-      "@@@STEP_LOG_LINE@textproto@  target: \"x64\"@@@",
-      "@@@STEP_LOG_LINE@textproto@}@@@",
-      "@@@STEP_LOG_LINE@textproto@test {@@@",
-      "@@@STEP_LOG_LINE@textproto@  device_type: \"QEMU\"@@@",
-      "@@@STEP_LOG_LINE@textproto@  pool: \"fuchsia.tests\"@@@",
-      "@@@STEP_LOG_LINE@textproto@  swarming_expiration_timeout_secs: 600@@@",
-      "@@@STEP_LOG_LINE@textproto@  swarming_io_timeout_secs: 300@@@",
-      "@@@STEP_LOG_LINE@textproto@  test_in_shards: true@@@",
-      "@@@STEP_LOG_LINE@textproto@  timeout_secs: 1800@@@",
-      "@@@STEP_LOG_LINE@textproto@  use_runtests: true@@@",
-      "@@@STEP_LOG_LINE@textproto@}@@@",
-      "@@@STEP_LOG_LINE@textproto@@@@",
-      "@@@STEP_LOG_END@textproto@@@",
-      "@@@SET_BUILD_PROPERTY@artifact_gcs_bucket@\"\"@@@",
-      "@@@SET_BUILD_PROPERTY@gcs_bucket@\"\"@@@"
-    ]
-  },
-  {
-    "cmd": [],
-    "name": "load spec.install infra/tools/luci/gitiles",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "ensure-directory",
-      "--mode",
-      "0777",
-      "[CACHE]/cipd/infra/tools/luci/gitiles/latest"
-    ],
-    "infra_step": true,
-    "name": "load spec.install infra/tools/luci/gitiles.ensure package directory",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@2@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "cipd",
-      "ensure",
-      "-root",
-      "[CACHE]/cipd/infra/tools/luci/gitiles/latest",
-      "-ensure-file",
-      "infra/tools/luci/gitiles/${platform} latest",
-      "-max-threads",
-      "0",
-      "-json-output",
-      "/path/to/tmp/json"
-    ],
-    "infra_step": true,
-    "name": "load spec.install infra/tools/luci/gitiles.ensure_installed",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@2@@@",
-      "@@@STEP_LOG_LINE@json.output@{@@@",
-      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
-      "@@@STEP_LOG_LINE@json.output@      {@@@",
-      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
-      "@@@STEP_LOG_LINE@json.output@        \"package\": \"infra/tools/luci/gitiles/resolved-platform\"@@@",
-      "@@@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@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "[CACHE]/cipd/infra/tools/luci/gitiles/latest/gitiles",
-      "refs",
-      "-json-output",
-      "/path/to/tmp/json",
-      "http://fuchsia.googlesource.com/integration",
-      "refs/heads"
-    ],
-    "infra_step": true,
-    "name": "load spec.refs",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@json.output@{@@@",
-      "@@@STEP_LOG_LINE@json.output@  \"refs/heads/master\": \"deadbeef\"@@@",
-      "@@@STEP_LOG_LINE@json.output@}@@@",
-      "@@@STEP_LOG_END@json.output@@@"
-    ]
-  },
-  {
-    "cmd": [],
-    "name": "load spec.install fuchsia/infra/build_init",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "vpython",
-      "-u",
-      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
-      "--json-output",
-      "/path/to/tmp/json",
-      "ensure-directory",
-      "--mode",
-      "0777",
-      "[CACHE]/cipd/fuchsia/infra/build_init/git_revision%3Ad20cd84e02c8105ba719f26b0fa4579f5d8026e8"
-    ],
-    "infra_step": true,
-    "name": "load spec.install fuchsia/infra/build_init.ensure package directory",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@2@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "cipd",
-      "ensure",
-      "-root",
-      "[CACHE]/cipd/fuchsia/infra/build_init/git_revision%3Ad20cd84e02c8105ba719f26b0fa4579f5d8026e8",
-      "-ensure-file",
-      "fuchsia/infra/build_init/${platform} git_revision:d20cd84e02c8105ba719f26b0fa4579f5d8026e8",
-      "-max-threads",
-      "0",
-      "-json-output",
-      "/path/to/tmp/json"
-    ],
-    "infra_step": true,
-    "name": "load spec.install fuchsia/infra/build_init.ensure_installed",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@2@@@",
-      "@@@STEP_LOG_LINE@json.output@{@@@",
-      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
-      "@@@STEP_LOG_LINE@json.output@      {@@@",
-      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-git_revision:d20\", @@@",
-      "@@@STEP_LOG_LINE@json.output@        \"package\": \"fuchsia/infra/build_init/resolved-platform\"@@@",
-      "@@@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@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "[CACHE]/cipd/fuchsia/infra/build_init/git_revision%3Ad20cd84e02c8105ba719f26b0fa4579f5d8026e8/build_init",
-      "-spec_remote",
-      "http://fuchsia.googlesource.com/integration",
-      "-spec_path",
-      "infra/config/generated/fuchsia/specs/ci/builder.textproto",
-      "-spec_ref",
-      "deadbeef"
-    ],
-    "cwd": "[CLEANUP]/build_init_workspace_tmp_1",
-    "infra_step": true,
-    "name": "load spec.build_init",
-    "stdin": "CNDsgNmu8bWSfBIWCgdmdWNoc2lhEgJjaRoHYnVpbGRlciIvdXNlcjpsdWNpLXNjaGVkdWxlckBhcHBzcG90LmdzZXJ2aWNlYWNjb3VudC5jb20yBgi5wqLYBXpiEmAKGGZ1Y2hzaWEuZ29vZ2xlc291cmNlLmNvbRIHZnVjaHNpYRooMmQ3MjUxMGU0NDdhYjYwYTk3MjhhZWVhMjM2MmQ4YmUyY2JkNzc4OSIRcmVmcy9oZWFkcy9tYXN0ZXKSAS0SAiAeKicSJWludm9jYXRpb25zL2J1aWxkOjg5NDU1MTE3NTE1MTQ4NjMxODQ=",
-    "timeout": 600,
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [],
-    "name": "build",
-    "~followup_annotations": [
-      "@@@STEP_LINK@builder-subbuild@https://ci.chromium.org/b/8945511751514863184@@@",
-      "@@@STEP_FAILURE@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "bb",
-      "batch",
-      "-host",
-      "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\": {\"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\": \"skip-retry-in-gerrit\", \"value\": \"subbuild\"}, {\"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@        \"builder\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@          \"bucket\": \"ci\", @@@",
-      "@@@STEP_LOG_LINE@json.output@          \"builder\": \"builder-subbuild\", @@@",
-      "@@@STEP_LOG_LINE@json.output@          \"project\": \"fuchsia\"@@@",
-      "@@@STEP_LOG_LINE@json.output@        }, @@@",
-      "@@@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@          \"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\": \"skip-retry-in-gerrit\", @@@",
-      "@@@STEP_LOG_LINE@request@            \"value\": \"subbuild\"@@@",
-      "@@@STEP_LOG_LINE@request@          }, @@@",
-      "@@@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.child build id",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@SET_BUILD_PROPERTY@child_build_id@\"8945511751514863184\"@@@"
-    ]
-  },
-  {
-    "cmd": [],
-    "name": "build.collect",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@1@@@"
-    ]
-  },
-  {
-    "cmd": [
-      "bb",
-      "collect",
-      "-host",
-      "cr-buildbucket.appspot.com",
-      "-interval",
-      "20s",
-      "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",
-    "stdin": "{\"requests\": [{\"getBuild\": {\"fields\": \"builder,createTime,createdBy,critical,endTime,id,input,number,output,startTime,status,summaryMarkdown,updateTime\", \"id\": \"8945511751514863184\"}}]}",
-    "~followup_annotations": [
-      "@@@STEP_NEST_LEVEL@2@@@",
-      "@@@STEP_LOG_LINE@json.output@{@@@",
-      "@@@STEP_LOG_LINE@json.output@  \"responses\": [@@@",
-      "@@@STEP_LOG_LINE@json.output@    {@@@",
-      "@@@STEP_LOG_LINE@json.output@      \"getBuild\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@        \"builder\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@          \"bucket\": \"ci\", @@@",
-      "@@@STEP_LOG_LINE@json.output@          \"builder\": \"builder-subbuild\", @@@",
-      "@@@STEP_LOG_LINE@json.output@          \"project\": \"fuchsia\"@@@",
-      "@@@STEP_LOG_LINE@json.output@        }, @@@",
-      "@@@STEP_LOG_LINE@json.output@        \"createTime\": \"2018-05-25T23:50:17Z\", @@@",
-      "@@@STEP_LOG_LINE@json.output@        \"createdBy\": \"user:luci-scheduler@appspot.gserviceaccount.com\", @@@",
-      "@@@STEP_LOG_LINE@json.output@        \"id\": \"8945511751514863184\", @@@",
-      "@@@STEP_LOG_LINE@json.output@        \"infra\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@          \"resultdb\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@            \"invocation\": \"invocations/build:8945511751514863184\"@@@",
-      "@@@STEP_LOG_LINE@json.output@          }, @@@",
-      "@@@STEP_LOG_LINE@json.output@          \"swarming\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@            \"priority\": 30@@@",
-      "@@@STEP_LOG_LINE@json.output@          }@@@",
-      "@@@STEP_LOG_LINE@json.output@        }, @@@",
-      "@@@STEP_LOG_LINE@json.output@        \"input\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@          \"gitilesCommit\": {@@@",
-      "@@@STEP_LOG_LINE@json.output@            \"host\": \"chromium.googlesource.com\", @@@",
-      "@@@STEP_LOG_LINE@json.output@            \"id\": \"2d72510e447ab60a9728aeea2362d8be2cbd7789\", @@@",
-      "@@@STEP_LOG_LINE@json.output@            \"project\": \"fuchsia\", @@@",
-      "@@@STEP_LOG_LINE@json.output@            \"ref\": \"refs/heads/master\"@@@",
-      "@@@STEP_LOG_LINE@json.output@          }@@@",
-      "@@@STEP_LOG_LINE@json.output@        }, @@@",
-      "@@@STEP_LOG_LINE@json.output@        \"status\": \"SUCCESS\"@@@",
-      "@@@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@      \"getBuild\": {@@@",
-      "@@@STEP_LOG_LINE@request@        \"fields\": \"builder,createTime,createdBy,critical,endTime,id,input,number,output,startTime,status,summaryMarkdown,updateTime\", @@@",
-      "@@@STEP_LOG_LINE@request@        \"id\": \"8945511751514863184\"@@@",
-      "@@@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@@@"
-    ]
-  },
-  {
-    "failure": {
-      "failure": {},
-      "humanReason": "no `test_orchestration_inputs_hash` property found"
-    },
-    "name": "$result"
-  }
-]
\ No newline at end of file
diff --git a/recipes/fuchsia/fuchsia.py b/recipes/fuchsia/fuchsia.py
index b90082f..054e01d 100644
--- a/recipes/fuchsia/fuchsia.py
+++ b/recipes/fuchsia/fuchsia.py
@@ -108,10 +108,10 @@
             (
                 orchestration_inputs,
                 orchestration_inputs_hash,
-            ) = collect_test_orchestration_inputs(api, child_props, without_cl=False)
+            ) = collect_test_orchestration_inputs(api, child_build, without_cl=False)
             if props.perfcompare:
                 orchestration_inputs_without_cl, _ = collect_test_orchestration_inputs(
-                    api, child_props, without_cl=True
+                    api, child_build, without_cl=True
                 )
 
             # Copy to output properties so the coverage recipe can access it.
@@ -284,25 +284,23 @@
         api.fxt.cleanup(step_name="cleanup", workspace=resp["workspace"])
 
 
-def collect_test_orchestration_inputs(api, build_props, without_cl):
+def collect_test_orchestration_inputs(api, build_proto, without_cl):
     """Downloads isolated orchestration inputs from a build.
 
     Args:
-      build_props (dict): The properties of the build that produced the test
-          orchestration inputs.
-      without_cl (bool): Whether to download the "without CL" build.  If false,
-          this downloads the "with CL" build.
+        build_proto (Build): The Build proto for the build that produced the
+            test orchestration inputs.
+        without_cl (bool): Whether to download the "without CL" build.  If false,
+            this downloads the "with CL" build.
 
     Returns:
-      FuchsiaBuildApi.TestOrchestrationInputs, hash (str)
+        FuchsiaBuildApi.TestOrchestrationInputs, hash (str)
 
     Raises:
-      A StepFailure if the required property is not found.
+        An InfraFailure if the required property is not found.
     """
     prop_name = api.build.test_orchestration_inputs_property_name(without_cl)
-    orchestration_inputs_hash = build_props.get(prop_name)
-    if not orchestration_inputs_hash:
-        raise api.step.StepFailure("no `%s` property found" % prop_name)
+    orchestration_inputs_hash = api.subbuild.get_property(build_proto, prop_name)
     return (
         api.build.download_test_orchestration_inputs(orchestration_inputs_hash),
         orchestration_inputs_hash,
@@ -819,20 +817,6 @@
     ) + spec_data()
 
     yield api.fuchsia.test(
-        "build_passed_but_hash_is_missing",
-        status="failure",
-        steps=[
-            api.subbuild.child_build_steps(
-                builds=[
-                    api.subbuild.ci_build_message(
-                        builder="builder-subbuild", status="SUCCESS",
-                    )
-                ]
-            )
-        ],
-    ) + spec_data()
-
-    yield api.fuchsia.test(
         "successful_external_tests",
         steps=[api.subbuild.child_build_steps(builds=[child_build])],
     ) + spec_data(
diff --git a/recipes/sdk.py b/recipes/sdk.py
index 590ec48..60b45db 100644
--- a/recipes/sdk.py
+++ b/recipes/sdk.py
@@ -83,6 +83,7 @@
     "fuchsia/macos_sdk",
     "fuchsia/release",
     "fuchsia/sso",
+    "fuchsia/status_check",
     "fuchsia/subbuild",
     "fuchsia/tar",
     "fuchsia/upload",
@@ -115,9 +116,9 @@
         for build_id, build in builds.iteritems():
             build_id = str(build_id)
             with api.step.nest(build_id):
-                isolated_output = build.build_proto.output.properties[
-                    ISOLATED_OUTPUT_KEY
-                ].strip('"')
+                isolated_output = api.subbuild.get_property(
+                    build.build_proto, ISOLATED_OUTPUT_KEY
+                )
                 output_dir = isolated_output_path.join(build_id)
                 api.file.ensure_directory("makedirs", dest=output_dir)
                 api.isolated.download(
@@ -828,7 +829,7 @@
     ]
 
     yield (
-        api.test("local_ci")
+        api.status_check.test("local_ci")
         + topaz_local_ci
         + ci_subbuilds
         + api.fxt.launch(
@@ -844,15 +845,15 @@
             tap_testing=Sdk.TapTesting(tap_projects=["foo"], use_staging_host=False),
         )
     )
-    yield (api.test("local_cq") + topaz_local_cq + cq_subbuilds)
+    yield (api.status_check.test("local_cq") + topaz_local_cq + cq_subbuilds)
     yield (
-        api.test("local_ci_mac")
+        api.status_check.test("local_ci_mac")
         + topaz_local_ci
         + api.platform.name("mac")
         + ci_subbuilds
     )
     yield (
-        api.test("global_ci")
+        api.status_check.test("global_ci")
         + topaz_global_ci
         + ci_subbuilds
         + api.cl_util.create_cl(
@@ -887,7 +888,7 @@
         ),
     ]
     yield (
-        api.test("explicit_tryjobs")
+        api.status_check.test("explicit_tryjobs")
         + topaz_global_ci
         + ci_subbuilds
         + api.cl_util.create_cl(
@@ -921,7 +922,7 @@
         )
     )
     yield (
-        api.test("release_ci")
+        api.status_check.test("release_ci")
         + topaz_release_ci
         + ci_subbuilds
         + ci_image_builds
@@ -934,7 +935,7 @@
         + release_versions
     )
     yield (
-        api.test("release_ci_no_update_ref")
+        api.status_check.test("release_ci_no_update_ref")
         + topaz_release_ci
         + ci_subbuilds
         + ci_image_builds
@@ -946,14 +947,18 @@
         + describe
         + no_release_versions
     )
-    yield (api.test("local_ci_build_failure") + topaz_global_ci + ci_subbuilds_failure)
     yield (
-        api.test("local_ci_infra_failure")
+        api.status_check.test("local_ci_build_failure", status="failure")
+        + topaz_global_ci
+        + ci_subbuilds_failure
+    )
+    yield (
+        api.status_check.test("local_ci_infra_failure", status="infra_failure")
         + topaz_global_ci
         + ci_subbuilds_infra_failure
     )
     yield (
-        api.test("release_ci_image_failure")
+        api.status_check.test("release_ci_image_failure", status="failure")
         + topaz_global_ci
         + ci_subbuilds
         + ci_image_builds_failure
@@ -966,7 +971,7 @@
         + release_versions
     )
     yield (
-        api.test("release_ci_new_upload")
+        api.status_check.test("release_ci_new_upload")
         + topaz_release_ci
         + api.step_data(
             "upload core.cipd.cipd search fuchsia/sdk/core/${platform} "