Trigger multiple builds from a single run.
The purpose of this recipe is to trigger multiple builds at the same
revision. Specify build request arguments in a property and trigger the
builds in a batch, this may be in separate projects and/or buckets as
long as the service account this recipe runs under has the corresponding
permissions in buildbucket.
R=nodir,liaoyuke,sajjadm,iannucci,phosek
Bug: 944752
Change-Id: Icd2543cc8823ec2dc5b6e4bc80322df0c359683e
Reviewed-on: https://chromium-review.googlesource.com/c/infra/luci/recipes-py/+/1537739
Commit-Queue: Roberto Carrillo <robertocn@chromium.org>
Reviewed-by: Nodir Turakulov <nodir@chromium.org>
diff --git a/README.recipes.md b/README.recipes.md
index 1fa2ad8..ee6f2c3 100644
--- a/README.recipes.md
+++ b/README.recipes.md
@@ -41,6 +41,7 @@
* [assertions:tests/long_message](#recipes-assertions_tests_long_message)
* [assertions:tests/max_diff](#recipes-assertions_tests_max_diff)
* [buildbucket:examples/full](#recipes-buildbucket_examples_full) — This file is a recipe demonstrating the buildbucket recipe module.
+ * [buildbucket:run/multi](#recipes-buildbucket_run_multi) — Launches multiple builds at the same revision.
* [buildbucket:tests/build](#recipes-buildbucket_tests_build)
* [buildbucket:tests/collect](#recipes-buildbucket_tests_collect)
* [buildbucket:tests/get](#recipes-buildbucket_tests_get)
@@ -238,7 +239,7 @@
A module for interacting with buildbucket.
-  **@property**<br>— **def [bucket\_v1](/recipe_modules/buildbucket/api.py#636)(self):**
+  **@property**<br>— **def [bucket\_v1](/recipe_modules/buildbucket/api.py#652)(self):**
Returns bucket name in v1 format.
@@ -261,11 +262,11 @@
the rules described in the .proto files.
If the current build is not a buildbucket build, returned `build.id` is 0.
-  **@property**<br>— **def [build\_id](/recipe_modules/buildbucket/api.py#652)(self):**
+  **@property**<br>— **def [build\_id](/recipe_modules/buildbucket/api.py#668)(self):**
DEPRECATED, use build.id instead.
-  **@property**<br>— **def [build\_input](/recipe_modules/buildbucket/api.py#657)(self):**
+  **@property**<br>— **def [build\_input](/recipe_modules/buildbucket/api.py#673)(self):**
DEPRECATED, use build.input instead.
@@ -273,7 +274,7 @@
Returns url to a build. Defaults to current build.
-  **@property**<br>— **def [builder\_id](/recipe_modules/buildbucket/api.py#662)(self):**
+  **@property**<br>— **def [builder\_id](/recipe_modules/buildbucket/api.py#678)(self):**
Deprecated. Use build.builder instead.
@@ -281,9 +282,9 @@
Returns builder name. Shortcut for `.build.builder.builder`.
-— **def [cancel\_build](/recipe_modules/buildbucket/api.py#523)(self, build_id, \*\*kwargs):**
+— **def [cancel\_build](/recipe_modules/buildbucket/api.py#525)(self, build_id, \*\*kwargs):**
-— **def [collect\_build](/recipe_modules/buildbucket/api.py#529)(self, build_id, mirror_status=False, \*\*kwargs):**
+— **def [collect\_build](/recipe_modules/buildbucket/api.py#531)(self, build_id, mirror_status=False, \*\*kwargs):**
Shorthand for `collect_builds` below, but for a single build only.
@@ -295,7 +296,7 @@
[Build](https://chromium.googlesource.com/infra/luci/luci-go/+/master/buildbucket/proto/build.proto).
for the ended build.
-— **def [collect\_builds](/recipe_modules/buildbucket/api.py#549)(self, build_ids, interval=None, timeout=None, step_name=None):**
+— **def [collect\_builds](/recipe_modules/buildbucket/api.py#551)(self, build_ids, interval=None, timeout=None, step_name=None, raise_if_unsuccessful=False):**
Waits for a set of builds to end and returns their details.
@@ -305,13 +306,15 @@
Defaults to 1m.
* timeout: Maximum time to wait for builds to end. Defaults to 1h.
* step_name: Custom name for the generated step.
+* raise_if_unsuccessful: if any build being collected did not succeed, raise
+ an exception.
Returns:
A map from integer build IDs to the corresponding
[Build](https://chromium.googlesource.com/infra/luci/luci-go/+/master/buildbucket/proto/build.proto)
for all specified builds.
-— **def [get\_build](/recipe_modules/buildbucket/api.py#526)(self, build_id, \*\*kwargs):**
+— **def [get\_build](/recipe_modules/buildbucket/api.py#528)(self, build_id, \*\*kwargs):**
  **@property**<br>— **def [gitiles\_commit](/recipe_modules/buildbucket/api.py#135)(self):**
@@ -329,11 +332,11 @@
Returns True if the build is critical. Build defaults to the current one.
-  **@property**<br>— **def [properties](/recipe_modules/buildbucket/api.py#647)(self):**
+  **@property**<br>— **def [properties](/recipe_modules/buildbucket/api.py#663)(self):**
DEPRECATED, use build attribute instead.
-— **def [put](/recipe_modules/buildbucket/api.py#488)(self, builds, \*\*kwargs):**
+— **def [put](/recipe_modules/buildbucket/api.py#490)(self, builds, \*\*kwargs):**
Puts a batch of builds.
@@ -357,7 +360,7 @@
A step that as its `.stdout` property contains the response object as
returned by buildbucket.
-— **def [run](/recipe_modules/buildbucket/api.py#238)(self, schedule_build_requests, collect_interval=None, timeout=None, url_title_fn=None, step_name=None):**
+— **def [run](/recipe_modules/buildbucket/api.py#238)(self, schedule_build_requests, collect_interval=None, timeout=None, url_title_fn=None, step_name=None, raise_if_unsuccessful=False):**
Runs builds and returns results.
@@ -369,7 +372,7 @@
[Builds](https://chromium.googlesource.com/infra/luci/luci-go/+/master/buildbucket/proto/build.proto)
in the same order as schedule_build_requests.
-— **def [schedule](/recipe_modules/buildbucket/api.py#393)(self, schedule_build_requests, url_title_fn=None, step_name=None):**
+— **def [schedule](/recipe_modules/buildbucket/api.py#395)(self, schedule_build_requests, url_title_fn=None, step_name=None):**
Schedules a batch of builds.
@@ -391,7 +394,7 @@
* url_title_fn: a function (build_pb2.Build) -> (str) that returns a title
of build link for the step. Defaults to build id.
If returns None, the link is not emitted.
-* step_name: step name/
+* step_name: name for this step.
Returns:
A list of
@@ -401,7 +404,7 @@
Raises:
`InfraFailure` if any of the requests fail.
-— **def [schedule\_request](/recipe_modules/buildbucket/api.py#262)(self, builder, project=None, bucket=None, properties=None, experimental=None, gitiles_commit=None, gerrit_changes=None, tags=None, inherit_buildsets=True, dimensions=None, priority=None, critical=None):**
+— **def [schedule\_request](/recipe_modules/buildbucket/api.py#264)(self, builder, project=None, bucket=None, properties=None, experimental=None, gitiles_commit=None, gerrit_changes=None, tags=None, inherit_buildsets=True, dimensions=None, priority=None, critical=None):**
Creates a new `ScheduleBuildRequest` message with reasonable defaults.
@@ -2358,6 +2361,13 @@
This file is a recipe demonstrating the buildbucket recipe module.
— **def [RunSteps](/recipe_modules/buildbucket/examples/full.py#18)(api):**
+### *recipes* / [buildbucket:run/multi](/recipe_modules/buildbucket/run/multi.py)
+
+[DEPS](/recipe_modules/buildbucket/run/multi.py#12): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties)
+
+Launches multiple builds at the same revision.
+
+— **def [RunSteps](/recipe_modules/buildbucket/run/multi.py#29)(api, build_requests, collect_builds):**
### *recipes* / [buildbucket:tests/build](/recipe_modules/buildbucket/tests/build.py)
[DEPS](/recipe_modules/buildbucket/tests/build.py#9): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties), [step](#recipe_modules-step)
@@ -2365,9 +2375,9 @@
— **def [RunSteps](/recipe_modules/buildbucket/tests/build.py#16)(api):**
### *recipes* / [buildbucket:tests/collect](/recipe_modules/buildbucket/tests/collect.py)
-[DEPS](/recipe_modules/buildbucket/tests/collect.py#5): [buildbucket](#recipe_modules-buildbucket)
+[DEPS](/recipe_modules/buildbucket/tests/collect.py#5): [buildbucket](#recipe_modules-buildbucket), [properties](#recipe_modules-properties)
-— **def [RunSteps](/recipe_modules/buildbucket/tests/collect.py#10)(api):**
+— **def [RunSteps](/recipe_modules/buildbucket/tests/collect.py#11)(api):**
### *recipes* / [buildbucket:tests/get](/recipe_modules/buildbucket/tests/get.py)
[DEPS](/recipe_modules/buildbucket/tests/get.py#5): [buildbucket](#recipe_modules-buildbucket)
diff --git a/recipe_modules/buildbucket/api.py b/recipe_modules/buildbucket/api.py
index f11140b..17a624a 100644
--- a/recipe_modules/buildbucket/api.py
+++ b/recipe_modules/buildbucket/api.py
@@ -237,7 +237,7 @@
def run(
self, schedule_build_requests, collect_interval=None, timeout=None,
- url_title_fn=None, step_name=None):
+ url_title_fn=None, step_name=None, raise_if_unsuccessful=False):
"""Runs builds and returns results.
A shortcut for schedule() and collect_builds().
@@ -256,7 +256,9 @@
[b.id for b in builds],
interval=collect_interval,
timeout=timeout,
- step_name='collect')
+ step_name='collect',
+ raise_if_unsuccessful=raise_if_unsuccessful,
+ )
return [build_dict[b.id] for b in builds]
def schedule_request(
@@ -547,7 +549,9 @@
return build
def collect_builds(
- self, build_ids, interval=None, timeout=None, step_name=None):
+ self, build_ids, interval=None, timeout=None, step_name=None,
+ raise_if_unsuccessful=False
+ ):
"""Waits for a set of builds to end and returns their details.
Args:
@@ -556,6 +560,8 @@
Defaults to 1m.
* timeout: Maximum time to wait for builds to end. Defaults to 1h.
* step_name: Custom name for the generated step.
+ * raise_if_unsuccessful: if any build being collected did not succeed, raise
+ an exception.
Returns:
A map from integer build IDs to the corresponding
@@ -580,6 +586,16 @@
)
builds = [json_format.ParseDict(build_json, build_pb2.Build())
for build_json in result.json.output]
+ if raise_if_unsuccessful:
+ unsuccessful_builds = sorted(b.id for b in builds
+ if b.status != common_pb2.SUCCESS)
+ if unsuccessful_builds:
+ self.m.step.active_result.presentation.status = self.m.step.FAILURE
+ self.m.step.active_result.presentation.logs[
+ 'unsuccessful_builds'] = map(str, unsuccessful_builds)
+ raise self.m.step.InfraFailure(
+ 'Triggered build(s) did not succeed, unexpectedly')
+
return {build.id: build for build in builds}
# Internal.
diff --git a/recipe_modules/buildbucket/run/multi.expected/basic.json b/recipe_modules/buildbucket/run/multi.expected/basic.json
new file mode 100644
index 0000000..71977fd
--- /dev/null
+++ b/recipe_modules/buildbucket/run/multi.expected/basic.json
@@ -0,0 +1,111 @@
+[
+ {
+ "cmd": [
+ "bb",
+ "batch",
+ "-host",
+ "cr-buildbucket.appspot.com"
+ ],
+ "infra_step": true,
+ "name": "buildbucket.schedule",
+ "stdin": "{\"requests\": [{\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"linux\", \"project\": \"chromium\"}, \"requestId\": \"0-00000000-0000-0000-0000-000000001337\", \"tags\": [{\"key\": \"user_agent\", \"value\": \"recipe\"}]}}, {\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"win\", \"project\": \"chromium\"}, \"requestId\": \"0-00000000-0000-0000-0000-00000000133a\", \"tags\": [{\"key\": \"user_agent\", \"value\": \"recipe\"}]}}, {\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"mac\", \"project\": \"chromium\"}, \"requestId\": \"0-00000000-0000-0000-0000-00000000133d\", \"tags\": [{\"key\": \"user_agent\", \"value\": \"recipe\"}]}}]}",
+ "stdout": "/path/to/tmp/json",
+ "~followup_annotations": [
+ "@@@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\": \"linux\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"chromium\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514000\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@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\": \"win\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"chromium\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514001\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@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\": \"mac\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"chromium\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514002\"@@@",
+ "@@@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@ \"project\": \"chromium\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"builder\": \"linux\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"bucket\": \"ci\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ \"requestId\": \"0-00000000-0000-0000-0000-000000001337\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"tags\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"recipe\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"user_agent\"@@@",
+ "@@@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@ \"project\": \"chromium\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"builder\": \"win\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"bucket\": \"ci\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ \"requestId\": \"0-00000000-0000-0000-0000-00000000133a\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"tags\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"recipe\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"user_agent\"@@@",
+ "@@@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@ \"project\": \"chromium\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"builder\": \"mac\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"bucket\": \"ci\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ \"requestId\": \"0-00000000-0000-0000-0000-00000000133d\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"tags\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"recipe\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"user_agent\"@@@",
+ "@@@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@8922054662172514000@https://cr-buildbucket.appspot.com/build/8922054662172514000@@@",
+ "@@@STEP_LINK@8922054662172514001@https://cr-buildbucket.appspot.com/build/8922054662172514001@@@",
+ "@@@STEP_LINK@8922054662172514002@https://cr-buildbucket.appspot.com/build/8922054662172514002@@@"
+ ]
+ },
+ {
+ "jsonResult": null,
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipe_modules/buildbucket/run/multi.expected/collect.json b/recipe_modules/buildbucket/run/multi.expected/collect.json
new file mode 100644
index 0000000..331d07e
--- /dev/null
+++ b/recipe_modules/buildbucket/run/multi.expected/collect.json
@@ -0,0 +1,152 @@
+[
+ {
+ "cmd": [],
+ "name": "buildbucket.run"
+ },
+ {
+ "cmd": [
+ "bb",
+ "batch",
+ "-host",
+ "cr-buildbucket.appspot.com"
+ ],
+ "infra_step": true,
+ "name": "buildbucket.run.schedule",
+ "stdin": "{\"requests\": [{\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"linux\", \"project\": \"chromium\"}, \"requestId\": \"0-00000000-0000-0000-0000-000000001337\", \"tags\": [{\"key\": \"user_agent\", \"value\": \"recipe\"}]}}, {\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"win\", \"project\": \"chromium\"}, \"requestId\": \"0-00000000-0000-0000-0000-00000000133a\", \"tags\": [{\"key\": \"user_agent\", \"value\": \"recipe\"}]}}, {\"scheduleBuild\": {\"builder\": {\"bucket\": \"ci\", \"builder\": \"mac\", \"project\": \"chromium\"}, \"requestId\": \"0-00000000-0000-0000-0000-00000000133d\", \"tags\": [{\"key\": \"user_agent\", \"value\": \"recipe\"}]}}]}",
+ "stdout": "/path/to/tmp/json",
+ "~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\": \"linux\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"chromium\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514000\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@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\": \"win\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"chromium\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514001\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@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\": \"mac\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"chromium\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514002\"@@@",
+ "@@@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@ \"project\": \"chromium\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"builder\": \"linux\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"bucket\": \"ci\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ \"requestId\": \"0-00000000-0000-0000-0000-000000001337\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"tags\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"recipe\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"user_agent\"@@@",
+ "@@@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@ \"project\": \"chromium\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"builder\": \"win\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"bucket\": \"ci\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ \"requestId\": \"0-00000000-0000-0000-0000-00000000133a\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"tags\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"recipe\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"user_agent\"@@@",
+ "@@@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@ \"project\": \"chromium\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"builder\": \"mac\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"bucket\": \"ci\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ \"requestId\": \"0-00000000-0000-0000-0000-00000000133d\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"tags\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"recipe\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"user_agent\"@@@",
+ "@@@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@8922054662172514000@https://cr-buildbucket.appspot.com/build/8922054662172514000@@@",
+ "@@@STEP_LINK@8922054662172514001@https://cr-buildbucket.appspot.com/build/8922054662172514001@@@",
+ "@@@STEP_LINK@8922054662172514002@https://cr-buildbucket.appspot.com/build/8922054662172514002@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "buildbucket",
+ "collect",
+ "-host",
+ "cr-buildbucket.appspot.com",
+ "-json-output",
+ "/path/to/tmp/json",
+ "-interval",
+ "60s",
+ "8922054662172514000",
+ "8922054662172514001",
+ "8922054662172514002"
+ ],
+ "infra_step": true,
+ "name": "buildbucket.run.collect",
+ "timeout": 3600,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@[@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514000\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"status\": \"SUCCESS\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514001\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"status\": \"SUCCESS\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514002\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"status\": \"SUCCESS\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@]@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "jsonResult": null,
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipe_modules/buildbucket/run/multi.py b/recipe_modules/buildbucket/run/multi.py
new file mode 100644
index 0000000..d5cb8c2
--- /dev/null
+++ b/recipe_modules/buildbucket/run/multi.py
@@ -0,0 +1,83 @@
+# Copyright 2019 The LUCI Authors. All rights reserved.
+# Use of this source code is governed under the Apache License, Version 2.0
+# that can be found in the LICENSE file.
+
+"""Launches multiple builds at the same revision."""
+
+from recipe_engine.config import List
+from recipe_engine.config import Single
+from recipe_engine.recipe_api import Property
+
+
+DEPS = [
+ 'buildbucket',
+ 'properties',
+]
+
+PROPERTIES = {
+ 'build_requests': Property(
+ kind=List(dict),
+ help='List of params to buildbucket.schedule_request for builds'
+ ' to trigger.'),
+ 'collect_builds': Property(
+ kind=Single(bool),
+ default=False,
+ help='Whether to wait for child builds and surface failures.'),
+}
+
+
+def RunSteps(api, build_requests, collect_builds):
+ builds_to_schedule = []
+ for params in build_requests:
+ builds_to_schedule.append(api.buildbucket.schedule_request(**params))
+ if collect_builds:
+ api.buildbucket.run(builds_to_schedule, raise_if_unsuccessful=True)
+ else:
+ api.buildbucket.schedule(builds_to_schedule)
+
+
+def GenTests(api):
+ yield (
+ api.test('basic') +
+ api.properties(
+ build_requests=[
+ {
+ 'builder': 'linux',
+ 'project': 'chromium',
+ 'bucket': 'ci',
+ },
+ {
+ 'builder': 'win',
+ 'project': 'chromium',
+ 'bucket': 'ci',
+ },
+ {
+ 'builder': 'mac',
+ 'project': 'chromium',
+ 'bucket': 'ci',
+ },
+ ])
+ )
+ yield (
+ api.test('collect') +
+ api.properties(
+ build_requests=[
+ {
+ 'builder': 'linux',
+ 'project': 'chromium',
+ 'bucket': 'ci',
+ },
+ {
+ 'builder': 'win',
+ 'project': 'chromium',
+ 'bucket': 'ci',
+ },
+ {
+ 'builder': 'mac',
+ 'project': 'chromium',
+ 'bucket': 'ci',
+ },
+ ],
+ collect_builds=True,
+ )
+ )
diff --git a/recipe_modules/buildbucket/tests/collect.expected/with mocking and failure raising.json b/recipe_modules/buildbucket/tests/collect.expected/with mocking and failure raising.json
new file mode 100644
index 0000000..9f84db2
--- /dev/null
+++ b/recipe_modules/buildbucket/tests/collect.expected/with mocking and failure raising.json
@@ -0,0 +1,119 @@
+[
+ {
+ "cmd": [
+ "buildbucket",
+ "collect",
+ "-host",
+ "cr-buildbucket.appspot.com",
+ "-json-output",
+ "/path/to/tmp/json",
+ "-interval",
+ "30s",
+ "9016911228971028736"
+ ],
+ "infra_step": true,
+ "name": "collect1",
+ "timeout": 3600,
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@[@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"builder\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"bucket\": \"ci\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"builder\": \"builder\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"project\"@@@",
+ "@@@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\": \"9016911228971028736\", @@@",
+ "@@@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\": \"project\", @@@",
+ "@@@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\": \"INFRA_FAILURE\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@]@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_EXCEPTION@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "buildbucket",
+ "collect",
+ "-host",
+ "cr-buildbucket.appspot.com",
+ "-json-output",
+ "/path/to/tmp/json",
+ "-interval",
+ "60s",
+ "9016911228971028737",
+ "123456789012345678"
+ ],
+ "infra_step": true,
+ "name": "buildbucket.collect",
+ "timeout": 600,
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@[@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"builder\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"bucket\": \"try\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"builder\": \"builder\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"project\"@@@",
+ "@@@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\": \"9016911228971028737\", @@@",
+ "@@@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\": \"project\"@@@",
+ "@@@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@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"builder\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"bucket\": \"ci\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"builder\": \"builder\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"project\"@@@",
+ "@@@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\": \"123456789012345678\", @@@",
+ "@@@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\": \"project\", @@@",
+ "@@@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\": \"FAILURE\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@]@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LOG_LINE@unsuccessful_builds@123456789012345678@@@",
+ "@@@STEP_LOG_END@unsuccessful_builds@@@",
+ "@@@STEP_FAILURE@@@"
+ ]
+ },
+ {
+ "failure": {
+ "exception": {
+ "traceback": [
+ "<omitted by recipe engine>"
+ ]
+ },
+ "humanReason": "Triggered build(s) did not succeed, unexpectedly"
+ },
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipe_modules/buildbucket/tests/collect.py b/recipe_modules/buildbucket/tests/collect.py
index 175182f..e55c2a5 100644
--- a/recipe_modules/buildbucket/tests/collect.py
+++ b/recipe_modules/buildbucket/tests/collect.py
@@ -4,6 +4,7 @@
DEPS = [
'buildbucket',
+ 'properties',
]
@@ -12,7 +13,8 @@
9016911228971028736, interval=30, step_name='collect1',
mirror_status=True)
api.buildbucket.collect_builds(
- [9016911228971028737, 123456789012345678], timeout=600)
+ [9016911228971028737, 123456789012345678], timeout=600,
+ raise_if_unsuccessful=api.properties.get('raise_if_unsuccessful', False))
def GenTests(api):
@@ -33,3 +35,20 @@
build_id=123456789012345678, status='FAILURE'),
])
)
+
+ yield (
+ api.test('with mocking and failure raising') +
+ api.properties(raise_if_unsuccessful=True) +
+ api.buildbucket.simulated_collect_output(
+ [
+ api.buildbucket.ci_build_message(
+ build_id=9016911228971028736, status='INFRA_FAILURE'),
+ ],
+ step_name='collect1') +
+ api.buildbucket.simulated_collect_output([
+ api.buildbucket.try_build_message(
+ build_id=9016911228971028737, status='SUCCESS'),
+ api.buildbucket.ci_build_message(
+ build_id=123456789012345678, status='FAILURE'),
+ ])
+ )
diff --git a/recipe_modules/buildbucket/tests/schedule.expected/mirror_failure.json b/recipe_modules/buildbucket/tests/schedule.expected/mirror_failure.json
new file mode 100644
index 0000000..2758ed5
--- /dev/null
+++ b/recipe_modules/buildbucket/tests/schedule.expected/mirror_failure.json
@@ -0,0 +1,198 @@
+[
+ {
+ "cmd": [
+ "bb",
+ "batch",
+ "-host",
+ "cr-buildbucket.appspot.com"
+ ],
+ "infra_step": true,
+ "name": "buildbucket.schedule",
+ "stdin": "{\"requests\": [{\"scheduleBuild\": {\"builder\": {\"bucket\": \"try\", \"builder\": \"linux\", \"project\": \"chromium\"}, \"gerritChanges\": [{\"change\": \"123456\", \"host\": \"chromium-review.googlesource.com\", \"patchset\": \"7\", \"project\": \"chromium/src\"}], \"gitilesCommit\": {\"host\": \"chromium.googlesource.com\", \"id\": \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", \"project\": \"chromium/src\"}, \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-000000001337\", \"tags\": [{\"key\": \"buildset\", \"value\": \"bs\"}, {\"key\": \"user_agent\", \"value\": \"recipe\"}]}}]}",
+ "stdout": "/path/to/tmp/json",
+ "~followup_annotations": [
+ "@@@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\": \"linux\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"chromium\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514000\"@@@",
+ "@@@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@ \"project\": \"chromium\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"builder\": \"linux\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"bucket\": \"try\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ \"gerritChanges\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"project\": \"chromium/src\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"host\": \"chromium-review.googlesource.com\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"patchset\": \"7\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"change\": \"123456\"@@@",
+ "@@@STEP_LOG_LINE@request@ }@@@",
+ "@@@STEP_LOG_LINE@request@ ], @@@",
+ "@@@STEP_LOG_LINE@request@ \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-000000001337\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"tags\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"bs\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"buildset\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"recipe\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"user_agent\"@@@",
+ "@@@STEP_LOG_LINE@request@ }@@@",
+ "@@@STEP_LOG_LINE@request@ ], @@@",
+ "@@@STEP_LOG_LINE@request@ \"gitilesCommit\": {@@@",
+ "@@@STEP_LOG_LINE@request@ \"project\": \"chromium/src\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"host\": \"chromium.googlesource.com\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"id\": \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"@@@",
+ "@@@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@8922054662172514000@https://cr-buildbucket.appspot.com/build/8922054662172514000@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "buildbucket.run"
+ },
+ {
+ "cmd": [
+ "bb",
+ "batch",
+ "-host",
+ "cr-buildbucket.appspot.com"
+ ],
+ "infra_step": true,
+ "name": "buildbucket.run.schedule",
+ "stdin": "{\"requests\": [{\"scheduleBuild\": {\"builder\": {\"bucket\": \"try\", \"builder\": \"linux\", \"project\": \"chromium\"}, \"gerritChanges\": [{\"change\": \"123456\", \"host\": \"chromium-review.googlesource.com\", \"patchset\": \"7\", \"project\": \"chromium/src\"}], \"gitilesCommit\": {\"host\": \"chromium.googlesource.com\", \"id\": \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", \"project\": \"chromium/src\"}, \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-000000001337\", \"tags\": [{\"key\": \"buildset\", \"value\": \"bs\"}, {\"key\": \"user_agent\", \"value\": \"recipe\"}]}}]}",
+ "stdout": "/path/to/tmp/json",
+ "~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\": \"linux\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"chromium\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"id\": \"8922054662172514001\"@@@",
+ "@@@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@ \"project\": \"chromium\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"builder\": \"linux\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"bucket\": \"try\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ \"gerritChanges\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"project\": \"chromium/src\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"host\": \"chromium-review.googlesource.com\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"patchset\": \"7\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"change\": \"123456\"@@@",
+ "@@@STEP_LOG_LINE@request@ }@@@",
+ "@@@STEP_LOG_LINE@request@ ], @@@",
+ "@@@STEP_LOG_LINE@request@ \"requestId\": \"8945511751514863184-00000000-0000-0000-0000-000000001337\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"tags\": [@@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"bs\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"buildset\"@@@",
+ "@@@STEP_LOG_LINE@request@ }, @@@",
+ "@@@STEP_LOG_LINE@request@ {@@@",
+ "@@@STEP_LOG_LINE@request@ \"value\": \"recipe\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"key\": \"user_agent\"@@@",
+ "@@@STEP_LOG_LINE@request@ }@@@",
+ "@@@STEP_LOG_LINE@request@ ], @@@",
+ "@@@STEP_LOG_LINE@request@ \"gitilesCommit\": {@@@",
+ "@@@STEP_LOG_LINE@request@ \"project\": \"chromium/src\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"host\": \"chromium.googlesource.com\", @@@",
+ "@@@STEP_LOG_LINE@request@ \"id\": \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"@@@",
+ "@@@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@8922054662172514001@https://cr-buildbucket.appspot.com/build/8922054662172514001@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "buildbucket",
+ "collect",
+ "-host",
+ "cr-buildbucket.appspot.com",
+ "-json-output",
+ "/path/to/tmp/json",
+ "-interval",
+ "60s",
+ "8922054662172514001"
+ ],
+ "infra_step": true,
+ "name": "buildbucket.run.collect",
+ "timeout": 3600,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@[@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"builder\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"bucket\": \"ci\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"builder\": \"builder\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"project\": \"project\"@@@",
+ "@@@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\": \"8922054662172514001\", @@@",
+ "@@@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\": \"project\", @@@",
+ "@@@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\": \"FAILURE\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@]@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LOG_LINE@unsuccessful_builds@8922054662172514001@@@",
+ "@@@STEP_LOG_END@unsuccessful_builds@@@",
+ "@@@STEP_FAILURE@@@"
+ ]
+ },
+ {
+ "failure": {
+ "exception": {
+ "traceback": [
+ "<omitted by recipe engine>"
+ ]
+ },
+ "humanReason": "Triggered build(s) did not succeed, unexpectedly"
+ },
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipe_modules/buildbucket/tests/schedule.py b/recipe_modules/buildbucket/tests/schedule.py
index a3b3565..02f424c 100644
--- a/recipe_modules/buildbucket/tests/schedule.py
+++ b/recipe_modules/buildbucket/tests/schedule.py
@@ -23,7 +23,8 @@
req = api.buildbucket.schedule_request(tags=tags, **req_body)
api.buildbucket.schedule([req])
- api.buildbucket.run([req])
+ api.buildbucket.run([req], raise_if_unsuccessful=api.properties.get(
+ 'raise_failed_status'))
def GenTests(api):
@@ -94,3 +95,11 @@
test(test_name='error') +
api.buildbucket.simulated_schedule_output(err_batch_res)
)
+ yield (
+ test(test_name='mirror_failure') +
+ api.properties(raise_failed_status=True) +
+ api.buildbucket.simulated_collect_output([
+ api.buildbucket.ci_build_message(
+ build_id=8922054662172514001, status='FAILURE'),
+ ], step_name='buildbucket.run.collect')
+ )