Store results to cloud storage by configuration, as well as by builder

The results, logs, and flakiness are stored separately
for each configuration, in addition to by builder.
For each configuration appearing in results.json,
the cloud storage files
gs://dart-test-results/configuration/[channel]/[configuration]/latest
gs://dart-test-results/configuration/[channel]/[configuration]/[build number]/results.json
gs://dart-test-results/configuration/[channel]/[configuration]/[build number]/logs.json
gs://dart-test-results/configuration/[channel]/[configuration]/[build number]/flaky.json
gs://dart-test-results/configuration/[channel]/[configuration]/[build number]/revision
are created.

These new uploads will be inconsistent if more than one builder per
channel runs the same configuration, so we are disallowing that.
We plan to deprecate the per-builder uploads, and eventually remove
them, using the per-configuration uploads everywhere.

For experimental runs triggered by led, the cloud storage files are
created in the subdirectory
gs://dart-test-results/experimental/

Fixes: https://github.com/dart-lang/dart_ci/issues/81
Change-Id: I95b0989a01ef8d2a11473fc37ffeada7d4abb10b
Reviewed-on: https://dart-review.googlesource.com/c/recipes/+/145060
Reviewed-by: Alexander Thomas <athom@google.com>
diff --git a/README.recipes.md b/README.recipes.md
index c810732..72ff2ab 100644
--- a/README.recipes.md
+++ b/README.recipes.md
@@ -48,7 +48,7 @@
 
 Checks out the dart code and prepares it for building.
 
