[roll] Add a roll to dev recipe
The recipe merges the latest commit on a specified ref to dev. It
updates the VERSION file in refs/heads/dev to match the specified
ref or bumps the PRERELEASE version by 1 if they are already matching.
https://github.com/dart-lang/sdk/issues/42917
Change-Id: I2eddae8e35dcb9d90d3ea35df93316ac84e9db66
Reviewed-on: https://dart-review.googlesource.com/c/recipes/+/157960
Commit-Queue: Alexander Thomas <athom@google.com>
Reviewed-by: Karl Klose <karlklose@google.com>
diff --git a/README.recipes.md b/README.recipes.md
index f19b10d..98f2a34 100644
--- a/README.recipes.md
+++ b/README.recipes.md
@@ -22,6 +22,7 @@
* [dart:examples/example-get_secret](#recipes-dart_examples_example-get_secret)
* [presubmit/presubmit](#recipes-presubmit_presubmit)
* [roller/lkgr](#recipes-roller_lkgr)
+ * [roller/roll_to_dev](#recipes-roller_roll_to_dev)
## Recipe Modules
### *recipe_modules* / [bisect\_build](/recipe_modules/bisect_build)
@@ -210,6 +211,11 @@
[DEPS](/recipes/roller/lkgr.py#17): [depot\_tools/bot\_update][depot_tools/recipe_modules/bot_update], [depot\_tools/gclient][depot_tools/recipe_modules/gclient], [depot\_tools/git][depot_tools/recipe_modules/git], [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/path][recipe_engine/recipe_modules/path], [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]
— **def [RunSteps](/recipes/roller/lkgr.py#33)(api, properties):**
+### *recipes* / [roller/roll\_to\_dev](/recipes/roller/roll_to_dev.py)
+
+[DEPS](/recipes/roller/roll_to_dev.py#9): [depot\_tools/bot\_update][depot_tools/recipe_modules/bot_update], [depot\_tools/gclient][depot_tools/recipe_modules/gclient], [depot\_tools/git][depot_tools/recipe_modules/git], [depot\_tools/gitiles][depot_tools/recipe_modules/gitiles], [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/file][recipe_engine/recipe_modules/file], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/path][recipe_engine/recipe_modules/path], [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]
+
+— **def [RunSteps](/recipes/roller/roll_to_dev.py#37)(api, properties):**
[build/recipe_modules/goma]: https://chromium.googlesource.com/chromium/tools/build.git/+/d384bbe2de7b92c4959711d38499a57f6b5fdfed/scripts/slave/README.recipes.md#recipe_modules-goma
[depot_tools/recipe_modules/bot_update]: https://chromium.googlesource.com/chromium/tools/depot_tools.git/+/0fa91d0f3563276834b632b21d03fc327eff6c9c/recipes/README.recipes.md#recipe_modules-bot_update
diff --git a/recipes/roller/roll.expected/push.json b/recipes/roller/roll.expected/push.json
new file mode 100644
index 0000000..03c8354
--- /dev/null
+++ b/recipes/roller/roll.expected/push.json
@@ -0,0 +1,254 @@
+[
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gitiles]/resources/gerrit_client.py",
+ "--json-file",
+ "/path/to/tmp/json",
+ "--url",
+ "https://dart.googlesource.com/sdk/+/refs/heads/lkgr",
+ "--format",
+ "json"
+ ],
+ "name": "get commit to merge",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"author\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"testauthor@fake.chromium.org\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"Test Author\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"time\": \"Mon Jan 01 00:00:00 2015\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"commit\": \"1f8ac10f23c5b5bc1167bda84b833e5c057a77d2\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"committer\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"testauthor@fake.chromium.org\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"Test Author\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"time\": \"Mon Jan 01 00:00:00 2015\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"message\": \"Subject\\n\\nMessage\\n\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"parents\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"8bb834e0b20c5477e78620c2108be38b4cab1ea1\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ ], @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"tree\": \"48761f4afebd42d59efcf591792ab1e79289fafd\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"tree_diff\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_id\": \"0f975f72631d85445ca50562eb5cc2c71837b55e\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_mode\": 33188, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_path\": \"foo/bar\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_id\": \"0000000000000000000000000000000000000000\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_mode\": 0, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"type\": \"add\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_id\": \"52c4105c1b40b1e59cbb2f51ff017ecf74a1a8c0\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_mode\": 33188, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_path\": \"baz/qux\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_id\": \"0000000000000000000000000000000000000000\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_mode\": 0, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"type\": \"add\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::bot_update]/resources/bot_update.py",
+ "--spec-path",
+ "cache_dir = '[CACHE]/git'\nsolutions = [{'deps_file': 'DEPS', 'managed': False, 'name': 'sdk', 'url': 'https://dart.googlesource.com/sdk.git'}]",
+ "--revision_mapping_file",
+ "{}",
+ "--git-cache-dir",
+ "[CACHE]/git",
+ "--cleanup-dir",
+ "[CLEANUP]/bot_update",
+ "--output_json",
+ "/path/to/tmp/json",
+ "--revision",
+ "sdk@HEAD",
+ "--refs",
+ "refs/heads/dev",
+ "--no_fetch_tags"
+ ],
+ "cwd": "[CACHE]/builder",
+ "env": {
+ "GIT_HTTP_LOW_SPEED_LIMIT": "102400",
+ "GIT_HTTP_LOW_SPEED_TIME": "300"
+ },
+ "env_suffixes": {
+ "DEPOT_TOOLS_UPDATE": [
+ "0"
+ ],
+ "PATH": [
+ "RECIPE_REPO[depot_tools]"
+ ]
+ },
+ "infra_step": true,
+ "name": "bot_update",
+ "timeout": 1080,
+ "~followup_annotations": [
+ "@@@STEP_TEXT@Some step text@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"did_run\": true, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"fixed_revisions\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"sdk\": \"HEAD\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"manifest\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"sdk\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"repository\": \"https://fake.org/sdk.git\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"revision\": \"5a374dcd2e5eb762b527af3a5bab6072a4d24493\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"patch_failure\": false, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"patch_root\": \"sdk\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"properties\": {}, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"root\": \"sdk\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"source_manifest\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"directories\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"sdk\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"git_checkout\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"repo_url\": \"https://fake.org/sdk.git\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"revision\": \"5a374dcd2e5eb762b527af3a5bab6072a4d24493\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"version\": 0@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"step_text\": \"Some step text\"@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge",
+ "--no-commit--no-ff",
+ "1f8ac10f23c5b5bc1167bda84b833e5c057a77d2"
+ ],
+ "cwd": "[CACHE]/builder",
+ "infra_step": true,
+ "name": "git merge"
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gitiles]/resources/gerrit_client.py",
+ "--json-file",
+ "/path/to/tmp/json",
+ "--url",
+ "https://dart.googlesource.com/sdk/+/refs/heads/lkgr/tools/VERSION",
+ "--format",
+ "text"
+ ],
+ "cwd": "[CACHE]/builder",
+ "name": "download from_ref version file"
+ },
+ {
+ "cmd": [
+ "vpython",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "tools/VERSION",
+ "/path/to/tmp/"
+ ],
+ "cwd": "[CACHE]/builder",
+ "infra_step": true,
+ "name": "read to_ref version file",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@VERSION@# Comment@@@",
+ "@@@STEP_LOG_LINE@VERSION@CHANNEL dev@@@",
+ "@@@STEP_LOG_LINE@VERSION@MAJOR 4@@@",
+ "@@@STEP_LOG_LINE@VERSION@MINOR 1@@@",
+ "@@@STEP_LOG_LINE@VERSION@PATCH 2@@@",
+ "@@@STEP_LOG_LINE@VERSION@PRERELEASE 34@@@",
+ "@@@STEP_LOG_LINE@VERSION@PRERELEASE_PATCH 25@@@",
+ "@@@STEP_LOG_LINE@VERSION@UNKNOWN_FIELD feg@@@",
+ "@@@STEP_LOG_END@VERSION@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "UNKNOWN_FIELD cde",
+ "tools/VERSION"
+ ],
+ "cwd": "[CACHE]/builder",
+ "infra_step": true,
+ "name": "write new version file",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@VERSION@UNKNOWN_FIELD cde@@@",
+ "@@@STEP_LOG_END@VERSION@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "add",
+ "tools/VERSION"
+ ],
+ "cwd": "[CACHE]/builder",
+ "infra_step": true,
+ "name": "git add"
+ },
+ {
+ "cmd": [
+ "git",
+ "commit",
+ "--all",
+ "--message=Version 4.1.2-35.0.dev\n\nMerge commit '1f8ac10f23c5b5bc1167bda84b833e5c057a77d2' into dev\n"
+ ],
+ "cwd": "[CACHE]/builder",
+ "infra_step": true,
+ "name": "git commit"
+ },
+ {
+ "cmd": [
+ "git",
+ "tag",
+ "--annotate",
+ "--message=4.1.2-35.0.dev",
+ "4.1.2-35.0.dev"
+ ],
+ "cwd": "[CACHE]/builder",
+ "infra_step": true,
+ "name": "git tag"
+ },
+ {
+ "cmd": [
+ "git",
+ "push",
+ "https://dart.googlesource.com/sdk.git",
+ "refs/heads/dev"
+ ],
+ "cwd": "[CACHE]/builder",
+ "infra_step": true,
+ "name": "push to refs/heads/dev"
+ },
+ {
+ "cmd": [
+ "git",
+ "push",
+ "https://dart.googlesource.com/sdk.git",
+ "4.1.2-35.0.dev"
+ ],
+ "cwd": "[CACHE]/builder",
+ "infra_step": true,
+ "name": "tag 4.1.2-35.0.dev"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipes/roller/roll_to_dev.expected/no-push-if-already-merged.json b/recipes/roller/roll_to_dev.expected/no-push-if-already-merged.json
new file mode 100644
index 0000000..790c2ef
--- /dev/null
+++ b/recipes/roller/roll_to_dev.expected/no-push-if-already-merged.json
@@ -0,0 +1,154 @@
+[
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gitiles]/resources/gerrit_client.py",
+ "--json-file",
+ "/path/to/tmp/json",
+ "--url",
+ "https://dart.googlesource.com/sdk/+/refs/heads/lkgr",
+ "--format",
+ "json"
+ ],
+ "name": "get commit to merge",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"author\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"testauthor@fake.chromium.org\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"Test Author\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"time\": \"Mon Jan 01 00:00:00 2015\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"commit\": \"1f8ac10f23c5b5bc1167bda84b833e5c057a77d2\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"committer\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"testauthor@fake.chromium.org\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"Test Author\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"time\": \"Mon Jan 01 00:00:00 2015\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"message\": \"Subject\\n\\nMessage\\n\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"parents\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"8bb834e0b20c5477e78620c2108be38b4cab1ea1\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ ], @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"tree\": \"48761f4afebd42d59efcf591792ab1e79289fafd\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"tree_diff\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_id\": \"0f975f72631d85445ca50562eb5cc2c71837b55e\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_mode\": 33188, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_path\": \"foo/bar\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_id\": \"0000000000000000000000000000000000000000\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_mode\": 0, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"type\": \"add\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_id\": \"52c4105c1b40b1e59cbb2f51ff017ecf74a1a8c0\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_mode\": 33188, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_path\": \"baz/qux\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_id\": \"0000000000000000000000000000000000000000\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_mode\": 0, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"type\": \"add\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::git]/resources/git_setup.py",
+ "--path",
+ "[START_DIR]/sdk",
+ "--url",
+ "https://dart.googlesource.com/sdk"
+ ],
+ "name": "git setup"
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "dev",
+ "--progress"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "env": {
+ "PATH": "RECIPE_REPO[depot_tools]:<PATH>"
+ },
+ "infra_step": true,
+ "name": "git fetch"
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "-f",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "git checkout"
+ },
+ {
+ "cmd": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "read revision",
+ "~followup_annotations": [
+ "@@@STEP_TEXT@<br/>checked out 'deadbeef'<br/>@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "clean",
+ "-f",
+ "-d",
+ "-x"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "git clean"
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "dev"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "checkout dev"
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "1f8ac10f23c5b5bc1167bda84b833e5c057a77d2"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "fetch 1f8ac10f23c5b5bc1167bda84b833e5c057a77d2"
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "1f8ac10f23c5b5bc1167bda84b833e5c057a77d2",
+ "HEAD"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "check if commit has been merged before"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipes/roller/roll_to_dev.expected/push.json b/recipes/roller/roll_to_dev.expected/push.json
new file mode 100644
index 0000000..3979cfa
--- /dev/null
+++ b/recipes/roller/roll_to_dev.expected/push.json
@@ -0,0 +1,292 @@
+[
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gitiles]/resources/gerrit_client.py",
+ "--json-file",
+ "/path/to/tmp/json",
+ "--url",
+ "https://dart.googlesource.com/sdk/+/refs/heads/lkgr",
+ "--format",
+ "json"
+ ],
+ "name": "get commit to merge",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"author\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"testauthor@fake.chromium.org\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"Test Author\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"time\": \"Mon Jan 01 00:00:00 2015\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"commit\": \"1f8ac10f23c5b5bc1167bda84b833e5c057a77d2\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"committer\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"testauthor@fake.chromium.org\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"Test Author\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"time\": \"Mon Jan 01 00:00:00 2015\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"message\": \"Subject\\n\\nMessage\\n\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"parents\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"8bb834e0b20c5477e78620c2108be38b4cab1ea1\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ ], @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"tree\": \"48761f4afebd42d59efcf591792ab1e79289fafd\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"tree_diff\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_id\": \"0f975f72631d85445ca50562eb5cc2c71837b55e\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_mode\": 33188, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_path\": \"foo/bar\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_id\": \"0000000000000000000000000000000000000000\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_mode\": 0, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"type\": \"add\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }, @@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_id\": \"52c4105c1b40b1e59cbb2f51ff017ecf74a1a8c0\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_mode\": 33188, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"new_path\": \"baz/qux\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_id\": \"0000000000000000000000000000000000000000\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"old_mode\": 0, @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"type\": \"add\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::git]/resources/git_setup.py",
+ "--path",
+ "[START_DIR]/sdk",
+ "--url",
+ "https://dart.googlesource.com/sdk"
+ ],
+ "name": "git setup"
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "dev",
+ "--progress"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "env": {
+ "PATH": "RECIPE_REPO[depot_tools]:<PATH>"
+ },
+ "infra_step": true,
+ "name": "git fetch"
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "-f",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "git checkout"
+ },
+ {
+ "cmd": [
+ "git",
+ "rev-parse",
+ "HEAD"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "read revision",
+ "~followup_annotations": [
+ "@@@STEP_TEXT@<br/>checked out 'deadbeef'<br/>@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "clean",
+ "-f",
+ "-d",
+ "-x"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "git clean"
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "dev"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "checkout dev"
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "1f8ac10f23c5b5bc1167bda84b833e5c057a77d2"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "fetch 1f8ac10f23c5b5bc1167bda84b833e5c057a77d2"
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "1f8ac10f23c5b5bc1167bda84b833e5c057a77d2",
+ "HEAD"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "check if commit has been merged before"
+ },
+ {
+ "cmd": [
+ "git",
+ "merge",
+ "--no-commit",
+ "--no-ff",
+ "1f8ac10f23c5b5bc1167bda84b833e5c057a77d2"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "merge 1f8ac10f23c5b5bc1167bda84b833e5c057a77d2 to dev"
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "--ours",
+ "tools/VERSION"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "restore version file on dev"
+ },
+ {
+ "cmd": [
+ "python",
+ "-u",
+ "RECIPE_MODULE[depot_tools::gitiles]/resources/gerrit_client.py",
+ "--json-file",
+ "/path/to/tmp/json",
+ "--url",
+ "https://dart.googlesource.com/sdk/+/refs/heads/lkgr/tools/VERSION",
+ "--format",
+ "text"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "name": "download from_ref version file"
+ },
+ {
+ "cmd": [
+ "vpython",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "[START_DIR]/sdk/tools/VERSION",
+ "/path/to/tmp/"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "read to_ref version file",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@VERSION@# Comment@@@",
+ "@@@STEP_LOG_LINE@VERSION@CHANNEL dev@@@",
+ "@@@STEP_LOG_LINE@VERSION@MAJOR 4@@@",
+ "@@@STEP_LOG_LINE@VERSION@MINOR 1@@@",
+ "@@@STEP_LOG_LINE@VERSION@PATCH 2@@@",
+ "@@@STEP_LOG_LINE@VERSION@PRERELEASE 34@@@",
+ "@@@STEP_LOG_LINE@VERSION@PRERELEASE_PATCH 25@@@",
+ "@@@STEP_LOG_LINE@VERSION@UNKNOWN_FIELD feg@@@",
+ "@@@STEP_LOG_END@VERSION@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "UNKNOWN_FIELD cde",
+ "[START_DIR]/sdk/tools/VERSION"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "write new version file",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@VERSION@UNKNOWN_FIELD cde@@@",
+ "@@@STEP_LOG_END@VERSION@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "add",
+ "tools/VERSION"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "git add"
+ },
+ {
+ "cmd": [
+ "git",
+ "commit",
+ "--all",
+ "--message=Version 4.1.2-35.0.dev\n\nMerge commit '1f8ac10f23c5b5bc1167bda84b833e5c057a77d2' into 'dev'\n"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "git commit"
+ },
+ {
+ "cmd": [
+ "git",
+ "tag",
+ "--annotate",
+ "--message=4.1.2-35.0.dev",
+ "4.1.2-35.0.dev"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "git tag"
+ },
+ {
+ "cmd": [
+ "git",
+ "push",
+ "https://dart.googlesource.com/sdk.git",
+ "refs/heads/dev"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "push to refs/heads/dev"
+ },
+ {
+ "cmd": [
+ "git",
+ "push",
+ "https://dart.googlesource.com/sdk.git",
+ "4.1.2-35.0.dev"
+ ],
+ "cwd": "[START_DIR]/sdk",
+ "infra_step": true,
+ "name": "tag 4.1.2-35.0.dev"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipes/roller/roll_to_dev.proto b/recipes/roller/roll_to_dev.proto
new file mode 100644
index 0000000..6f0d0f8
--- /dev/null
+++ b/recipes/roller/roll_to_dev.proto
@@ -0,0 +1,11 @@
+// Copyright (c) 2020, the Dart project authors. All rights reserved. Use of
+// this source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+syntax = "proto3";
+
+package recipes.dart.roller.roll_to_dev;
+
+message RollToDev {
+ // The source ref (e.g. "refs/heads/lkgr") or commit SHA to roll from.
+ string from_ref = 1;
+}
\ No newline at end of file
diff --git a/recipes/roller/roll_to_dev.py b/recipes/roller/roll_to_dev.py
new file mode 100644
index 0000000..b9e37af
--- /dev/null
+++ b/recipes/roller/roll_to_dev.py
@@ -0,0 +1,278 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from recipe_engine import post_process
+
+from PB.recipes.dart.roller.roll_to_dev import RollToDev
+
+DEPS = [
+ 'depot_tools/bot_update',
+ 'depot_tools/gclient',
+ 'depot_tools/git',
+ 'depot_tools/gitiles',
+ 'recipe_engine/context',
+ 'recipe_engine/file',
+ 'recipe_engine/json',
+ 'recipe_engine/path',
+ 'recipe_engine/properties',
+ 'recipe_engine/raw_io',
+ 'recipe_engine/runtime',
+ 'recipe_engine/step',
+]
+DEV_BRANCH = 'dev'
+DEV_REF = 'refs/heads/dev'
+MESSAGE_TEMPLATE = '''Version %s
+
+Merge commit '%s' into '%s'
+'''
+PROPERTIES = RollToDev
+REPO_URL = 'https://dart.googlesource.com/sdk'
+SUPPORTED_FIELDS = {
+ 'CHANNEL', 'MAJOR', 'MINOR', 'PATCH', 'PRERELEASE', 'PRERELEASE_PATCH'
+}
+VERSION_PATH = 'tools/VERSION'
+
+
+def RunSteps(api, properties):
+ from_ref = properties.from_ref
+ assert from_ref, 'the recipe requires a from_ref'
+ to_ref = DEV_REF
+ commit = api.gitiles.commit_log(
+ commit=from_ref,
+ step_name='get commit to merge',
+ url=REPO_URL,
+ )
+ commit_hash = commit['commit']
+ assert commit_hash, 'no commit hash to merge found'
+
+ api.git.checkout(
+ REPO_URL,
+ ref=to_ref,
+ submodules=False,
+ submodule_update_recursive=False,
+ )
+ with api.context(cwd=api.path['checkout']):
+ api.git('checkout', DEV_BRANCH, name='checkout dev')
+ api.git('fetch', 'origin', commit_hash, name='fetch %s' % commit_hash)
+ result = api.git(
+ 'merge-base',
+ '--is-ancestor',
+ commit_hash,
+ 'HEAD',
+ name='check if commit has been merged before',
+ ok_ret=[0, 1], # merge-base returns 1 if the commit is not an ancestor.
+ )
+ if result.exc_result.retcode == 0:
+ # The commit has already been pushed before.
+ return
+
+ api.git(
+ 'merge',
+ '--no-commit',
+ '--no-ff',
+ commit_hash,
+ name='merge %s to dev' % commit_hash,
+ ok_ret='any')
+ api.git(
+ 'checkout', '--ours', VERSION_PATH, name='restore version file on dev')
+ version, channel = _update_version_file(api, from_ref)
+ message = MESSAGE_TEMPLATE % (version, commit_hash, channel)
+ api.git('commit', '--all', '--message=%s' % message)
+ api.git('tag', '--annotate', '--message=%s' % version, version)
+ push_args = ['push']
+ if api.runtime.is_experimental:
+ push_args.append('--dry-run')
+ push_args.append('https://dart.googlesource.com/sdk.git')
+ api.git(*push_args + [to_ref], name='push to %s' % to_ref)
+ api.git(*push_args + [version], name='tag %s' % version)
+
+
+def _update_version_file(api, from_ref):
+ from_version_file_text = api.gitiles.download_file(
+ REPO_URL,
+ VERSION_PATH,
+ branch=from_ref,
+ step_name='download from_ref version file',
+ )
+ from_version = _parse_version_file(from_version_file_text)
+ from_triplet = _version_triplet(from_version)
+
+ to_version_file_text = api.file.read_text(
+ 'read to_ref version file', api.path['checkout'].join(VERSION_PATH))
+ to_version = _parse_version_file(to_version_file_text)
+ to_triplet = _version_triplet(to_version)
+
+ if not from_triplet == to_triplet:
+ # major, minor, or patch was bumped on from_ref
+ assert from_triplet > to_triplet, 'version downgrade is unsupported'
+ for field in ['MAJOR', 'MINOR', 'PATCH']:
+ to_version[field] = from_version[field]
+ # reset prerelease
+ to_version['PRERELEASE'] = '0'
+ else:
+ _bump(to_version, 'PRERELEASE')
+
+ # always '0' on dev
+ to_version['PRERELEASE_PATCH'] = '0'
+
+ # copy unknown fields
+ for field in from_version.keys():
+ if field not in SUPPORTED_FIELDS:
+ to_version[field] = from_version[field]
+
+ _write_version_file(api, from_version_file_text, to_version)
+ api.git('add', VERSION_PATH)
+ return _version_string(to_version), to_version['CHANNEL']
+
+
+def _parse_version_file(version_file_text):
+ version = {}
+ for line in version_file_text.splitlines():
+ if not line or line.startswith('#'):
+ continue
+ field, value = line.split(' ')
+ version[field] = value
+ return version
+
+
+def _version_triplet(version):
+ return (version['MAJOR'], version['MINOR'], version['PATCH'])
+
+
+def _bump(version, field):
+ version[field] = str(int(version[field]) + 1)
+
+
+def _write_version_file(api, version_file_text, new_version):
+ updated_lines = []
+ for line in version_file_text.splitlines():
+ if line.startswith('#'):
+ updated_lines.append(line)
+ else:
+ field, _ = line.split(' ')
+ updated_lines = ['%s %s' % (field, new_version[field])]
+ api.file.write_text('write new version file',
+ api.path['checkout'].join(VERSION_PATH),
+ '\n'.join(updated_lines))
+
+
+def _version_string(version):
+ return '%s.%s.%s-%s.%s.%s' % (version['MAJOR'], version['MINOR'],
+ version['PATCH'], version['PRERELEASE'],
+ version['PRERELEASE_PATCH'], version['CHANNEL'])
+
+
+def GenTests(api):
+
+ assertion_error = (
+ api.post_process(post_process.DoesNotRunRE, '(push|tag).*'),
+ api.expect_exception('AssertionError'),
+ api.post_process(post_process.StatusException),
+ api.post_process(post_process.DropExpectation),
+ )
+ yield api.test('no-from-ref-no-push', *assertion_error)
+
+ input_properties = api.properties(RollToDev(from_ref='refs/heads/lkgr'))
+ from_ref_commit = api.step_data(
+ 'get commit to merge',
+ api.gitiles.make_commit_test_data(
+ 'abcdef', 'Subject\n\nMessage\n', new_files=['foo/bar', 'baz/qux']))
+ from_ref_version_file = api.step_data(
+ 'download from_ref version file',
+ api.gitiles.make_encoded_file('''# Comment
+CHANNEL abc
+MAJOR 4
+MINOR 1
+PATCH 2
+PRERELEASE 0
+PRERELEASE_PATCH 0
+UNKNOWN_FIELD cde
+'''))
+ to_ref_version_file = api.step_data(
+ 'read to_ref version file',
+ api.file.read_text('''# Comment
+CHANNEL dev
+MAJOR 4
+MINOR 1
+PATCH 2
+PRERELEASE 34
+PRERELEASE_PATCH 25
+UNKNOWN_FIELD feg
+'''))
+
+ yield api.test(
+ 'no-push-if-already-merged',
+ input_properties,
+ from_ref_commit,
+ api.post_process(post_process.DoesNotRunRE, '(push|tag).*'),
+ api.post_process(post_process.StatusSuccess),
+ )
+
+ unmerged = api.step_data('check if commit has been merged before', retcode=1)
+ yield api.test(
+ 'push',
+ input_properties,
+ from_ref_commit,
+ from_ref_version_file,
+ to_ref_version_file,
+ unmerged,
+ api.post_process(post_process.MustRun, 'push to refs/heads/dev'),
+ api.post_process(post_process.MustRun, 'tag 4.1.2-35.0.dev'),
+ api.post_process(post_process.StatusSuccess),
+ )
+ yield api.test(
+ 'dry-run',
+ api.runtime(is_luci=True, is_experimental=True),
+ input_properties,
+ from_ref_commit,
+ from_ref_version_file,
+ to_ref_version_file,
+ unmerged,
+ api.post_process(post_process.MustRun, 'push to refs/heads/dev'),
+ api.post_process(post_process.MustRun, 'tag 4.1.2-35.0.dev'),
+ api.post_process(post_process.StepCommandContains,
+ 'push to refs/heads/dev', ['--dry-run']),
+ api.post_process(post_process.StepCommandContains, 'tag 4.1.2-35.0.dev',
+ ['--dry-run']),
+ api.post_process(post_process.StatusSuccess),
+ api.post_process(post_process.DropExpectation),
+ )
+
+ from_ref_version_file = api.step_data(
+ 'download from_ref version file',
+ api.gitiles.make_encoded_file('''# Comment
+CHANNEL abc
+MAJOR 5
+MINOR 2
+PATCH 10
+PRERELEASE 0
+PRERELEASE_PATCH 0
+UNKNOWN_FIELD cde
+'''))
+ yield api.test(
+ 'push-version-mismatch',
+ input_properties,
+ from_ref_commit,
+ from_ref_version_file,
+ to_ref_version_file,
+ unmerged,
+ api.post_process(post_process.MustRun, 'push to refs/heads/dev'),
+ api.post_process(post_process.MustRun, 'tag 5.2.10-0.0.dev'),
+ api.post_process(post_process.StatusSuccess),
+ api.post_process(post_process.DropExpectation),
+ )
+ from_ref_version_file = api.step_data(
+ 'download from_ref version file',
+ api.gitiles.make_encoded_file('''# Comment
+CHANNEL abc
+MAJOR 4
+MINOR 0
+PATCH 2
+PRERELEASE 0
+PRERELEASE_PATCH 0
+UNKNOWN_FIELD cde
+'''))
+ yield api.test('no-push-version-downgrade', input_properties, from_ref_commit,
+ from_ref_version_file, to_ref_version_file, unmerged,
+ *assertion_error)