Supports `always` run logic for packages tasks
It is not uncommon some tasks are expected to `always` run no matter there are earlier task failures or not. This CL supports the `always` run logic to unblock packages cirrus to LUCI migration.
An LED run based on https://github.com/flutter/packages/pull/4234/files, which intentionally fails an earlier task:
https://ci.chromium.org/raw/build/logs.chromium.org/flutter/led/keyonghan_google.com/c747961ad022a190d2badfb314b4396d7de0beaa88b795d58ed4b5e2faa8e5b1/+/build.proto?server=chromium-swarm.appspot.com
Where it continues the `always: True` tasks:
native test
drive examples
but skips the one without `always: True`
remove simulator
and shows `Failed` for the whole build.
Change-Id: Id03074ae8b6a71f30567310b226fa060b442de9a
Bug: https://github.com/flutter/flutter/issues/122629
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/46041
Reviewed-by: Stuart Morgan <stuartmorgan@google.com>
Reviewed-by: Godofredo Contreras <godofredoc@google.com>
Commit-Queue: Keyong Han <keyonghan@google.com>
diff --git a/recipes/packages/packages.expected/multiple_tests_with_always.json b/recipes/packages/packages.expected/multiple_tests_with_always.json
new file mode 100644
index 0000000..6bfa21d
--- /dev/null
+++ b/recipes/packages/packages.expected/multiple_tests_with_always.json
@@ -0,0 +1,885 @@
+[
+ {
+ "cmd": [],
+ "name": "checkout source code"
+ },
+ {
+ "cmd": [],
+ "name": "checkout source code.Checkout flutter/packages",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "-u",
+ "RECIPE_MODULE[depot_tools::git]/resources/git_setup.py",
+ "--path",
+ "[START_DIR]/packages",
+ "--url",
+ "https://flutter.googlesource.com/mirrors/packages"
+ ],
+ "name": "checkout source code.Checkout flutter/packages.git setup",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "main",
+ "--recurse-submodules",
+ "--progress",
+ "--tags"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "PATH": "RECIPE_REPO[depot_tools]:<PATH>"
+ },
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/packages.git fetch",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "-f",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/packages.git checkout",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/packages.read revision",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_TEXT@<br/>checked out 'deadbeef'<br/>@@@",
+ "@@@SET_BUILD_PROPERTY@got_revision@\"deadbeef\"@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "clean",
+ "-f",
+ "-d",
+ "-x"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/packages.git clean",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "sync"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/packages.submodule sync",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "update",
+ "--init",
+ "--recursive"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/packages.submodule update",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "[START_DIR]/packages/.ci/flutter_master.version",
+ "/path/to/tmp/"
+ ],
+ "infra_step": true,
+ "name": "checkout source code.read pinned version",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@flutter_master.version@refs/heads/master@@@",
+ "@@@STEP_LOG_END@flutter_master.version@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "checkout source code.Checkout flutter/flutter",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "-u",
+ "RECIPE_MODULE[depot_tools::git]/resources/git_setup.py",
+ "--path",
+ "[START_DIR]/flutter",
+ "--url",
+ "https://github.com/flutter/flutter"
+ ],
+ "name": "checkout source code.Checkout flutter/flutter.git setup",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "master",
+ "--recurse-submodules",
+ "--progress",
+ "--tags"
+ ],
+ "cwd": "[START_DIR]/flutter",
+ "env": {
+ "PATH": "RECIPE_REPO[depot_tools]:<PATH>"
+ },
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/flutter.git fetch",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "-f",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/flutter",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/flutter.git checkout",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[START_DIR]/flutter",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/flutter.read revision",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_TEXT@<br/>checked out 'deadbeef'<br/>@@@",
+ "@@@SET_BUILD_PROPERTY@got_revision@\"deadbeef\"@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "clean",
+ "-f",
+ "-d",
+ "-x"
+ ],
+ "cwd": "[START_DIR]/flutter",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/flutter.git clean",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "sync"
+ ],
+ "cwd": "[START_DIR]/flutter",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/flutter.submodule sync",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "update",
+ "--init",
+ "--recursive"
+ ],
+ "cwd": "[START_DIR]/flutter",
+ "infra_step": true,
+ "name": "checkout source code.Checkout flutter/flutter.submodule update",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[START_DIR]/flutter",
+ "infra_step": true,
+ "name": "git rev-parse"
+ },
+ {
+ "cmd": [],
+ "name": "Dependencies"
+ },
+ {
+ "cmd": [],
+ "name": "prepare environment"
+ },
+ {
+ "cmd": [
+ "flutter",
+ "doctor",
+ "-v"
+ ],
+ "cwd": "[START_DIR]/flutter",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "name": "prepare environment.flutter doctor",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "flutter",
+ "update-packages",
+ "-v"
+ ],
+ "cwd": "[START_DIR]/flutter",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "prepare environment.download dependencies",
+ "timeout": 300,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "read yaml",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@yaml@@@@",
+ "@@@STEP_LOG_END@yaml@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "[START_DIR]/packages/.ci/targets/tests.yaml",
+ "/path/to/tmp/"
+ ],
+ "infra_step": true,
+ "name": "read yaml.read",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_END@tests.yaml@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "RECIPE_MODULE[flutter::yaml]/resources/parse_yaml.py",
+ "--yaml_file",
+ "[START_DIR]/packages/.ci/targets/tests.yaml",
+ "--json_file",
+ "/path/to/tmp/json"
+ ],
+ "infra_step": true,
+ "name": "read yaml.parse",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"tasks\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"args\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"arg1\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"arg2\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ ], @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"one\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"script\": \"myscript\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"always\": true, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"args\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"arg1\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"arg2\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ ], @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"two\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"script\": \"myscript\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "Run package tests",
+ "~followup_annotations": [
+ "@@@STEP_FAILURE@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "Run package tests.Initialize logs",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "ensure-directory",
+ "--mode",
+ "0777",
+ "[CLEANUP]/flutter_logs_dir"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.Initialize logs.Ensure [CLEANUP]/flutter_logs_dir",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "",
+ "[CLEANUP]/flutter_logs_dir/noop.txt"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.Initialize logs.Write noop file",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "bash",
+ "[START_DIR]/packages/myscript",
+ "arg1",
+ "arg2"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "FLUTTER_LOGS_DIR": "[CLEANUP]/flutter_logs_dir",
+ "FLUTTER_TEST_OUTPUTS_DIR": "[CLEANUP]/flutter_logs_dir",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "name": "Run package tests.one",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_FAILURE@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "Run package tests.process logs",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "-m",
+ "----",
+ "cp",
+ "-r",
+ "[CLEANUP]/flutter_logs_dir",
+ "gs://flutter_logs/flutter/00000000-0000-0000-0000-000000001337/one/00000000-0000-0000-0000-000000001337"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.process logs.gsutil upload logs 00000000-0000-0000-0000-000000001337",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@archive logs@https://console.cloud.google.com/storage/browser/flutter_logs/flutter/00000000-0000-0000-0000-000000001337/one/00000000-0000-0000-0000-000000001337@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "glob",
+ "[CLEANUP]/flutter_logs_dir",
+ "*"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.process logs.logs",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@glob@[CLEANUP]/flutter_logs_dir/a.txt@@@",
+ "@@@STEP_LOG_END@glob@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "Run package tests.log links",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@myfile.txt@https://storage.googleapis.com/flutter_logs/flutter/00000000-0000-0000-0000-000000001337/one/00000000-0000-0000-0000-000000001337/myfile.txt@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "listdir",
+ "[CLEANUP]/flutter_logs_dir",
+ "--recursive"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.log links.List logs path",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@listdir@[CLEANUP]/flutter_logs_dir/myfile.txt@@@",
+ "@@@STEP_LOG_END@listdir@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "Run package tests.Initialize logs (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "ensure-directory",
+ "--mode",
+ "0777",
+ "[CLEANUP]/flutter_logs_dir"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.Initialize logs (2).Ensure [CLEANUP]/flutter_logs_dir",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "",
+ "[CLEANUP]/flutter_logs_dir/noop.txt"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.Initialize logs (2).Write noop file",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "bash",
+ "[START_DIR]/packages/myscript",
+ "arg1",
+ "arg2"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "FLUTTER_LOGS_DIR": "[CLEANUP]/flutter_logs_dir",
+ "FLUTTER_TEST_OUTPUTS_DIR": "[CLEANUP]/flutter_logs_dir",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "name": "Run package tests.two",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "Run package tests.process logs (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python3",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gsutil]/resources/gsutil_smart_retry.py",
+ "--",
+ "RECIPE_REPO[depot_tools]/gsutil.py",
+ "-m",
+ "----",
+ "cp",
+ "-r",
+ "[CLEANUP]/flutter_logs_dir",
+ "gs://flutter_logs/flutter/00000000-0000-0000-0000-00000000133a/two/00000000-0000-0000-0000-00000000133a"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.process logs (2).gsutil upload logs 00000000-0000-0000-0000-00000000133a",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LINK@archive logs@https://console.cloud.google.com/storage/browser/flutter_logs/flutter/00000000-0000-0000-0000-00000000133a/two/00000000-0000-0000-0000-00000000133a@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "glob",
+ "[CLEANUP]/flutter_logs_dir",
+ "*"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.process logs (2).logs",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@glob@[CLEANUP]/flutter_logs_dir/a.txt@@@",
+ "@@@STEP_LOG_END@glob@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "Run package tests.log links (2)",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LINK@myfile.txt@https://storage.googleapis.com/flutter_logs/flutter/00000000-0000-0000-0000-00000000133a/two/00000000-0000-0000-0000-00000000133a/myfile.txt@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "listdir",
+ "[CLEANUP]/flutter_logs_dir",
+ "--recursive"
+ ],
+ "cwd": "[START_DIR]/packages",
+ "env": {
+ "DEPOT_TOOLS": "RECIPE_REPO[depot_tools]",
+ "GIT_BRANCH": "",
+ "LUCI_BRANCH": "",
+ "LUCI_CI": "True",
+ "LUCI_PR": "",
+ "OS": "linux",
+ "PUB_CACHE": "[START_DIR]/.pub-cache",
+ "REVISION": "12345abcde12345abcde12345abcde12345abcde",
+ "SDK_CHECKOUT_PATH": "[START_DIR]/flutter"
+ },
+ "env_prefixes": {
+ "PATH": [
+ "[START_DIR]/flutter/bin",
+ "[START_DIR]/flutter/bin/cache/dart-sdk/bin"
+ ]
+ },
+ "infra_step": true,
+ "name": "Run package tests.log links (2).List logs path",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_LOG_LINE@listdir@[CLEANUP]/flutter_logs_dir/myfile.txt@@@",
+ "@@@STEP_LOG_END@listdir@@@"
+ ]
+ },
+ {
+ "failure": {
+ "failure": {},
+ "humanReason": "Tasks failed: one"
+ },
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipes/packages/packages.py b/recipes/packages/packages.py
index e2b6e22..3ab96e7 100644
--- a/recipes/packages/packages.py
+++ b/recipes/packages/packages.py
@@ -80,6 +80,7 @@
def run_test(api, result, packages_checkout_path, env):
"""Run tests sequentially following the script"""
+ failed_tasks = []
for task in result.json.output['tasks']:
script_path = packages_checkout_path.join(task['script'])
cmd = ['bash', script_path]
@@ -87,11 +88,20 @@
args = task['args']
cmd.extend(args)
api.logs_util.initialize_logs_collection(env)
- try:
- with api.context(env=env):
- api.step(task['name'], cmd)
- finally:
- api.logs_util.upload_logs(task['name'])
+
+ # Flag showing whether the task should always run regardless of previous failures.
+ always_run_task = task['always'] if 'always' in task else False
+ with api.context(env=env):
+ # Runs the task in two scenarios:
+ # 1) all earlier tasks pass
+ # 2) there are earlier task failures, but the current task is marked as `always: True`.
+ if not failed_tasks or always_run_task:
+ step = api.step(task['name'], cmd, raise_on_failure=False)
+ if step.retcode != 0:
+ failed_tasks.append(task['name'])
+ api.logs_util.upload_logs(task['name'])
+ if failed_tasks:
+ raise api.step.StepFailure('Tasks failed: %s' % ','.join(failed_tasks))
def GenTests(api):
@@ -119,3 +129,21 @@
**{'$flutter/osx_sdk': {'sdk_version': 'deadbeef',}},
), api.step_data('read yaml.parse', api.json.output(tasks_dict))
)
+ multiple_tasks_dict = {
+ 'tasks': [{'name': 'one', 'script': 'myscript', 'args': ['arg1', 'arg2']},
+ {
+ 'name': 'two', 'script': 'myscript',
+ 'args': ['arg1', 'arg2'], 'always': True
+ }]
+ }
+ yield api.test(
+ 'multiple_tests_with_always',
+ api.repo_util.flutter_environment_data(flutter_path),
+ api.properties(
+ channel='master',
+ version_file='flutter_master.version',
+ ),
+ api.step_data('read yaml.parse', api.json.output(multiple_tasks_dict)),
+ api.step_data('Run package tests.one', retcode=1),
+ status='FAILURE'
+ )