Use new defer module
Also, don't use any deferred logic in some places, like where there was
only one command being run.
Bug: chromium:1495428
Change-Id: If1221538c7b763a7215f2481c3635031e2b64115
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/51924
Reviewed-by: Keyong Han <keyonghan@google.com>
Commit-Queue: Rob Mohr <mohrr@google.com>
diff --git a/recipe_modules/goma/__init__.py b/recipe_modules/goma/__init__.py
index 0ee03a0..df453e1 100644
--- a/recipe_modules/goma/__init__.py
+++ b/recipe_modules/goma/__init__.py
@@ -10,6 +10,7 @@
"recipe_engine/buildbucket",
"recipe_engine/cipd",
"recipe_engine/context",
+ "recipe_engine/defer",
"recipe_engine/file",
"recipe_engine/json",
"recipe_engine/path",
diff --git a/recipe_modules/goma/api.py b/recipe_modules/goma/api.py
index 6e3eda5..73a0402 100644
--- a/recipe_modules/goma/api.py
+++ b/recipe_modules/goma/api.py
@@ -169,19 +169,21 @@
self._goma_ctl("start goma", ["restart"])
self._goma_started = True
except self.m.step.StepFailure: # pragma: no cover
- with self.m.step.defer_results():
- self._run_jsonstatus()
- self._goma_ctl("stop goma (start failure)", ["stop"])
+ deferred = []
+ deferred.append(self.m.defer(self._run_jsonstatus))
+ deferred.append(self.m.defer(self._goma_ctl, "stop goma (start failure)", ["stop"]))
+ self.m.defer.collect(deferred)
raise
def _stop(self):
"""Stop goma compiler proxy."""
assert self._goma_started
- with self.m.step.defer_results():
- self._run_jsonstatus()
- self._goma_ctl("goma stats", ["stat"])
- self._goma_ctl("stop goma", ["stop"])
+ deferred = []
+ deferred.append(self.m.defer(self._run_jsonstatus))
+ deferred.append(self.m.defer(self._goma_ctl, "goma stats", ["stat"]))
+ deferred.append(self.m.defer(self._goma_ctl, "stop goma", ["stop"]))
+ self.m.defer.collect(deferred)
self._goma_started = False
diff --git a/recipe_modules/goma/tests/full.expected/linux_stop_goma_failed.json b/recipe_modules/goma/tests/full.expected/linux_stop_goma_failed.json
index 3154436..fdf3e70 100644
--- a/recipe_modules/goma/tests/full.expected/linux_stop_goma_failed.json
+++ b/recipe_modules/goma/tests/full.expected/linux_stop_goma_failed.json
@@ -282,8 +282,38 @@
]
},
{
+ "cmd": [],
+ "name": "teardown goma.collect",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_TEXT@1 deferred failures@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@Traceback (most recent call last):@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ File \"RECIPE_REPO[recipe_engine]/recipe_modules/defer/api.py\", in __call__@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ return DeferredResult(_api=self.m, _value=func(*args, **kwargs))@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ File \"RECIPE_REPO[recipe_engine]/recipe_engine/recipe_api.py\", in _inner@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ return func(*a, **kw)@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ File \"RECIPE_REPO[flutter]/recipe_modules/goma/api.py\", line 117, in _goma_ctl@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ return self.m.python3(@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ File \"RECIPE_REPO[recipe_engine]/recipe_engine/recipe_api.py\", in _inner@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ return func(*a, **kw)@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ File \"RECIPE_REPO[fuchsia]/recipe_modules/python3/api.py\", in __call__@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ return self.m.step(name, cmd, **kwargs)@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ File \"RECIPE_REPO[recipe_engine]/recipe_engine/recipe_api.py\", in _inner@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ return func(*a, **kw)@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ File \"RECIPE_REPO[recipe_engine]/recipe_modules/step/api.py\", in __call__@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ return self._run_or_raise_step(@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ File \"RECIPE_REPO[recipe_engine]/recipe_modules/step/api.py\", in _run_or_raise_step@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ return self._raise_on_disallowed_statuses(ret, allowed_statuses)@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ File \"RECIPE_REPO[recipe_engine]/recipe_modules/step/api.py\", in _raise_on_disallowed_statuses@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@ raise exc('.'.join(result.name_tokens), result)@@@",
+ "@@@STEP_LOG_LINE@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@recipe_engine.recipe_api.InfraFailure: Infra Failure: Step('teardown goma.stop goma') (retcode: 1)@@@",
+ "@@@STEP_LOG_END@InfraFailure(\"Infra Failure: Step('teardown goma.stop goma') (retcode: 1)\")@@@",
+ "@@@STEP_FAILURE@@@"
+ ]
+ },
+ {
"failure": {
- "humanReason": "1 out of 3 aggregated steps failed: Infra Failure: Step('teardown goma.stop goma') (retcode: 1)"
+ "humanReason": "Infra Failure: Step('teardown goma.stop goma') (retcode: 1)"
},
"name": "$result"
}
diff --git a/recipes/engine/engine_builder.py b/recipes/engine/engine_builder.py
index 8d86b37..c6dd7db 100644
--- a/recipes/engine/engine_builder.py
+++ b/recipes/engine/engine_builder.py
@@ -17,6 +17,7 @@
'recipe_engine/buildbucket',
'recipe_engine/cas',
'recipe_engine/context',
+ 'recipe_engine/defer',
'recipe_engine/file',
'recipe_engine/path',
'recipe_engine/platform',
@@ -55,7 +56,7 @@
api.step('gn %s' % ' '.join(args), gn_cmd)
else:
# Run gn within a context.
- env = {'GOMA_DIR': api.goma.goma_dir.get_result()}
+ env = {'GOMA_DIR': api.goma.goma_dir}
with api.context(env=env):
api.step('gn %s' % ' '.join(args), gn_cmd)
@@ -79,13 +80,19 @@
output_files = []
output_dirs = []
- with api.osx_sdk('ios'), api.depot_tools.on_path(), api.context(
- env=env), api.step.defer_results():
+ with api.osx_sdk('ios'), api.depot_tools.on_path(), api.context(env=env):
+ deferred = []
for build in properties.builds:
with api.step.nest('build %s (%s)' %
(build.dir, ','.join(build.targets))):
- RunGN(api, build.disable_goma, *build.gn_args)
- Build(api, build.dir, build.disable_goma, *build.targets)
+ deferred.append(
+ api.defer(RunGN, api, build.disable_goma, *build.gn_args)
+ )
+ deferred.append(
+ api.defer(
+ Build, api, build.dir, build.disable_goma, *build.targets
+ )
+ )
for output_file in build.output_files:
output_files.append(
cache_root.join('src', 'out', build.dir, output_file)
@@ -95,9 +102,10 @@
cache_root.join('src', 'out', build.dir, output_dir)
)
# This is to clean up leaked processes.
- api.os_utils.kill_processes()
+ deferred.append(api.defer(api.os_utils.kill_processes))
# Collect memory/cpu/process after task execution.
- api.os_utils.collect_os_info()
+ deferred.append(api.defer(api.os_utils.collect_os_info))
+ api.defer.collect(deferred)
cas_hash = CasOutputs(api, output_files, output_dirs)
output_props = api.step('Set output properties', None)
diff --git a/recipes/engine/femu_test.py b/recipes/engine/femu_test.py
index 5e75a5f..20e0224 100644
--- a/recipes/engine/femu_test.py
+++ b/recipes/engine/femu_test.py
@@ -255,8 +255,7 @@
# TODO(http://fxb/121613): Emulator instances are not cleaned up
# when tests fail. Added a clean up step before tests start to
# stop all running emulators.
- with api.step.defer_results():
- api.retry.step('run ffx test', [ffx] + suite['test_command'].split(' '))
+ api.retry.step('run ffx test', [ffx] + suite['test_command'].split(' '))
def ReadLogFiles(api, ffx):
diff --git a/recipes/flutter/android_views.py b/recipes/flutter/android_views.py
index f396b6f..acfe365 100644
--- a/recipes/flutter/android_views.py
+++ b/recipes/flutter/android_views.py
@@ -16,6 +16,7 @@
'flutter/repo_util',
'flutter/retry',
'recipe_engine/context',
+ 'recipe_engine/defer',
'recipe_engine/file',
'recipe_engine/path',
'recipe_engine/properties',
@@ -62,25 +63,40 @@
views_test_dir = checkout_path.join(
'dev', 'integration_tests', 'android_views'
)
- with api.step.nest('prepare environment'), api.step.defer_results():
+ with api.step.nest('prepare environment'):
+ deferred = []
# This prevents junk analytics from being sent due to testing
- api.step(
- 'flutter config --no-analytics',
- ['flutter', 'config', '--no-analytics'],
+ deferred.append(
+ api.defer(
+ api.step,
+ 'flutter config --no-analytics',
+ ['flutter', 'config', '--no-analytics'],
+ )
)
- api.step(
- 'flutter doctor',
- ['flutter', 'doctor'],
+ deferred.append(
+ api.defer(
+ api.step,
+ 'flutter doctor',
+ ['flutter', 'doctor'],
+ )
)
- api.step(
- 'flutter devices',
- ['flutter', 'devices', '--device-timeout=40', '--verbose'],
+ deferred.append(
+ api.defer(
+ api.step,
+ 'flutter devices',
+ ['flutter', 'devices', '--device-timeout=40', '--verbose'],
+ )
)
- api.step(
- 'download flutter dependencies',
- ['flutter', 'update-packages', '-v'],
- infra_step=True,
+ deferred.append(
+ api.defer(
+ api.step,
+ 'download flutter dependencies',
+ ['flutter', 'update-packages', '-v'],
+ infra_step=True,
+ )
)
+ api.defer.collect(deferred)
+
# Create gradlew file
with api.context(env=env, env_prefixes=env_prefixes, cwd=views_test_dir):
api.step(
@@ -102,8 +118,7 @@
max_attempts=2,
infra_step=True,
)
- with api.context(env=env, env_prefixes=env_prefixes,
- cwd=views_test_dir), api.step.defer_results():
+ with api.context(env=env, env_prefixes=env_prefixes, cwd=views_test_dir):
api.step(
'Android Views Integration Tests',
[
diff --git a/recipes/flutter/coverage.py b/recipes/flutter/coverage.py
index 922acee..8b91d5b 100644
--- a/recipes/flutter/coverage.py
+++ b/recipes/flutter/coverage.py
@@ -7,6 +7,7 @@
'flutter/flutter_deps',
'flutter/repo_util',
'recipe_engine/context',
+ 'recipe_engine/defer',
'recipe_engine/path',
'recipe_engine/properties',
'recipe_engine/step',
@@ -31,16 +32,20 @@
packages_path = checkout_path.join('packages', 'flutter')
with api.context(env=env, env_prefixes=env_prefixes, cwd=packages_path):
- with api.step.nest('prepare environment'), api.step.defer_results():
- api.step(
- 'flutter doctor',
- ['flutter', 'doctor'],
+ with api.step.nest('prepare environment'):
+ deferred = []
+ deferred.append(
+ api.defer(api.step, 'flutter doctor',['flutter', 'doctor'])
)
- api.step(
- 'download dependencies',
- ['flutter', 'update-packages', '-v'],
- infra_step=True,
+ deferred.append(
+ api.defer(
+ api.step,
+ 'download dependencies',
+ ['flutter', 'update-packages', '-v'],
+ infra_step=True,
+ )
)
+ api.defer.collect(deferred)
api.step(
'flutter coverage',
diff --git a/recipes/flutter/deferred_components.py b/recipes/flutter/deferred_components.py
index 700a587..f85ede1 100644
--- a/recipes/flutter/deferred_components.py
+++ b/recipes/flutter/deferred_components.py
@@ -19,6 +19,7 @@
'flutter/repo_util',
'recipe_engine/cipd',
'recipe_engine/context',
+ 'recipe_engine/defer',
'recipe_engine/file',
'recipe_engine/path',
'recipe_engine/properties',
@@ -62,46 +63,72 @@
bundletool_dir = cache_root.join('bundletool')
bundletool_jar = bundletool_dir.join('bundletool.jar')
with api.context(env=env, env_prefixes=env_prefixes, cwd=checkout_path):
- with api.step.nest('prepare environment'), api.step.defer_results():
+ with api.step.nest('prepare environment'):
+ deferred = []
# This prevents junk analytics from being sent due to testing
- api.step(
- 'flutter config --no-analytics',
- ['flutter', 'config', '--no-analytics'],
- )
- api.step(
- 'flutter doctor',
- ['flutter', 'doctor'],
- )
- api.step(
- 'flutter devices',
- ['flutter', 'devices', '--device-timeout=40', '--verbose'],
- )
- api.step(
- 'download dependencies',
- ['flutter', 'update-packages', '-v'],
- infra_step=True,
- )
- api.cipd.ensure(
- bundletool_dir,
- api.cipd.EnsureFile().add_package(
- 'flutter/android/bundletool',
- '0xeDa85nRhdQfi3iN2dK8PPluwI73z9San_Afuj3CfgC'
+ deferred.append(
+ api.defer(
+ api.step,
+ 'flutter config --no-analytics',
+ ['flutter', 'config', '--no-analytics'],
)
)
+ deferred.append(
+ api.defer(
+ api.step,
+ 'flutter doctor',
+ ['flutter', 'doctor'],
+ )
+ )
+ deferred.append(
+ api.defer(
+ api.step,
+ 'flutter devices',
+ ['flutter', 'devices', '--device-timeout=40', '--verbose'],
+ )
+ )
+ deferred.append(
+ api.defer(
+ api.step,
+ 'download dependencies',
+ ['flutter', 'update-packages', '-v'],
+ infra_step=True,
+ )
+ )
+ deferred.append(
+ api.defer(
+ api.cipd.ensure,
+ bundletool_dir,
+ api.cipd.EnsureFile().add_package(
+ 'flutter/android/bundletool',
+ '0xeDa85nRhdQfi3iN2dK8PPluwI73z9San_Afuj3CfgC'
+ )
+ )
+ )
+ api.defer.collect(deferred)
+
test_dir = checkout_path.join(
'dev', 'integration_tests', 'deferred_components_test'
)
- with api.context(env=env, env_prefixes=env_prefixes,
- cwd=test_dir), api.step.defer_results():
+ with api.context(env=env, env_prefixes=env_prefixes, cwd=test_dir):
+ deferred = []
# These assets are not allowed to be checked into the repo,
# so they are downloaded separately here.
- api.step('download assets script', ['./download_assets.sh'])
- api.step(
- 'Deferred components release tests',
- ['./run_release_test.sh',
- str(bundletool_jar), env['ADB_PATH']],
- timeout=700,
+ deferred.append(
+ api.defer(
+ api.step, 'download assets script', ['./download_assets.sh']
+ )
)
+ deferred.append(
+ api.defer(
+ api.step,
+ 'Deferred components release tests',
+ ['./run_release_test.sh',
+ str(bundletool_jar), env['ADB_PATH']],
+ timeout=700,
+ )
+ )
+ api.defer.collect(deferred)
# This is to clean up leaked processes.
api.os_utils.kill_processes()
diff --git a/recipes/flutter/flutter.py b/recipes/flutter/flutter.py
index 1922c8e..962ef44 100644
--- a/recipes/flutter/flutter.py
+++ b/recipes/flutter/flutter.py
@@ -19,6 +19,7 @@
'flutter/os_utils',
'flutter/repo_util',
'recipe_engine/context',
+ 'recipe_engine/defer',
'recipe_engine/path',
'recipe_engine/properties',
'recipe_engine/step',
@@ -50,26 +51,35 @@
env, env_prefixes, api.properties.get('dependencies', [])
)
with api.context(env=env, env_prefixes=env_prefixes, cwd=checkout_path):
- with api.step.nest('prepare environment'), api.step.defer_results():
- api.step(
- 'flutter doctor',
- ['flutter', 'doctor'],
+ with api.step.nest('prepare environment'):
+ deferred = []
+ deferred.append(
+ api.defer(api.step, 'flutter doctor', ['flutter', 'doctor'])
)
- api.step(
- 'download dependencies',
- ['flutter', 'update-packages', '-v'],
- infra_step=True,
+ deferred.append(
+ api.defer(
+ api.step,
+ 'download dependencies',
+ ['flutter', 'update-packages', '-v'],
+ infra_step=True,
+ )
)
- with api.step.defer_results():
- api.adhoc_validation.run(
- api.properties.get('validation_name'),
- api.properties.get('validation'), env, env_prefixes,
- api.properties.get('secrets', {})
- )
- # This is to clean up leaked processes.
- api.os_utils.kill_processes()
- # Collect memory/cpu/process after task execution.
- api.os_utils.collect_os_info()
+ api.defer.collect(deferred)
+
+ deferred = []
+ deferred.append(
+ api.defer(
+ api.adhoc_validation.run,
+ api.properties.get('validation_name'),
+ api.properties.get('validation'), env, env_prefixes,
+ api.properties.get('secrets', {})
+ )
+ )
+ # This is to clean up leaked processes.
+ deferred.append(api.defer(api.os_utils.kill_processes))
+ # Collect memory/cpu/process after task execution.
+ deferred.append(api.defer(api.os_utils.collect_os_info))
+ api.defer.collect(deferred)
def GenTests(api):
diff --git a/recipes/flutter/flutter_drone.py b/recipes/flutter/flutter_drone.py
index 7ec3169..19da867 100644
--- a/recipes/flutter/flutter_drone.py
+++ b/recipes/flutter/flutter_drone.py
@@ -21,6 +21,7 @@
'flutter/test_utils',
'flutter/token_util',
'recipe_engine/context',
+ 'recipe_engine/defer',
'recipe_engine/path',
'recipe_engine/properties',
'recipe_engine/step',
@@ -97,27 +98,35 @@
# Load local engine information if available.
api.flutter_deps.flutter_engine(env, env_prefixes)
if api.properties.get('$flutter/osx_sdk'):
- with api.osx_sdk('ios'), api.step.defer_results():
- api.step(
- 'flutter doctor',
- ['flutter', 'doctor', '-v'],
+ with api.osx_sdk('ios'):
+ deferred = []
+ deferred.append(
+ api.defer(
+ api.step,
+ 'flutter doctor',
+ ['flutter', 'doctor', '-v'],
+ )
)
- RunShard(api, env, env_prefixes, checkout_path)
+ deferred.append(
+ api.defer(RunShard, api, env, env_prefixes, checkout_path))
# This is to clean up leaked processes.
- api.os_utils.kill_processes()
+ deferred.append(api.defer(api.os_utils.kill_processes))
# Collect memory/cpu/process after task execution.
- api.os_utils.collect_os_info()
+ deferred.append(api.defer(api.os_utils.collect_os_info))
+ api.defer.collect(deferred)
else:
- with api.step.defer_results():
- api.step(
- 'flutter doctor',
- ['flutter', 'doctor', '-v'],
- )
- RunShard(api, env, env_prefixes, checkout_path)
- # This is to clean up leaked processes.
- api.os_utils.kill_processes()
- # Collect memory/cpu/process after task execution.
- api.os_utils.collect_os_info()
+ deferred = []
+ deferred.append(
+ api.defer(api.step,
+ 'flutter doctor',
+ ['flutter', 'doctor', '-v']))
+ deferred.append(
+ api.defer(RunShard, api, env, env_prefixes, checkout_path))
+ # This is to clean up leaked processes.
+ deferred.append(api.defer(api.os_utils.kill_processes))
+ # Collect memory/cpu/process after task execution.
+ deferred.append(api.defer(api.os_utils.collect_os_info))
+ api.defer.collect(deferred)
def GenTests(api):
diff --git a/recipes/recipes.py b/recipes/recipes.py
index 5ce43f5..78fec69 100755
--- a/recipes/recipes.py
+++ b/recipes/recipes.py
@@ -19,6 +19,7 @@
'fuchsia/git_checkout',
'recipe_engine/buildbucket',
'recipe_engine/context',
+ 'recipe_engine/defer',
'recipe_engine/json',
'recipe_engine/path',
'recipe_engine/properties',
@@ -106,9 +107,12 @@
with api.context(cwd=checkout_path):
api.git('log', 'log', '--oneline', '-n', '10')
api.recipe_testing.projects = ('flutter',)
- with api.step.defer_results():
- api.recipe_testing.run_lint(checkout_path)
- api.recipe_testing.run_unit_tests(checkout_path)
+
+ deferred = []
+ deferred.append(api.defer(api.recipe_testing.run_lint, checkout_path))
+ deferred.append(api.defer(api.recipe_testing.run_unit_tests, checkout_path))
+ api.defer.collect(deferred)
+
if not unittest_only:
flutter = options_pb2.Project(name='flutter', include_unrestricted=True)
opts = options_pb2.Options(projects=[flutter])