-&mdash; **def [collect\_all](/recipe_modules/dart/api.py#283)(self, steps):**
+&mdash; **def [collect\_all](/recipe_modules/dart/api.py#288)(self, steps):**
 
 Collects the results of a sharded test run.
 
@@ -60,11 +60,11 @@
 
 Returns the path to the checked-in SDK dart executable.
 
-&mdash; **def [delete\_debug\_log](/recipe_modules/dart/api.py#573)(self):**
+&mdash; **def [delete\_debug\_log](/recipe_modules/dart/api.py#606)(self):**
 
 Deletes the debug log file
 
-&mdash; **def [download\_browser](/recipe_modules/dart/api.py#853)(self, runtime, version):**
+&mdash; **def [download\_browser](/recipe_modules/dart/api.py#888)(self, runtime, version):**
 
 &mdash; **def [download\_parent\_isolate](/recipe_modules/dart/api.py#155)(self):**
 
@@ -76,7 +76,7 @@
 
 Kills leftover tasks from previous runs or steps.
 
-&mdash; **def [read\_debug\_log](/recipe_modules/dart/api.py#561)(self):**
+&mdash; **def [read\_debug\_log](/recipe_modules/dart/api.py#594)(self):**
 
 Reads the debug log file
 
@@ -85,7 +85,7 @@
 Runs test.py in the given isolate, sharded over several swarming tasks.
 Returns the created tasks, which can be collected with collect_all().
 
-&mdash; **def [test](/recipe_modules/dart/api.py#579)(self, test_data):**
+&mdash; **def [test](/recipe_modules/dart/api.py#612)(self, test_data):**
 
 Reads the test-matrix.json file in checkout and runs each step listed
 in the file.
@@ -179,7 +179,7 @@
 
 [DEPS](/recipe_modules/dart/examples/example.py#19): [dart](#recipe_modules-dart), [depot\_tools/tryserver][depot_tools/recipe_modules/tryserver], [recipe\_engine/buildbucket][recipe_engine/recipe_modules/buildbucket], [recipe\_engine/file][recipe_engine/recipe_modules/file], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/properties][recipe_engine/recipe_modules/properties], [recipe\_engine/raw\_io][recipe_engine/recipe_modules/raw_io], [recipe\_engine/runtime][recipe_engine/recipe_modules/runtime], [recipe\_engine/step][recipe_engine/recipe_modules/step], [recipe\_engine/swarming][recipe_engine/recipe_modules/swarming]
 
-&mdash; **def [RunSteps](/recipe_modules/dart/examples/example.py#315)(api):**
+&mdash; **def [RunSteps](/recipe_modules/dart/examples/example.py#321)(api):**
 ### *recipes* / [dart:examples/example-get\_secret](/recipe_modules/dart/examples/example-get_secret.py)
 
 [DEPS](/recipe_modules/dart/examples/example-get_secret.py#7): [dart](#recipe_modules-dart), [recipe\_engine/platform][recipe_engine/recipe_modules/platform]
diff --git a/recipe_modules/dart/api.py b/recipe_modules/dart/api.py
index ea2fa78..28e62bb 100644
--- a/recipe_modules/dart/api.py
+++ b/recipe_modules/dart/api.py
@@ -265,19 +265,24 @@
     return self.m.swarming.trigger('trigger shards for %s' % name, tasks)
 
 
+  def _channel(self):
+    channel = self.m.buildbucket.builder_name.split('-')[-1]
+    if channel in ['beta', 'dev', 'stable', 'try']:
+      return channel
+    return 'master'
+
+
   def _release_builder(self):
     """Boolean that reports whether the builder is on the
        beta, dev or stable channels. Some steps are only
        run on the master and try builders."""
-    return (self.m.buildbucket.builder_name.endswith('-beta') or
-            self.m.buildbucket.builder_name.endswith('-dev') or
-            self.m.buildbucket.builder_name.endswith('-stable'))
+    return self._channel() in ['beta', 'dev', 'stable']
 
 
   def _try_builder(self):
     """Boolean that reports whether this a try builder.
        Some steps are not run on the try builders."""
-    return self.m.buildbucket.builder_name.endswith('-try')
+    return self._channel() == 'try'
 
 
   def collect_all(self, steps):
@@ -403,36 +408,64 @@
     return flaky_json.raw_io.output_texts.get('flaky.json')
 
 
-  def _upload_results_to_cloud(self, flaky_json_str, logs_str, results_str):
-    builder = str(self.m.buildbucket.builder_name)
-    build_revision = str(self.m.buildbucket.gitiles_commit.id)
+  def _upload_configurations_to_cloud(self, flaky_str, logs_str, results_str):
+
+    def by_configuration(json_lines):
+      result = {}
+      for line in (json_lines or '').splitlines():
+        result.setdefault(json.loads(line)['configuration'], []).append(line)
+      return result
+
+    results = by_configuration(results_str)
+    logs = by_configuration(logs_str)
+    flaky = by_configuration(flaky_str)
+
+    def to_lines(json_list):
+      json_list.append('')
+      return '\n'.join(json_list)
+
+    for configuration in results:
+      self._upload_results_to_cloud(
+          to_lines(flaky.get(configuration, [])),
+          to_lines(logs.get(configuration, [])),
+          to_lines(results[configuration]), configuration)
+
+  def _upload_results_to_cloud(self, flaky_json_str, logs_str, results_str,
+                               configuration):
+    builder = self.m.buildbucket.builder_name
+    build_revision = self.m.buildbucket.gitiles_commit.id
     build_number = str(self.m.buildbucket.build.number)
-    self._upload_result(builder, build_number, 'revision', build_revision)
-    self._upload_result(builder, build_number, 'logs.json', logs_str)
-    self._upload_result(builder, build_number, 'results.json', results_str)
-    self._upload_result(builder, build_number, 'flaky.json', flaky_json_str)
-    if not self._release_builder():
-      self._upload_result('current_flakiness', 'single_directory',
+
+    if configuration:
+      path = 'configuration/%s/%s' % (self._channel(), configuration)
+    else:
+      path = 'builders/%s' % builder
+    if (self.m.runtime.is_experimental):
+      path = 'experimental/%s' % path
+    self._upload_result(path, build_number, 'revision', build_revision)
+    self._upload_result(path, build_number, 'logs.json', logs_str)
+    self._upload_result(path, build_number, 'results.json', results_str)
+    self._upload_result(path, build_number, 'flaky.json', flaky_json_str)
+    if (not self._release_builder() and not configuration and
+        not self.m.runtime.is_experimental):
+      self._upload_result('builders/current_flakiness', 'single_directory',
                           'flaky_current_%s.json' % builder, flaky_json_str)
     # Update "latest" file
     new_latest = self.m.raw_io.input_text(build_number, name='latest')
     args = [
         new_latest,
         'dart-test-results',
-        'builders/%s/%s' % (builder, 'latest'),
+        '%s/%s' % (path, 'latest'),
     ]
-    if not self.m.runtime.is_experimental:
-      self.m.gsutil.upload(*args, name='update "latest" reference')
+    self.m.gsutil.upload(*args, name='update "latest" reference')
 
-
-  def _upload_result(self, builder, build_number, filename, result_str):
+  def _upload_result(self, path, build_number, filename, result_str):
     args = [
         self.m.raw_io.input_text(str(result_str), name=filename),
         'dart-test-results',
-        'builders/%s/%s/%s' % (builder, build_number, filename),
+        '%s/%s/%s' % (path, build_number, filename),
     ]
-    if not self.m.runtime.is_experimental:
-      self.m.gsutil.upload(*args, name='upload %s' % filename)
+    self.m.gsutil.upload(*args, name='upload %s' % filename)
 
 
   def _publish_results(self, results_str):
@@ -844,7 +877,9 @@
               self._publish_results(results_str)
             if not self._try_builder():
               self._upload_results_to_cloud(flaky_json_str, logs_str,
-                                            results_str)
+                                            results_str, None)
+              self._upload_configurations_to_cloud(flaky_json_str, logs_str,
+                                                   results_str)
               self._upload_results_to_bq(results_str)
         finally:
           self._present_results(logs_str, results_str, flaky_json_str)
diff --git a/recipe_modules/dart/examples/example.expected/analyzer-linux-release.json b/recipe_modules/dart/examples/example.expected/analyzer-linux-release.json
index ea0d060..356f127 100644
--- a/recipe_modules/dart/examples/example.expected/analyzer-linux-release.json
+++ b/recipe_modules/dart/examples/example.expected/analyzer-linux-release.json
@@ -1352,7 +1352,7 @@
     "infra_step": true,
     "name": "read logs.json for test2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1379,8 +1379,8 @@
     "infra_step": true,
     "name": "read results.json for test2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1544,7 +1544,7 @@
     "infra_step": true,
     "name": "read logs.json for test3_shard_2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1571,8 +1571,8 @@
     "infra_step": true,
     "name": "read results.json for test3_shard_2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1633,7 +1633,7 @@
     "infra_step": true,
     "name": "read logs.json for test1_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1651,8 +1651,8 @@
     "infra_step": true,
     "name": "read results.json for test1_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1713,7 +1713,7 @@
     "infra_step": true,
     "name": "read logs.json for test1_shard_2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1731,8 +1731,8 @@
     "infra_step": true,
     "name": "read results.json for test1_shard_2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1793,7 +1793,7 @@
     "infra_step": true,
     "name": "read logs.json for test3_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1811,8 +1811,8 @@
     "infra_step": true,
     "name": "read results.json for test3_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1913,7 +1913,7 @@
       "--count",
       "50",
       "LATEST/results.json",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -1982,7 +1982,7 @@
       "--count",
       "50",
       "LATEST/results.json",
-      "{\"name\":\"test1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\",\"bot_name\":\"trusty-dart-123\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"trusty-dart-123\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -2055,8 +2055,8 @@
     "name": "deflaking.read logs.json for test2",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/1\":\"log\"}@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/2\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -2084,8 +2084,8 @@
     "name": "deflaking.read results.json for test2",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -2101,7 +2101,7 @@
       "--count",
       "50",
       "LATEST/results.json",
-      "{\"name\":\"test1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -2174,8 +2174,8 @@
     "name": "deflaking.read logs.json for test3",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/1\":\"log\"}@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/2\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -2203,8 +2203,8 @@
     "name": "deflaking.read results.json for test3",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -2269,8 +2269,8 @@
     "name": "deflaking.read logs.json for test1_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/1\":\"log\"}@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/2\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -2290,8 +2290,8 @@
     "name": "deflaking.read results.json for test1_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -2307,7 +2307,7 @@
       "8945511751514863184",
       "--commit",
       "3456abce78ef",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"trusty-dart-123\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -2332,7 +2332,7 @@
     "cmd": [
       "[CACHE]/builder/sdk/tools/sdks/dart-sdk/bin/dart",
       "[CACHE]/builder/sdk/tools/bots/extend_results.dart",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"trusty-dart-123\"}\n",
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"trusty-dart-123\"}\n",
       "[CACHE]/builder/sdk/LATEST/results.json",
       "",
       "[CACHE]/builder/sdk/LATEST/flaky.json",
@@ -2415,7 +2415,7 @@
       "RECIPE_REPO[depot_tools]/gsutil.py",
       "----",
       "cp",
-      "{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}",
+      "{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n",
       "gs://dart-test-results/builders/analyzer-linux-release/1357/logs.json"
     ],
     "cwd": "[CACHE]/builder/sdk",
@@ -2508,6 +2508,106 @@
   },
   {
     "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "3456abce78ef",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/1357/revision"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload revision (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/1357/revision@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/1357/logs.json"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload logs.json (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/1357/logs.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t01\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t01\",\"time_ms\":451,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t02\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t02\",\"time_ms\":496,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/1357/results.json"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload results.json (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/1357/results.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/1357/flaky.json"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload flaky.json (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/1357/flaky.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "1357",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/latest"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil update \"latest\" reference (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/latest@@@"
+    ]
+  },
+  {
+    "cmd": [
       "cipd",
       "ensure",
       "-root",
@@ -2588,7 +2688,7 @@
       "[CACHE]/builder/sdk/LATEST/results.json",
       "{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t01\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t01\",\"time_ms\":451,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t02\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t02\",\"time_ms\":496,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n",
       "--logs",
-      "{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}",
+      "{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n",
       "--logs-only",
       "--changed",
       "--failing"
@@ -2631,7 +2731,7 @@
       "[CACHE]/builder/sdk/LATEST/results.json",
       "{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t01\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t01\",\"time_ms\":451,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t02\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t02\",\"time_ms\":496,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n",
       "--logs",
-      "{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}",
+      "{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n",
       "--logs-only",
       "--flaky"
     ],
diff --git a/recipe_modules/dart/examples/example.expected/basic-mac.json b/recipe_modules/dart/examples/example.expected/basic-mac.json
index d247264..819488e 100644
--- a/recipe_modules/dart/examples/example.expected/basic-mac.json
+++ b/recipe_modules/dart/examples/example.expected/basic-mac.json
@@ -1586,6 +1586,106 @@
   },
   {
     "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+      "gs://dart-test-results/configuration/dev/dartk-linux-product-x64/1357/revision"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload revision (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/dev/dartk-linux-product-x64/1357/revision@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "",
+      "gs://dart-test-results/configuration/dev/dartk-linux-product-x64/1357/logs.json"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload logs.json (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/dev/dartk-linux-product-x64/1357/logs.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t01\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t01\",\"time_ms\":451,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t02\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t02\",\"time_ms\":496,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n",
+      "gs://dart-test-results/configuration/dev/dartk-linux-product-x64/1357/results.json"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload results.json (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/dev/dartk-linux-product-x64/1357/results.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "",
+      "gs://dart-test-results/configuration/dev/dartk-linux-product-x64/1357/flaky.json"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload flaky.json (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/dev/dartk-linux-product-x64/1357/flaky.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]/gsutil.py",
+      "----",
+      "cp",
+      "1357",
+      "gs://dart-test-results/configuration/dev/dartk-linux-product-x64/latest"
+    ],
+    "cwd": "[CACHE]/builder/sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil update \"latest\" reference (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/dev/dartk-linux-product-x64/latest@@@"
+    ]
+  },
+  {
+    "cmd": [
       "cipd",
       "ensure",
       "-root",
diff --git a/recipe_modules/dart/examples/example.expected/basic.json b/recipe_modules/dart/examples/example.expected/basic.json
index a0768a8..6f2a65b 100644
--- a/recipe_modules/dart/examples/example.expected/basic.json
+++ b/recipe_modules/dart/examples/example.expected/basic.json
@@ -1091,7 +1091,7 @@
     "infra_step": true,
     "name": "read logs.json for custom_runner",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1118,8 +1118,8 @@
     "infra_step": true,
     "name": "read results.json for custom_runner",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1182,7 +1182,7 @@
     "infra_step": true,
     "name": "read logs.json for test2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1209,8 +1209,8 @@
     "infra_step": true,
     "name": "read results.json for test2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1271,7 +1271,7 @@
     "infra_step": true,
     "name": "read logs.json for test1_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1289,8 +1289,8 @@
     "infra_step": true,
     "name": "read results.json for test1_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1351,7 +1351,7 @@
     "infra_step": true,
     "name": "read logs.json for test1_shard_2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1369,8 +1369,8 @@
     "infra_step": true,
     "name": "read results.json for test1_shard_2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1511,7 +1511,7 @@
       "--count",
       "50",
       "LATEST/results.json",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -1580,7 +1580,7 @@
       "--count",
       "50",
       "LATEST/results.json",
-      "{\"name\":\"test1\",\"bot_name\":\"None\"}\n{\"name\":\"test2\",\"bot_name\":\"None\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"None\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"None\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -1658,8 +1658,8 @@
     "name": "deflaking.read logs.json for test2",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/1\":\"log\"}@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/2\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1687,8 +1687,8 @@
     "name": "deflaking.read results.json for test2",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1753,8 +1753,8 @@
     "name": "deflaking.read logs.json for test1_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/1\":\"log\"}@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/2\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1774,8 +1774,8 @@
     "name": "deflaking.read results.json for test1_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1791,7 +1791,7 @@
       "8945511751514863184",
       "--commit",
       "",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"None\"}\n{\"name\":\"test2\",\"bot_name\":\"None\"}\n{\"name\":\"test1\",\"bot_name\":\"None\"}\n{\"name\":\"test2\",\"bot_name\":\"None\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"None\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"None\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"None\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"None\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"None\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"None\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"None\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"None\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -1816,7 +1816,7 @@
     "cmd": [
       "[CACHE]/builder/sdk/tools/sdks/dart-sdk/bin/dart",
       "[CACHE]/builder/sdk/tools/bots/extend_results.dart",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"None\"}\n{\"name\":\"test2\",\"bot_name\":\"None\"}\n{\"name\":\"test1\",\"bot_name\":\"None\"}\n{\"name\":\"test2\",\"bot_name\":\"None\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"None\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"None\"}\n",
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"None\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"None\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"None\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"None\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"None\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"None\"}\n",
       "[CACHE]/builder/sdk/LATEST/results.json",
       "",
       "[CACHE]/builder/sdk/LATEST/flaky.json",
@@ -1901,7 +1901,7 @@
       "[CACHE]/builder/sdk/LATEST/results.json",
       "{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t01\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t01\",\"time_ms\":451,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t02\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t02\",\"time_ms\":496,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n",
       "--logs",
-      "{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}",
+      "{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n",
       "--logs-only",
       "--changed",
       "--failing"
diff --git a/recipe_modules/dart/examples/example.expected/co19.json b/recipe_modules/dart/examples/example.expected/co19.json
index 55c872c..d3532cf 100644
--- a/recipe_modules/dart/examples/example.expected/co19.json
+++ b/recipe_modules/dart/examples/example.expected/co19.json
@@ -177,7 +177,7 @@
     "infra_step": true,
     "name": "read logs.json for co19_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -195,8 +195,8 @@
     "infra_step": true,
     "name": "read results.json for co19_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -212,7 +212,7 @@
       "--count",
       "50",
       "LATEST/results.json",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -330,8 +330,8 @@
     "name": "deflaking.read logs.json for co19_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/1\":\"log\"}@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/2\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -351,8 +351,8 @@
     "name": "deflaking.read results.json for co19_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
diff --git a/recipe_modules/dart/examples/example.expected/co19_2-legacy.json b/recipe_modules/dart/examples/example.expected/co19_2-legacy.json
index 4281d9a..2fbf61a 100644
--- a/recipe_modules/dart/examples/example.expected/co19_2-legacy.json
+++ b/recipe_modules/dart/examples/example.expected/co19_2-legacy.json
@@ -173,7 +173,7 @@
     "infra_step": true,
     "name": "read logs.json for co19_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -191,8 +191,8 @@
     "infra_step": true,
     "name": "read results.json for co19_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -208,7 +208,7 @@
       "--count",
       "50",
       "LATEST/results.json",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -326,8 +326,8 @@
     "name": "deflaking.read logs.json for co19_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/1\":\"log\"}@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/2\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -347,8 +347,8 @@
     "name": "deflaking.read results.json for co19_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
diff --git a/recipe_modules/dart/examples/example.expected/example-android.json b/recipe_modules/dart/examples/example.expected/example-android.json
index e709794..00ea385 100644
--- a/recipe_modules/dart/examples/example.expected/example-android.json
+++ b/recipe_modules/dart/examples/example.expected/example-android.json
@@ -986,7 +986,7 @@
     "infra_step": true,
     "name": "read logs.json for android_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1004,8 +1004,8 @@
     "infra_step": true,
     "name": "read results.json for android_shard_1",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1066,7 +1066,7 @@
     "infra_step": true,
     "name": "read logs.json for android_shard_2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"test\":\"test1\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1084,8 +1084,8 @@
     "infra_step": true,
     "name": "read results.json for android_shard_2",
     "~followup_annotations": [
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test1\", \"configuration\": example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"test2\", \"configuration\": example_configuration_2\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1186,7 +1186,7 @@
       "--count",
       "50",
       "LATEST/results.json",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -1304,8 +1304,8 @@
     "name": "deflaking.read logs.json for android_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/1\":\"log\"}@@@",
-      "@@@STEP_LOG_LINE@logs.json@{\"Flaky/Test/2\":\"log\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@logs.json@{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@logs.json@@@"
     ]
   },
@@ -1325,8 +1325,8 @@
     "name": "deflaking.read results.json for android_shard_1",
     "~followup_annotations": [
       "@@@STEP_NEST_LEVEL@1@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\"}@@@",
-      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\"}@@@",
+      "@@@STEP_LOG_LINE@results.json@{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\"}@@@",
       "@@@STEP_LOG_END@results.json@@@"
     ]
   },
@@ -1342,7 +1342,7 @@
       "8945511751514863184",
       "--commit",
       "2d72510e447ab60a9728aeea2362d8be2cbd7789",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"vm-123\"}\n"
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n"
     ],
     "cwd": "[CACHE]/builder/sdk",
     "infra_step": true,
@@ -1367,7 +1367,7 @@
     "cmd": [
       "[CACHE]/builder/sdk/tools/sdks/dart-sdk/bin/dart",
       "[CACHE]/builder/sdk/tools/bots/extend_results.dart",
-      "{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\",\"bot_name\":\"vm-123\"}\n",
+      "{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test1\", \"configuration\": example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"test2\", \"configuration\": example_configuration_2\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/1\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n{\"name\":\"Flaky/Test/2\", \"configuration\": \"example_configuration\",\"bot_name\":\"vm-123\"}\n",
       "[CACHE]/builder/sdk/LATEST/results.json",
       "",
       "[CACHE]/builder/sdk/LATEST/flaky.json",
@@ -1414,7 +1414,7 @@
       "RECIPE_REPO[depot_tools]/gsutil.py",
       "----",
       "cp",
-      "{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}",
+      "{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n",
       "gs://dart-test-results/builders/vm-kernel-precomp-android-release-armsimdbc64/0/logs.json"
     ],
     "cwd": "[CACHE]/builder/sdk",
@@ -1536,7 +1536,7 @@
       "[CACHE]/builder/sdk/LATEST/results.json",
       "",
       "--logs",
-      "{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}",
+      "{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n",
       "--logs-only",
       "--changed",
       "--failing"
@@ -1579,7 +1579,7 @@
       "[CACHE]/builder/sdk/LATEST/results.json",
       "",
       "--logs",
-      "{\"test\":\"log\"}\n{\"test\":\"log\"}\n{\"Flaky/Test/1\":\"log\"}\n{\"Flaky/Test/2\":\"log\"}",
+      "{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"test\":\"test1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/1\", \"configuration\": \"example_configuration\"}\n{\"name\": \"Flaky/Test/2\", \"configuration\": \"example_configuration\"}\n",
       "--logs-only",
       "--flaky"
     ],
diff --git a/recipe_modules/dart/examples/example.expected/vm-win.json b/recipe_modules/dart/examples/example.expected/vm-win.json
index b37f05f..b0806b9 100644
--- a/recipe_modules/dart/examples/example.expected/vm-win.json
+++ b/recipe_modules/dart/examples/example.expected/vm-win.json
@@ -2230,6 +2230,106 @@
   },
   {
     "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]\\resources\\gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]\\gsutil.py",
+      "----",
+      "cp",
+      "3456abce78ef",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/1357/revision"
+    ],
+    "cwd": "[CACHE]\\builder\\sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload revision (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/1357/revision@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]\\resources\\gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]\\gsutil.py",
+      "----",
+      "cp",
+      "",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/1357/logs.json"
+    ],
+    "cwd": "[CACHE]\\builder\\sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload logs.json (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/1357/logs.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]\\resources\\gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]\\gsutil.py",
+      "----",
+      "cp",
+      "{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t01\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t01\",\"time_ms\":451,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n{\"name\":\"co19_2/Language/Classes/Abstract_Instance_Members/inherited_t02\",\"configuration\":\"dartk-linux-product-x64\",\"suite\":\"co19_2\",\"test_name\":\"Language/Classes/Abstract_Instance_Members/inherited_t02\",\"time_ms\":496,\"result\":\"CompileTimeError\",\"expected\":\"CompileTimeError\",\"matches\":true,\"commit_time\":1551185312,\"commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"build_number\":\"2404\",\"builder_name\":\"vm-kernel-linux-product-x64\",\"bot_name\":\"trusty-dart-68765ebb-us-central1-b-2ls0\",\"flaky\":false,\"previous_flaky\":false,\"previous_result\":\"CompileTimeError\",\"previous_commit_hash\":\"f0042a32250a8a6193e6d07e2b6508b13f43c864\",\"previous_commit_time\":1551185312,\"previous_build_number\":2403,\"changed\":false}\n",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/1357/results.json"
+    ],
+    "cwd": "[CACHE]\\builder\\sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload results.json (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/1357/results.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]\\resources\\gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]\\gsutil.py",
+      "----",
+      "cp",
+      "",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/1357/flaky.json"
+    ],
+    "cwd": "[CACHE]\\builder\\sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil upload flaky.json (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/1357/flaky.json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[depot_tools::gsutil]\\resources\\gsutil_smart_retry.py",
+      "--",
+      "RECIPE_REPO[depot_tools]\\gsutil.py",
+      "----",
+      "cp",
+      "1357",
+      "gs://dart-test-results/configuration/master/dartk-linux-product-x64/latest"
+    ],
+    "cwd": "[CACHE]\\builder\\sdk",
+    "infra_step": true,
+    "name": "upload new results.gsutil update \"latest\" reference (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LINK@gsutil.upload@https://storage.cloud.google.com/dart-test-results/configuration/master/dartk-linux-product-x64/latest@@@"
+    ]
+  },
+  {
+    "cmd": [
       "cipd.bat",
       "ensure",
       "-root",
diff --git a/recipe_modules/dart/examples/example.py b/recipe_modules/dart/examples/example.py
index 7008eb0..cafdc89 100644
--- a/recipe_modules/dart/examples/example.py
+++ b/recipe_modules/dart/examples/example.py
@@ -32,14 +32,20 @@
 
 
 CANNED_OUTPUT_DIR = {
-  'logs.json': '{"test":"log"}\n',
-  'results.json': '{"name":"test1"}\n{"name":"test2"}\n',
+    'logs.json':
+        '{"test":"test1", "configuration": "example_configuration"}\n',
+    'results.json':
+        '{"name":"test1", "configuration": example_configuration"}\n'
+        '{"name":"test2", "configuration": example_configuration_2"}\n',
 }
 
-
 CANNED_FLAKY_OUTPUT_DIR = {
-  'logs.json': '{"Flaky/Test/1":"log"}\n{"Flaky/Test/2":"log"}',
-  'results.json': '{"name":"Flaky/Test/1"}\n{"name":"Flaky/Test/2"}\n',
+    'logs.json':
+        '{"name": "Flaky/Test/1", "configuration": "example_configuration"}\n'
+        '{"name": "Flaky/Test/2", "configuration": "example_configuration"}\n',
+    'results.json':
+        '{"name":"Flaky/Test/1", "configuration": "example_configuration"}\n'
+        '{"name":"Flaky/Test/2", "configuration": "example_configuration"}\n',
 }
 
 
@@ -421,8 +427,7 @@
       api.step_data('buildbucket.put', stdout=api.json.output(TRIGGER_RESULT)),
       api.step_data('add fields to result records',
                     api.raw_io.output_text(RESULT_DATA)),
-      api.post_process(DoesNotRunRE, r'.*gsutil (update|upload).*'),
-      api.post_process(DoesNotRunRE, r'.*(publish|upload) results.*'),
+      api.post_process(DoesNotRunRE, r'.*publish results.*'),
       api.post_process(StatusSuccess),
       api.post_process(DropExpectation),
   )