Allow sub-builds to set a custom timeout in builder configs

Bug: https://github.com/flutter/flutter/issues/150011
Change-Id: Ic502ca5e4af33d5edce9cf1d23e0dbdd7b735417
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/57980
Reviewed-by: Christopher Fujino <fujino@google.com>
Commit-Queue: Victoria Ashworth <vashworth@google.com>
diff --git a/recipe_modules/shard_util/api.py b/recipe_modules/shard_util/api.py
index e18ff3c..ec9a3a3 100644
--- a/recipe_modules/shard_util/api.py
+++ b/recipe_modules/shard_util/api.py
@@ -399,10 +399,15 @@
               'exe_cipd_version', 'refs/heads/%s' % branch
           )
       )
-      # Increase timeout if no_goma, since the runtime is going to
-      # be much longer.
-      if drone_properties.get("no_goma", False):
+
+      timeout_in_minutes = build.get('timeout', None)
+      if timeout_in_minutes is not None:
+        req.execution_timeout.FromSeconds(timeout_in_minutes * 60)
+      elif drone_properties.get("no_goma", False):
+        # Increase timeout if no_goma, since the runtime is going to
+        # be much longer.
         req.execution_timeout.FromSeconds(60 * 60 * 4)
+
       reqs.append(req)
     scheduled_builds = self.m.buildbucket.schedule(reqs, step_name="schedule")
     results = {}
diff --git a/recipe_modules/shard_util/examples/full.expected/presubmit_bb_with_custom_timeout.json b/recipe_modules/shard_util/examples/full.expected/presubmit_bb_with_custom_timeout.json
new file mode 100644
index 0000000..9374191
--- /dev/null
+++ b/recipe_modules/shard_util/examples/full.expected/presubmit_bb_with_custom_timeout.json
@@ -0,0 +1,449 @@
+[
+  {
+    "cmd": [],
+    "name": "launch builds"
+  },
+  {
+    "cmd": [],
+    "name": "launch builds.get buildbucket id",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_TEXT@8945511751514863184@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "bb",
+      "batch",
+      "-host",
+      "cr-buildbucket.appspot.com"
+    ],
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "fuchsia:ci"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "launch builds.schedule",
+    "stdin": "{\"requests\": [{\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"Windows Engine Drone\", \"project\": \"fuchsia\"}, \"dimensions\": [{\"key\": \"cpu\", \"value\": \"arm64\"}, {\"key\": \"dimension1\", \"value\": \"abc\"}, {\"key\": \"os\", \"value\": \"Windows-10\"}], \"exe\": {\"cipdVersion\": \"refs/heads/main\"}, \"executionTimeout\": \"600s\", \"experimental\": \"NO\", \"experiments\": {\"luci.buildbucket.parent_tracking\": false}, \"fields\": \"builder,createTime,createdBy,critical,endTime,id,infra,input,number,output,startTime,status,updateTime\", \"gitilesCommit\": {\"host\": \"fuchsia.googlesource.com\", \"id\": \"2d72510e447ab60a9728aeea2362d8be2cbd7789\", \"project\": \"fuchsia\", \"ref\": \"refs/heads/main\"}, \"priority\": 30, \"properties\": {\"build\": {\"dimensions\": {\"cpu\": \"arm64\"}, \"drone_dimensions\": [\"dimension1=abc\", \"os=Windows-10\"], \"generators\": [{\"name\": \"generator1\", \"script\": \"script1.sh\"}], \"gn\": [\"--ios\"], \"name\": \"ios_debug\", \"ninja\": {\"config\": \"ios_debug\", \"targets\": []}, \"recipe\": \"engine_v2/builder\", \"timeout\": 10.0}, \"build_identifier\": \"8945511751514863184\", \"environment\": \"Staging\", \"gclient_variables\": {}, \"parent_commit\": \"\", \"recipe\": \"engine_v2/builder\", \"task_name\": \"mytask\", \"tests\": [{\"dependencies\": [\"ios_debug\"], \"name\": \"felt_test\", \"parameters\": [\"test\"], \"scripts\": [\"out/script.sh\"]}]}, \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-000000001337\", \"swarming\": {\"parentRunId\": \"fake-task-id\"}, \"tags\": [{\"key\": \"parent_buildbucket_id\", \"value\": \"8945511751514863184\"}, {\"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\": \"Windows Engine Drone\",@@@",
+      "@@@STEP_LOG_LINE@request@          \"project\": \"fuchsia\"@@@",
+      "@@@STEP_LOG_LINE@request@        },@@@",
+      "@@@STEP_LOG_LINE@request@        \"dimensions\": [@@@",
+      "@@@STEP_LOG_LINE@request@          {@@@",
+      "@@@STEP_LOG_LINE@request@            \"key\": \"cpu\",@@@",
+      "@@@STEP_LOG_LINE@request@            \"value\": \"arm64\"@@@",
+      "@@@STEP_LOG_LINE@request@          },@@@",
+      "@@@STEP_LOG_LINE@request@          {@@@",
+      "@@@STEP_LOG_LINE@request@            \"key\": \"dimension1\",@@@",
+      "@@@STEP_LOG_LINE@request@            \"value\": \"abc\"@@@",
+      "@@@STEP_LOG_LINE@request@          },@@@",
+      "@@@STEP_LOG_LINE@request@          {@@@",
+      "@@@STEP_LOG_LINE@request@            \"key\": \"os\",@@@",
+      "@@@STEP_LOG_LINE@request@            \"value\": \"Windows-10\"@@@",
+      "@@@STEP_LOG_LINE@request@          }@@@",
+      "@@@STEP_LOG_LINE@request@        ],@@@",
+      "@@@STEP_LOG_LINE@request@        \"exe\": {@@@",
+      "@@@STEP_LOG_LINE@request@          \"cipdVersion\": \"refs/heads/main\"@@@",
+      "@@@STEP_LOG_LINE@request@        },@@@",
+      "@@@STEP_LOG_LINE@request@        \"executionTimeout\": \"600s\",@@@",
+      "@@@STEP_LOG_LINE@request@        \"experimental\": \"NO\",@@@",
+      "@@@STEP_LOG_LINE@request@        \"experiments\": {@@@",
+      "@@@STEP_LOG_LINE@request@          \"luci.buildbucket.parent_tracking\": false@@@",
+      "@@@STEP_LOG_LINE@request@        },@@@",
+      "@@@STEP_LOG_LINE@request@        \"fields\": \"builder,createTime,createdBy,critical,endTime,id,infra,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/main\"@@@",
+      "@@@STEP_LOG_LINE@request@        },@@@",
+      "@@@STEP_LOG_LINE@request@        \"priority\": 30,@@@",
+      "@@@STEP_LOG_LINE@request@        \"properties\": {@@@",
+      "@@@STEP_LOG_LINE@request@          \"build\": {@@@",
+      "@@@STEP_LOG_LINE@request@            \"dimensions\": {@@@",
+      "@@@STEP_LOG_LINE@request@              \"cpu\": \"arm64\"@@@",
+      "@@@STEP_LOG_LINE@request@            },@@@",
+      "@@@STEP_LOG_LINE@request@            \"drone_dimensions\": [@@@",
+      "@@@STEP_LOG_LINE@request@              \"dimension1=abc\",@@@",
+      "@@@STEP_LOG_LINE@request@              \"os=Windows-10\"@@@",
+      "@@@STEP_LOG_LINE@request@            ],@@@",
+      "@@@STEP_LOG_LINE@request@            \"generators\": [@@@",
+      "@@@STEP_LOG_LINE@request@              {@@@",
+      "@@@STEP_LOG_LINE@request@                \"name\": \"generator1\",@@@",
+      "@@@STEP_LOG_LINE@request@                \"script\": \"script1.sh\"@@@",
+      "@@@STEP_LOG_LINE@request@              }@@@",
+      "@@@STEP_LOG_LINE@request@            ],@@@",
+      "@@@STEP_LOG_LINE@request@            \"gn\": [@@@",
+      "@@@STEP_LOG_LINE@request@              \"--ios\"@@@",
+      "@@@STEP_LOG_LINE@request@            ],@@@",
+      "@@@STEP_LOG_LINE@request@            \"name\": \"ios_debug\",@@@",
+      "@@@STEP_LOG_LINE@request@            \"ninja\": {@@@",
+      "@@@STEP_LOG_LINE@request@              \"config\": \"ios_debug\",@@@",
+      "@@@STEP_LOG_LINE@request@              \"targets\": []@@@",
+      "@@@STEP_LOG_LINE@request@            },@@@",
+      "@@@STEP_LOG_LINE@request@            \"recipe\": \"engine_v2/builder\",@@@",
+      "@@@STEP_LOG_LINE@request@            \"timeout\": 10.0@@@",
+      "@@@STEP_LOG_LINE@request@          },@@@",
+      "@@@STEP_LOG_LINE@request@          \"build_identifier\": \"8945511751514863184\",@@@",
+      "@@@STEP_LOG_LINE@request@          \"environment\": \"Staging\",@@@",
+      "@@@STEP_LOG_LINE@request@          \"gclient_variables\": {},@@@",
+      "@@@STEP_LOG_LINE@request@          \"parent_commit\": \"\",@@@",
+      "@@@STEP_LOG_LINE@request@          \"recipe\": \"engine_v2/builder\",@@@",
+      "@@@STEP_LOG_LINE@request@          \"task_name\": \"mytask\",@@@",
+      "@@@STEP_LOG_LINE@request@          \"tests\": [@@@",
+      "@@@STEP_LOG_LINE@request@            {@@@",
+      "@@@STEP_LOG_LINE@request@              \"dependencies\": [@@@",
+      "@@@STEP_LOG_LINE@request@                \"ios_debug\"@@@",
+      "@@@STEP_LOG_LINE@request@              ],@@@",
+      "@@@STEP_LOG_LINE@request@              \"name\": \"felt_test\",@@@",
+      "@@@STEP_LOG_LINE@request@              \"parameters\": [@@@",
+      "@@@STEP_LOG_LINE@request@                \"test\"@@@",
+      "@@@STEP_LOG_LINE@request@              ],@@@",
+      "@@@STEP_LOG_LINE@request@              \"scripts\": [@@@",
+      "@@@STEP_LOG_LINE@request@                \"out/script.sh\"@@@",
+      "@@@STEP_LOG_LINE@request@              ]@@@",
+      "@@@STEP_LOG_LINE@request@            }@@@",
+      "@@@STEP_LOG_LINE@request@          ]@@@",
+      "@@@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\": \"parent_buildbucket_id\",@@@",
+      "@@@STEP_LOG_LINE@request@            \"value\": \"8945511751514863184\"@@@",
+      "@@@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_FAILURE@@@"
+    ]
+  },
+  {
+    "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,
+    "luci_context": {
+      "realm": {
+        "name": "fuchsia:ci"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "collect builds.collect.wait",
+    "timeout": 86400,
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@2@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "bb",
+      "batch",
+      "-host",
+      "cr-buildbucket.appspot.com"
+    ],
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "fuchsia:ci"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "collect builds.collect.get",
+    "stdin": "{\"requests\": [{\"getBuild\": {\"fields\": \"builder,createTime,createdBy,critical,endTime,id,infra,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\": \"project:fuchsia\",@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"id\": \"8945511751514863187\",@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"infra\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@          \"backend\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@            \"task\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@              \"id\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@                \"id\": \"abc123\"@@@",
+      "@@@STEP_LOG_LINE@json.output@              }@@@",
+      "@@@STEP_LOG_LINE@json.output@            }@@@",
+      "@@@STEP_LOG_LINE@json.output@          },@@@",
+      "@@@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@        \"output\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@          \"properties\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@            \"cas_output_hash\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@              \"ios_debug\": \"bcd\",@@@",
+      "@@@STEP_LOG_LINE@json.output@              \"web_tests\": \"abc\"@@@",
+      "@@@STEP_LOG_LINE@json.output@            }@@@",
+      "@@@STEP_LOG_LINE@json.output@          }@@@",
+      "@@@STEP_LOG_LINE@json.output@        },@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"status\": \"FAILURE\",@@@",
+      "@@@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,infra,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@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "collect builds.install infra/tools/luci/swarming",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "vpython3",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "ensure-directory",
+      "--mode",
+      "0o777",
+      "[START_DIR]/cipd_tool/infra/tools/luci/swarming/90026cfdbec6795a35e48e95f30cbb0f779e0a4c35016adb14707e333aee4227"
+    ],
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "fuchsia:ci"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "collect builds.install infra/tools/luci/swarming.ensure package directory",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@2@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[START_DIR]/cipd_tool/infra/tools/luci/swarming/90026cfdbec6795a35e48e95f30cbb0f779e0a4c35016adb14707e333aee4227",
+      "-ensure-file",
+      "infra/tools/luci/swarming/${platform} swarming_module_pin",
+      "-max-threads",
+      "0",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "fuchsia:ci"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "collect builds.install infra/tools/luci/swarming.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-swarming_module_\",@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"infra/tools/luci/swarming/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": [
+      "[START_DIR]/cipd_tool/infra/tools/luci/swarming/90026cfdbec6795a35e48e95f30cbb0f779e0a4c35016adb14707e333aee4227/swarming",
+      "collect",
+      "-server",
+      "https://example.swarmingserver.appspot.com",
+      "-task-summary-json",
+      "/path/to/tmp/json",
+      "-task-output-stdout",
+      "json",
+      "abc123"
+    ],
+    "cost": {
+      "cpu": 100,
+      "disk": 0,
+      "memory": 50,
+      "net": 0
+    },
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "fuchsia:ci"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "collect builds.wait for 1 task to complete",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"abc123\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"output\": \"hello world!\",@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"outputs\": [],@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"results\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"bot_id\": \"vm-123\",@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"cas_output_root\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"cas_instance\": \"projects/example-project/instances/default_instance\",@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"digest\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@          \"hash\": \"24b2420bc49d8b8fdc1d011a163708927532b37dc9f91d7d8d6877e3a86559ca\",@@@",
+      "@@@STEP_LOG_LINE@json.output@          \"size_bytes\": \"73\"@@@",
+      "@@@STEP_LOG_LINE@json.output@        }@@@",
+      "@@@STEP_LOG_LINE@json.output@      },@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"duration\": 62.35,@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"exit_code\": \"0\",@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"name\": \"my_task_0\",@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"resultdb_info\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"invocation\": \"invocations/some-inv-name\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      },@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"state\": \"COMPLETED\",@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"task_id\": \"abc123\"@@@",
+      "@@@STEP_LOG_LINE@json.output@    }@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@",
+      "@@@STEP_LOG_LINE@task stdout+stderr: my_task_0@hello world!@@@",
+      "@@@STEP_LOG_END@task stdout+stderr: my_task_0@@@",
+      "@@@STEP_LINK@task cas outputs: my_task_0@https://cas-viewer.appspot.com/projects/example-project/instances/default_instance/blobs/24b2420bc49d8b8fdc1d011a163708927532b37dc9f91d7d8d6877e3a86559ca/73/tree@@@"
+    ]
+  },
+  {
+    "failure": {
+      "failure": {},
+      "humanReason": "build 8945511751514863187 failed"
+    },
+    "name": "$result"
+  }
+]
\ No newline at end of file
diff --git a/recipe_modules/shard_util/examples/full.py b/recipe_modules/shard_util/examples/full.py
index 483c18b..b72d786 100644
--- a/recipe_modules/shard_util/examples/full.py
+++ b/recipe_modules/shard_util/examples/full.py
@@ -179,6 +179,19 @@
       )
   )
 
+  presubmit_props_bb_with_custom_timeout = copy.deepcopy(props_bb)
+  presubmit_props_bb_with_custom_timeout['builds'][0]['timeout'] = 10
+  yield (
+      api.buildbucket_util.
+      test('presubmit_bb_with_custom_timeout', tryjob=False, status='FAILURE') +
+      api.properties(**presubmit_props_bb_with_custom_timeout) +
+      api.platform.name('linux') + api.shard_util.child_build_steps(
+          subbuilds=[try_failure],
+          launch_step='launch builds.schedule',
+          collect_step='collect builds',
+      )
+  )
+
   yield api.test(
       'presubmit_led_subbuilds', api.properties(**props),
       api.platform.name('linux'),