submodule_roller: Move most logic to module
Create a new submodule_roll recipe module and move most of the logic
from the submodule_roller recipe there.
Bug: b/341756093
Change-Id: I72d3392c786843053250947f45e6aaee0d5b13be
Reviewed-on: https://pigweed-review.googlesource.com/c/infra/recipes/+/229717
Commit-Queue: Rob Mohr <mohrr@google.com>
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Danielle Kay <danikay@google.com>
Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com>
diff --git a/recipe_modules/submodule_roll/__init__.py b/recipe_modules/submodule_roll/__init__.py
new file mode 100644
index 0000000..2cfcef4
--- /dev/null
+++ b/recipe_modules/submodule_roll/__init__.py
@@ -0,0 +1,26 @@
+# Copyright 2024 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+# pylint: disable=missing-docstring
+
+from __future__ import annotations
+
+DEPS = [
+ 'fuchsia/git',
+ 'pigweed/checkout',
+ 'pigweed/roll_util',
+ 'recipe_engine/context',
+ 'recipe_engine/file',
+ 'recipe_engine/step',
+]
diff --git a/recipe_modules/submodule_roll/api.py b/recipe_modules/submodule_roll/api.py
new file mode 100644
index 0000000..6d87693
--- /dev/null
+++ b/recipe_modules/submodule_roll/api.py
@@ -0,0 +1,164 @@
+# Copyright 2024 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from __future__ import annotations
+
+import configparser
+import dataclasses
+import io
+import re
+from typing import TYPE_CHECKING
+
+from recipe_engine import recipe_api
+
+if TYPE_CHECKING: # pragma: no cover
+ from typing import Generator
+ from recipe_engine import config_types
+ from RECIPE_MODULES.pigweed.checkout import api as checkout_api
+ from RECIPE_MODULES.pigweed.roll_util import api as roll_util_api
+
+
+@dataclasses.dataclass
+class Submodule:
+ path: str
+ name: str
+ branch: str
+ remote: str = dataclasses.field(default=None)
+ dir: config_types.Path = dataclasses.field(default=None)
+
+
+@dataclasses.dataclass
+class RevisionChange:
+ old: str
+ new: str
+
+
+class SubmoduleRollApi(recipe_api.RecipeApi):
+
+ Submodule = Submodule
+ RevisionChange = RevisionChange
+
+ def update_pin(
+ self,
+ checkout: checkout_api.CheckoutContext,
+ path: config_types.Path,
+ new_revision: str,
+ ) -> RevisionChange:
+ with self.m.context(cwd=checkout.top):
+ self.m.git.submodule_update(
+ paths=(path,),
+ timeout=checkout.options.submodule_timeout_sec,
+ )
+
+ old_revision = self.m.checkout.get_revision(
+ path, 'get old revision', test_data='1' * 40
+ )
+
+ with self.m.context(cwd=path):
+ self.m.git('git fetch', 'fetch', 'origin', new_revision)
+ self.m.git('git checkout', 'checkout', 'FETCH_HEAD')
+
+ # In case new_revision is a branch name we need to retrieve the hash it
+ # resolved to.
+ if not re.search(r'^[0-9a-f]{40}$', new_revision):
+ new_revision = self.m.checkout.get_revision(
+ path, 'get new revision', test_data='2' * 40
+ )
+
+ return RevisionChange(old=old_revision, new=new_revision)
+
+ def update(
+ self,
+ checkout: checkout_api.CheckoutContext,
+ submodule_entries: Sequence[SubmoduleEntry],
+ ) -> dict[config_types.Path, roll_util_api.Roll]:
+ # Confirm the given path is actually a submodule.
+ gitmodules = self.m.file.read_text(
+ 'read .gitmodules', checkout.root / '.gitmodules'
+ )
+ # Example .gitmodules file:
+ # [submodule "third_party/pigweed"]
+ # path = third_party/pigweed
+ # url = https://pigweed.googlesource.com/pigweed/pigweed
+
+ # configparser doesn't like leading whitespace on lines, despite what its
+ # documentation says.
+ gitmodules = re.sub(r'\n\s+', '\n', gitmodules)
+ parser = configparser.RawConfigParser()
+ parser.readfp(io.StringIO(gitmodules))
+
+ rolls: dict[config_types.Path, self.m.roll_util.Roll] = {}
+
+ for entry in submodule_entries:
+ submodule = Submodule(
+ path=entry.path,
+ name=entry.name or entry.path,
+ branch=entry.branch,
+ )
+ submodule.dir = checkout.root / submodule.path
+
+ with self.m.step.nest(submodule.name) as pres:
+ section = f'submodule "{submodule.name}"'
+ if not parser.has_section(section):
+ sections = parser.sections()
+ submodules = sorted(
+ re.sub(r'^.*"(.*)"$', r'\1', x) for x in sections
+ )
+ raise self.m.step.StepFailure(
+ 'no submodule "{}" (submodules: {})'.format(
+ submodule.name,
+ ', '.join('"{}"'.format(x) for x in submodules),
+ )
+ )
+
+ if not submodule.branch:
+ try:
+ submodule.branch = parser.get(section, 'branch')
+ except configparser.NoOptionError:
+ submodule.branch = 'main'
+
+ submodule.remote = self.m.roll_util.normalize_remote(
+ parser.get(section, 'url'),
+ checkout.options.remote,
+ )
+
+ change = self.update_pin(
+ checkout,
+ submodule.dir,
+ submodule.branch,
+ )
+
+ direction = self.m.roll_util.get_roll_direction(
+ submodule.dir, change.old, change.new
+ )
+
+ # If the primary roll is not necessary or is backwards we can
+ # exit immediately and don't need to check deps.
+ if self.m.roll_util.can_roll(direction):
+ rolls[submodule.path] = self.m.roll_util.create_roll(
+ project_name=str(submodule.path),
+ old_revision=change.old,
+ new_revision=change.new,
+ proj_dir=submodule.dir,
+ direction=direction,
+ nest_steps=False,
+ )
+
+ else:
+ pres.step_summary_text = 'no roll required'
+ self.m.roll_util.skip_roll_step(
+ submodule.remote, change.old, change.new
+ )
+
+ return rolls
diff --git a/recipe_modules/submodule_roll/submodule.proto b/recipe_modules/submodule_roll/submodule.proto
new file mode 100644
index 0000000..8a3b523
--- /dev/null
+++ b/recipe_modules/submodule_roll/submodule.proto
@@ -0,0 +1,29 @@
+// Copyright 2024 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+syntax = "proto3";
+
+package recipe_modules.pigweed.submodule_roll;
+
+message SubmoduleEntry {
+ // The path of the submodule to update. Required.
+ string path = 1;
+
+ // The name of the submodule to update. Defaults to the value of path. Only
+ // necessary if the name and path in the .gitmodules file are different.
+ string name = 2;
+
+ // Branch to track. By default retrieved from .gitmodules or "main".
+ string branch = 3;
+}
diff --git a/recipe_modules/submodule_roll/tests/full.expected/missing.json b/recipe_modules/submodule_roll/tests/full.expected/missing.json
new file mode 100644
index 0000000..0d4a2ae
--- /dev/null
+++ b/recipe_modules/submodule_roll/tests/full.expected/missing.json
@@ -0,0 +1,171 @@
+[
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "[START_DIR]/checkout/.gitmodules",
+ "/path/to/tmp/"
+ ],
+ "infra_step": true,
+ "name": "read .gitmodules",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@.gitmodules@[submodule \"a1\"]@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\tpath = a1@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\turl = sso://foo/a1@@@",
+ "@@@STEP_LOG_END@.gitmodules@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1",
+ "~followup_annotations": [
+ "@@@STEP_SUMMARY_TEXT@no roll required@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "update",
+ "--init",
+ "--jobs",
+ "4",
+ "[START_DIR]/checkout/a1"
+ ],
+ "cwd": "[START_DIR]/checkout",
+ "name": "a1.git submodule update",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get old revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@1111111111111111111111111111111111111111@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "main"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git fetch",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git checkout",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get new revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "1111111111111111111111111111111111111111",
+ "2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get roll direction.is forward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "2222222222222222222222222222222222222222",
+ "1111111111111111111111111111111111111111"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get roll direction.is backward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.get roll direction.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_SUMMARY_TEXT@up-to-date@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.cancelling roll",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@not updating from 1111111 to 2222222 because 1111111 is newer than 2222222@@@",
+ "@@@STEP_LINK@1111111111111111111111111111111111111111@https://foo.googlesource.com/a1/+/1111111111111111111111111111111111111111@@@",
+ "@@@STEP_LINK@2222222222222222222222222222222222222222@https://foo.googlesource.com/a1/+/2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2",
+ "~followup_annotations": [
+ "@@@STEP_FAILURE@@@"
+ ]
+ },
+ {
+ "failure": {
+ "failure": {},
+ "humanReason": "no submodule \"b2\" (submodules: \"a1\")"
+ },
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipe_modules/submodule_roll/tests/full.expected/noop.json b/recipe_modules/submodule_roll/tests/full.expected/noop.json
new file mode 100644
index 0000000..50ac01d
--- /dev/null
+++ b/recipe_modules/submodule_roll/tests/full.expected/noop.json
@@ -0,0 +1,303 @@
+[
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "[START_DIR]/checkout/.gitmodules",
+ "/path/to/tmp/"
+ ],
+ "infra_step": true,
+ "name": "read .gitmodules",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@.gitmodules@[submodule \"a1\"]@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\tpath = a1@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\turl = https://foo.googlesource.com/a1@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@[submodule \"b2\"]@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\tpath = b2@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\turl = https://foo.googlesource.com/b2@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\tbranch = branch@@@",
+ "@@@STEP_LOG_END@.gitmodules@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1",
+ "~followup_annotations": [
+ "@@@STEP_SUMMARY_TEXT@no roll required@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "update",
+ "--init",
+ "--jobs",
+ "4",
+ "[START_DIR]/checkout/a1"
+ ],
+ "cwd": "[START_DIR]/checkout",
+ "name": "a1.git submodule update",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get old revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@1111111111111111111111111111111111111111@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "main"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git fetch",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git checkout",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get new revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "1111111111111111111111111111111111111111",
+ "2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get roll direction.is forward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "2222222222222222222222222222222222222222",
+ "1111111111111111111111111111111111111111"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get roll direction.is backward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.get roll direction.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_SUMMARY_TEXT@up-to-date@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.cancelling roll",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@not updating from 1111111 to 2222222 because 1111111 is newer than 2222222@@@",
+ "@@@STEP_LINK@1111111111111111111111111111111111111111@https://foo.googlesource.com/a1/+/1111111111111111111111111111111111111111@@@",
+ "@@@STEP_LINK@2222222222222222222222222222222222222222@https://foo.googlesource.com/a1/+/2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2",
+ "~followup_annotations": [
+ "@@@STEP_SUMMARY_TEXT@no roll required@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "update",
+ "--init",
+ "--jobs",
+ "4",
+ "[START_DIR]/checkout/b2"
+ ],
+ "cwd": "[START_DIR]/checkout",
+ "name": "b2.git submodule update",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get old revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@1111111111111111111111111111111111111111@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "branch"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.git fetch",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.git checkout",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get new revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "1111111111111111111111111111111111111111",
+ "2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get roll direction.is forward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "2222222222222222222222222222222222222222",
+ "1111111111111111111111111111111111111111"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get roll direction.is backward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2.get roll direction.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_SUMMARY_TEXT@up-to-date@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2.cancelling roll",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@not updating from 1111111 to 2222222 because 1111111 is newer than 2222222@@@",
+ "@@@STEP_LINK@1111111111111111111111111111111111111111@https://foo.googlesource.com/b2/+/1111111111111111111111111111111111111111@@@",
+ "@@@STEP_LINK@2222222222222222222222222222222222222222@https://foo.googlesource.com/b2/+/2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "nothing to roll, exiting"
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipe_modules/submodule_roll/tests/full.expected/partial_noop.json b/recipe_modules/submodule_roll/tests/full.expected/partial_noop.json
new file mode 100644
index 0000000..2c6309c
--- /dev/null
+++ b/recipe_modules/submodule_roll/tests/full.expected/partial_noop.json
@@ -0,0 +1,495 @@
+[
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "[START_DIR]/checkout/.gitmodules",
+ "/path/to/tmp/"
+ ],
+ "infra_step": true,
+ "name": "read .gitmodules",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@.gitmodules@[submodule \"a1\"]@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\tpath = a1@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\turl = sso://foo/a1@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@[submodule \"b2\"]@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\tpath = b2@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\turl = sso://foo/b2@@@",
+ "@@@STEP_LOG_END@.gitmodules@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1"
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "update",
+ "--init",
+ "--jobs",
+ "4",
+ "[START_DIR]/checkout/a1"
+ ],
+ "cwd": "[START_DIR]/checkout",
+ "name": "a1.git submodule update",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get old revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@1111111111111111111111111111111111111111@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "main"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git fetch",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git checkout",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get new revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@forward@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "1111111111111111111111111111111111111111",
+ "2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get roll direction.is forward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "2222222222222222222222222222222222222222",
+ "1111111111111111111111111111111111111111"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get roll direction.is backward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.remote",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "remote"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.remote.name",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "remote",
+ "get-url",
+ "origin"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.remote.url",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--pretty=format:%H\n%an\n%ae\n%B",
+ "-z",
+ "1111111111111111111111111111111111111111..2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git log",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.get packages",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "RECIPE_MODULE[fuchsia::gerrit]/resources/cipd.ensure",
+ "/path/to/tmp/"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.get packages.read ensure file",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@3@@@",
+ "@@@STEP_LOG_LINE@cipd.ensure@infra/tools/luci/gerrit/${platform} version:pinned-version@@@",
+ "@@@STEP_LOG_END@cipd.ensure@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.install infra/tools/luci/gerrit",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "ensure-directory",
+ "--mode",
+ "0o777",
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.install infra/tools/luci/gerrit.ensure package directory",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@3@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "ensure",
+ "-root",
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07",
+ "-ensure-file",
+ "infra/tools/luci/gerrit/${platform} version:pinned-version",
+ "-max-threads",
+ "0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.install infra/tools/luci/gerrit.ensure_installed",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@3@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"resolved-instance_id-of-version:pinned-v\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"infra/tools/luci/gerrit/resolved-platform\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07/gerrit",
+ "change-query",
+ "-host",
+ "https://pigweed-review.googlesource.com",
+ "-input",
+ "{\"params\": {\"q\": \"commit:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}}",
+ "-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.get change-id",
+ "timeout": 600,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@[@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"_number\": 12345@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@]@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LOG_LINE@json.input@{@@@",
+ "@@@STEP_LOG_LINE@json.input@ \"params\": {@@@",
+ "@@@STEP_LOG_LINE@json.input@ \"q\": \"commit:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"@@@",
+ "@@@STEP_LOG_LINE@json.input@ }@@@",
+ "@@@STEP_LOG_LINE@json.input@}@@@",
+ "@@@STEP_LOG_END@json.input@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07/gerrit",
+ "change-detail",
+ "-host",
+ "https://pigweed-review.googlesource.com",
+ "-input",
+ "{\"change_id\": \"12345\"}",
+ "-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.get 12345",
+ "timeout": 600,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"owner\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"author@example.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"author\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ },@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"reviewers\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"REVIEWER\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"reviewer@example.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"reviewer\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ },@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"nobody@google.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"nobody\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ },@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"robot@gserviceaccount.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"robot\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LOG_LINE@json.input@{@@@",
+ "@@@STEP_LOG_LINE@json.input@ \"change_id\": \"12345\"@@@",
+ "@@@STEP_LOG_LINE@json.input@}@@@",
+ "@@@STEP_LOG_END@json.input@@@",
+ "@@@STEP_LINK@gerrit link@https://pigweed-review.googlesource.com/q/12345@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2",
+ "~followup_annotations": [
+ "@@@STEP_SUMMARY_TEXT@no roll required@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "update",
+ "--init",
+ "--jobs",
+ "4",
+ "[START_DIR]/checkout/b2"
+ ],
+ "cwd": "[START_DIR]/checkout",
+ "name": "b2.git submodule update",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get old revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@1111111111111111111111111111111111111111@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "main"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.git fetch",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.git checkout",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get new revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "1111111111111111111111111111111111111111",
+ "2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get roll direction.is forward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "2222222222222222222222222222222222222222",
+ "1111111111111111111111111111111111111111"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get roll direction.is backward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2.get roll direction.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@",
+ "@@@STEP_SUMMARY_TEXT@up-to-date@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2.cancelling roll",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@not updating from 1111111 to 2222222 because 1111111 is newer than 2222222@@@",
+ "@@@STEP_LINK@1111111111111111111111111111111111111111@https://foo.googlesource.com/b2/+/1111111111111111111111111111111111111111@@@",
+ "@@@STEP_LINK@2222222222222222222222222222222222222222@https://foo.googlesource.com/b2/+/2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipe_modules/submodule_roll/tests/full.expected/success.json b/recipe_modules/submodule_roll/tests/full.expected/success.json
new file mode 100644
index 0000000..9173e46
--- /dev/null
+++ b/recipe_modules/submodule_roll/tests/full.expected/success.json
@@ -0,0 +1,601 @@
+[
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "[START_DIR]/checkout/.gitmodules",
+ "/path/to/tmp/"
+ ],
+ "infra_step": true,
+ "name": "read .gitmodules",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@.gitmodules@[submodule \"a1\"]@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\tpath = a1@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\turl = sso://foo/a1@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@[submodule \"b2\"]@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\tpath = b2@@@",
+ "@@@STEP_LOG_LINE@.gitmodules@\turl = sso://foo/b2@@@",
+ "@@@STEP_LOG_END@.gitmodules@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1"
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "update",
+ "--init",
+ "--jobs",
+ "4",
+ "[START_DIR]/checkout/a1"
+ ],
+ "cwd": "[START_DIR]/checkout",
+ "name": "a1.git submodule update",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get old revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@1111111111111111111111111111111111111111@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "main"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git fetch",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git checkout",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get new revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@forward@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "1111111111111111111111111111111111111111",
+ "2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get roll direction.is forward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "2222222222222222222222222222222222222222",
+ "1111111111111111111111111111111111111111"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.get roll direction.is backward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.remote",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "remote"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.remote.name",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "remote",
+ "get-url",
+ "origin"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.remote.url",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--pretty=format:%H\n%an\n%ae\n%B",
+ "-z",
+ "1111111111111111111111111111111111111111..2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "name": "a1.git log",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.get packages",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "copy",
+ "RECIPE_MODULE[fuchsia::gerrit]/resources/cipd.ensure",
+ "/path/to/tmp/"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.get packages.read ensure file",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@3@@@",
+ "@@@STEP_LOG_LINE@cipd.ensure@infra/tools/luci/gerrit/${platform} version:pinned-version@@@",
+ "@@@STEP_LOG_END@cipd.ensure@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.install infra/tools/luci/gerrit",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "vpython3",
+ "-u",
+ "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+ "--json-output",
+ "/path/to/tmp/json",
+ "ensure-directory",
+ "--mode",
+ "0o777",
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.install infra/tools/luci/gerrit.ensure package directory",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@3@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "cipd",
+ "ensure",
+ "-root",
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07",
+ "-ensure-file",
+ "infra/tools/luci/gerrit/${platform} version:pinned-version",
+ "-max-threads",
+ "0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.ensure infra/tools/luci/gerrit/${platform}.install infra/tools/luci/gerrit.ensure_installed",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@3@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"resolved-instance_id-of-version:pinned-v\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"infra/tools/luci/gerrit/resolved-platform\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07/gerrit",
+ "change-query",
+ "-host",
+ "https://pigweed-review.googlesource.com",
+ "-input",
+ "{\"params\": {\"q\": \"commit:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}}",
+ "-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.get change-id",
+ "timeout": 600,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@[@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"_number\": 12345@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@]@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LOG_LINE@json.input@{@@@",
+ "@@@STEP_LOG_LINE@json.input@ \"params\": {@@@",
+ "@@@STEP_LOG_LINE@json.input@ \"q\": \"commit:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"@@@",
+ "@@@STEP_LOG_LINE@json.input@ }@@@",
+ "@@@STEP_LOG_LINE@json.input@}@@@",
+ "@@@STEP_LOG_END@json.input@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07/gerrit",
+ "change-detail",
+ "-host",
+ "https://pigweed-review.googlesource.com",
+ "-input",
+ "{\"change_id\": \"12345\"}",
+ "-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[START_DIR]/checkout/a1",
+ "infra_step": true,
+ "name": "a1.get 12345",
+ "timeout": 600,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"owner\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"author@example.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"author\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ },@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"reviewers\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"REVIEWER\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"reviewer@example.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"reviewer\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ },@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"nobody@google.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"nobody\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ },@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"robot@gserviceaccount.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"robot\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LOG_LINE@json.input@{@@@",
+ "@@@STEP_LOG_LINE@json.input@ \"change_id\": \"12345\"@@@",
+ "@@@STEP_LOG_LINE@json.input@}@@@",
+ "@@@STEP_LOG_END@json.input@@@",
+ "@@@STEP_LINK@gerrit link@https://pigweed-review.googlesource.com/q/12345@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2"
+ },
+ {
+ "cmd": [
+ "git",
+ "submodule",
+ "update",
+ "--init",
+ "--jobs",
+ "4",
+ "[START_DIR]/checkout/b2"
+ ],
+ "cwd": "[START_DIR]/checkout",
+ "name": "b2.git submodule update",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get old revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@1111111111111111111111111111111111111111@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "fetch",
+ "origin",
+ "main"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.git fetch",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "checkout",
+ "FETCH_HEAD"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.git checkout",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--max-count=1",
+ "--pretty=format:%H"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get new revision",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@2222222222222222222222222222222222222222@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2.get roll direction",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_SUMMARY_TEXT@forward@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "1111111111111111111111111111111111111111",
+ "2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get roll direction.is forward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "merge-base",
+ "--is-ancestor",
+ "2222222222222222222222222222222222222222",
+ "1111111111111111111111111111111111111111"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.get roll direction.is backward",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [],
+ "name": "b2.remote",
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "remote"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.remote.name",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "remote",
+ "get-url",
+ "origin"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.remote.url",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@2@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "git",
+ "log",
+ "--pretty=format:%H\n%an\n%ae\n%B",
+ "-z",
+ "1111111111111111111111111111111111111111..2222222222222222222222222222222222222222"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "name": "b2.git log",
+ "timeout": 600.0,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07/gerrit",
+ "change-query",
+ "-host",
+ "https://pigweed-review.googlesource.com",
+ "-input",
+ "{\"params\": {\"q\": \"commit:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}}",
+ "-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "infra_step": true,
+ "name": "b2.get change-id",
+ "timeout": 600,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@[@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"_number\": 12345@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@]@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LOG_LINE@json.input@{@@@",
+ "@@@STEP_LOG_LINE@json.input@ \"params\": {@@@",
+ "@@@STEP_LOG_LINE@json.input@ \"q\": \"commit:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"@@@",
+ "@@@STEP_LOG_LINE@json.input@ }@@@",
+ "@@@STEP_LOG_LINE@json.input@}@@@",
+ "@@@STEP_LOG_END@json.input@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "[START_DIR]/cipd_tool/infra/tools/luci/gerrit/0e548aa33f8113a45a5b3b62201e114e98e63d00f97296912380138f44597b07/gerrit",
+ "change-detail",
+ "-host",
+ "https://pigweed-review.googlesource.com",
+ "-input",
+ "{\"change_id\": \"12345\"}",
+ "-output",
+ "/path/to/tmp/json"
+ ],
+ "cwd": "[START_DIR]/checkout/b2",
+ "infra_step": true,
+ "name": "b2.get 12345",
+ "timeout": 600,
+ "~followup_annotations": [
+ "@@@STEP_NEST_LEVEL@1@@@",
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"owner\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"author@example.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"author\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ },@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"reviewers\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"REVIEWER\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"reviewer@example.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"reviewer\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ },@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"nobody@google.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"nobody\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ },@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"email\": \"robot@gserviceaccount.com\",@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"name\": \"robot\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@",
+ "@@@STEP_LOG_LINE@json.input@{@@@",
+ "@@@STEP_LOG_LINE@json.input@ \"change_id\": \"12345\"@@@",
+ "@@@STEP_LOG_LINE@json.input@}@@@",
+ "@@@STEP_LOG_END@json.input@@@",
+ "@@@STEP_LINK@gerrit link@https://pigweed-review.googlesource.com/q/12345@@@"
+ ]
+ },
+ {
+ "name": "$result"
+ }
+]
\ No newline at end of file
diff --git a/recipe_modules/submodule_roll/tests/full.proto b/recipe_modules/submodule_roll/tests/full.proto
new file mode 100644
index 0000000..2c4361a
--- /dev/null
+++ b/recipe_modules/submodule_roll/tests/full.proto
@@ -0,0 +1,26 @@
+// Copyright 2021 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+syntax = "proto3";
+
+package recipe_modules.pigweed.submodule_roll.tests;
+
+import "recipe_modules/pigweed/checkout/options.proto";
+import "recipe_modules/pigweed/submodule_roll/submodule.proto";
+import "recipe_modules/fuchsia/auto_roller/options.proto";
+
+message InputProperties {
+ // Submodules to update.
+ repeated recipe_modules.pigweed.submodule_roll.SubmoduleEntry submodules = 1;
+}
diff --git a/recipe_modules/submodule_roll/tests/full.py b/recipe_modules/submodule_roll/tests/full.py
new file mode 100644
index 0000000..fee8c53
--- /dev/null
+++ b/recipe_modules/submodule_roll/tests/full.py
@@ -0,0 +1,131 @@
+# Copyright 2024 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from __future__ import annotations
+
+from PB.recipe_modules.pigweed.submodule_roll.tests.full import InputProperties
+from PB.recipe_modules.pigweed.submodule_roll.submodule import SubmoduleEntry
+
+DEPS = [
+ "pigweed/checkout",
+ "pigweed/roll_util",
+ "pigweed/submodule_roll",
+ "recipe_engine/file",
+ "recipe_engine/properties",
+ "recipe_engine/step",
+]
+
+PROPERTIES = InputProperties
+
+
+def RunSteps( # pylint: disable=invalid-name
+ api: recipe_api.RecipeScriptApi,
+ props: InputProperties,
+):
+ checkout = api.checkout.fake_context()
+
+ rolls = api.submodule_roll.update(checkout, props.submodules)
+
+ if not rolls:
+ with api.step.nest('nothing to roll, exiting'):
+ return
+
+
+def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]:
+ """Create tests."""
+
+ def _url(x):
+ if x.startswith(('https://', 'sso://', '.')):
+ return x
+ return 'https://foo.googlesource.com/' + x
+
+ def submodules(*subs):
+ res = []
+ for sub in subs:
+ if isinstance(sub, str):
+ res.append(SubmoduleEntry(path=sub))
+ elif isinstance(sub, dict):
+ res.append(SubmoduleEntry(**sub))
+ else:
+ raise ValueError(repr(sub)) # pragma: no cover
+ return res
+
+ def properties(submodules, **kwargs):
+ props = InputProperties(**kwargs)
+ props.submodules.extend(submodules)
+ return api.properties(props)
+
+ def gitmodules(**submodules):
+ branches = {}
+ for k, v in submodules.items():
+ if k.endswith('_branch'):
+ branches[k.replace('_branch', '')] = v
+
+ for x in branches:
+ del submodules[f'{x}_branch']
+
+ text = []
+ for k, v in submodules.items():
+ text.append(
+ '[submodule "{0}"]\n\tpath = {0}\n\turl = {1}\n'.format(
+ k, _url(v)
+ )
+ )
+ if k in branches:
+ text.append(f'\tbranch = {branches[k]}\n')
+
+ return api.step_data(
+ 'read .gitmodules', api.file.read_text(''.join(text))
+ )
+
+ def commit_data(name, **kwargs):
+ return api.roll_util.commit_data(
+ name,
+ api.roll_util.commit('a' * 40, 'foo\nbar\n\nChange-Id: I1111'),
+ **kwargs,
+ )
+
+ yield api.test(
+ 'success',
+ properties(submodules('a1', 'b2')),
+ commit_data('a1', prefix=''),
+ commit_data('b2', prefix=''),
+ gitmodules(a1='sso://foo/a1', b2='sso://foo/b2'),
+ api.roll_util.forward_roll('a1'),
+ api.roll_util.forward_roll('b2'),
+ )
+
+ yield api.test(
+ 'partial_noop',
+ properties(submodules('a1', 'b2')),
+ commit_data('a1', prefix=''),
+ gitmodules(a1='sso://foo/a1', b2='sso://foo/b2'),
+ api.roll_util.forward_roll('a1'),
+ api.roll_util.noop_roll('b2'),
+ )
+
+ yield api.test(
+ 'noop',
+ properties(submodules('a1', {'path': 'b2'})),
+ gitmodules(a1='a1', b2='b2', b2_branch='branch'),
+ api.roll_util.noop_roll('a1'),
+ api.roll_util.noop_roll('b2'),
+ )
+
+ yield api.test(
+ 'missing',
+ properties(submodules('a1', 'b2')),
+ gitmodules(a1='sso://foo/a1'),
+ status='FAILURE',
+ )
diff --git a/recipes/submodule_roller.expected/missing.json b/recipes/submodule_roller.expected/missing.json
deleted file mode 100644
index 97e76c7..0000000
--- a/recipes/submodule_roller.expected/missing.json
+++ /dev/null
@@ -1,752 +0,0 @@
-[
- {
- "cmd": [],
- "name": "checkout pigweed"
- },
- {
- "cmd": [],
- "name": "checkout pigweed.options",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@",
- "@@@STEP_SUMMARY_TEXT@remote: \"https://pigweed.googlesource.com/pigweed/pigweed\"\nbranch: \"main\"\ninitialize_submodules: true\nmatch_branch: true\n@@@"
- ]
- },
- {
- "cmd": [],
- "name": "checkout pigweed.options with defaults",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@",
- "@@@STEP_SUMMARY_TEXT@remote: \"https://pigweed.googlesource.com/pigweed/pigweed\"\nbranch: \"main\"\nmanifest_file: \"default.xml\"\ninitialize_submodules: true\nrepo_init_timeout_sec: 20\nrepo_sync_timeout_sec: 120\nnumber_of_attempts: 3\nmatch_branch: true\nsubmodule_timeout_sec: 600\n@@@"
- ]
- },
- {
- "cmd": [],
- "name": "checkout pigweed.not matching branch names",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [],
- "name": "checkout pigweed.cache",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@",
- "@@@STEP_SUMMARY_TEXT@miss@@@"
- ]
- },
- {
- "cmd": [
- "vpython3",
- "-u",
- "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
- "--json-output",
- "/path/to/tmp/json",
- "ensure-directory",
- "--mode",
- "0o777",
- "[CACHE]/git"
- ],
- "infra_step": true,
- "name": "checkout pigweed.cache.ensure git cache 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",
- "",
- "[CACHE]/git/.GUARD_FILE"
- ],
- "infra_step": true,
- "name": "checkout pigweed.cache.write git cache guard file",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "vpython3",
- "-u",
- "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
- "--json-output",
- "/path/to/tmp/json",
- "ensure-directory",
- "--mode",
- "0o777",
- "[CACHE]/git/pigweed.googlesource.com-pigweed-pigweed"
- ],
- "infra_step": true,
- "name": "checkout pigweed.cache.makedirs",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "init"
- ],
- "cwd": "[CACHE]/git/pigweed.googlesource.com-pigweed-pigweed",
- "infra_step": true,
- "name": "checkout pigweed.cache.git init",
- "timeout": 300.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "config",
- "remote.origin.url",
- "https://pigweed.googlesource.com/pigweed/pigweed"
- ],
- "cwd": "[CACHE]/git/pigweed.googlesource.com-pigweed-pigweed",
- "infra_step": true,
- "name": "checkout pigweed.cache.remote set-url",
- "timeout": 300.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "config",
- "fetch.uriprotocols",
- "https"
- ],
- "cwd": "[CACHE]/git/pigweed.googlesource.com-pigweed-pigweed",
- "infra_step": true,
- "name": "checkout pigweed.cache.set fetch.uriprotocols",
- "timeout": 300.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [],
- "name": "checkout pigweed.cache.timeout 10s",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "fetch",
- "--prune",
- "--tags",
- "--jobs",
- "4",
- "origin",
- "--recurse-submodules"
- ],
- "cwd": "[CACHE]/git/pigweed.googlesource.com-pigweed-pigweed",
- "infra_step": true,
- "name": "checkout pigweed.cache.git fetch",
- "timeout": 1200.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "merge",
- "FETCH_HEAD"
- ],
- "cwd": "[CACHE]/git/pigweed.googlesource.com-pigweed-pigweed",
- "infra_step": true,
- "name": "checkout pigweed.cache.git merge",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "submodule",
- "sync",
- "--recursive"
- ],
- "cwd": "[CACHE]/git/pigweed.googlesource.com-pigweed-pigweed",
- "infra_step": true,
- "name": "checkout pigweed.cache.git submodule sync",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [],
- "name": "checkout pigweed.cache.timeout 10s (2)",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "submodule",
- "update",
- "--init",
- "--recursive",
- "--force",
- "--jobs",
- "4"
- ],
- "cwd": "[CACHE]/git/pigweed.googlesource.com-pigweed-pigweed",
- "infra_step": true,
- "name": "checkout pigweed.cache.git submodule update",
- "timeout": 600,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "vpython3",
- "-u",
- "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
- "--json-output",
- "/path/to/tmp/json",
- "remove",
- "[CACHE]/git/.GUARD_FILE"
- ],
- "infra_step": true,
- "name": "checkout pigweed.cache.remove git cache guard file",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "vpython3",
- "-u",
- "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
- "--json-output",
- "/path/to/tmp/json",
- "copytree",
- "--symlinks",
- "[CACHE]/git/pigweed.googlesource.com-pigweed-pigweed",
- "[START_DIR]/co"
- ],
- "infra_step": true,
- "name": "checkout pigweed.copy from cache",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [],
- "name": "checkout pigweed.git checkout",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [],
- "name": "checkout pigweed.git checkout.timeout 10s",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "vpython3",
- "-u",
- "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
- "--json-output",
- "/path/to/tmp/json",
- "ensure-directory",
- "--mode",
- "0o777",
- "[START_DIR]/co"
- ],
- "infra_step": true,
- "luci_context": {
- "deadline": {
- "grace_period": 30.0,
- "soft_deadline": 1337000019.0
- }
- },
- "name": "checkout pigweed.git checkout.makedirs",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "init"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.git init",
- "timeout": 300.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "remote",
- "add",
- "origin",
- "https://pigweed.googlesource.com/pigweed/pigweed"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.git remote",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "config",
- "core.longpaths",
- "true"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.set core.longpaths",
- "timeout": 300.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "config",
- "fetch.uriprotocols",
- "https"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.set fetch.uriprotocols",
- "timeout": 300.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "fetch",
- "--tags",
- "--jobs",
- "4",
- "origin",
- "main",
- "--recurse-submodules"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.git fetch",
- "timeout": 1200.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "checkout",
- "-f",
- "FETCH_HEAD"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.git checkout",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "rev-parse",
- "HEAD"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.git rev-parse",
- "timeout": 300.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "clean",
- "-f",
- "-d",
- "-x"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.git clean",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [],
- "name": "checkout pigweed.git checkout.submodule",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "submodule",
- "sync"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.submodule.git submodule sync",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@3@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "submodule",
- "update",
- "--init",
- "--recursive",
- "--force",
- "--jobs",
- "4"
- ],
- "cwd": "[START_DIR]/co",
- "infra_step": true,
- "name": "checkout pigweed.git checkout.submodule.git submodule update",
- "timeout": 600,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@3@@@"
- ]
- },
- {
- "cmd": [],
- "name": "checkout pigweed.git log",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "log",
- "--oneline",
- "-n",
- "10"
- ],
- "cwd": "[START_DIR]/co",
- "name": "checkout pigweed.git log.[START_DIR]/co",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "clean",
- "-f",
- "-f",
- "-d"
- ],
- "cwd": "[START_DIR]/co",
- "name": "checkout pigweed.git clean",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "status"
- ],
- "cwd": "[START_DIR]/co",
- "name": "checkout pigweed.git status",
- "timeout": 600.0,
- "~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",
- "0o777",
- "[START_DIR]/snapshot"
- ],
- "infra_step": true,
- "name": "checkout pigweed.mkdir",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "submodule",
- "status",
- "--recursive"
- ],
- "cwd": "[START_DIR]/co",
- "name": "checkout pigweed.submodule-status",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "vpython3",
- "-u",
- "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
- "--json-output",
- "/path/to/tmp/json",
- "copy",
- "submodule status filler text",
- "[START_DIR]/snapshot/submodules.log"
- ],
- "infra_step": true,
- "name": "checkout pigweed.write submodule snapshot",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@",
- "@@@STEP_LOG_LINE@submodules.log@submodule status filler text@@@",
- "@@@STEP_LOG_END@submodules.log@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "log",
- "--oneline",
- "-n",
- "10"
- ],
- "cwd": "[START_DIR]/co",
- "name": "checkout pigweed.log",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "vpython3",
- "-u",
- "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
- "--json-output",
- "/path/to/tmp/json",
- "copy",
- "",
- "[START_DIR]/snapshot/git.log"
- ],
- "infra_step": true,
- "name": "checkout pigweed.write git log",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@",
- "@@@STEP_LOG_END@git.log@@@"
- ]
- },
- {
- "cmd": [
- "vpython3",
- "-u",
- "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
- "--json-output",
- "/path/to/tmp/json",
- "copy",
- "[START_DIR]/co/.gitmodules",
- "/path/to/tmp/"
- ],
- "infra_step": true,
- "name": "read .gitmodules",
- "~followup_annotations": [
- "@@@STEP_LOG_LINE@.gitmodules@[submodule \"a1\"]@@@",
- "@@@STEP_LOG_LINE@.gitmodules@\tpath = a1@@@",
- "@@@STEP_LOG_LINE@.gitmodules@\turl = sso://foo/a1@@@",
- "@@@STEP_LOG_END@.gitmodules@@@"
- ]
- },
- {
- "cmd": [],
- "name": "a1",
- "~followup_annotations": [
- "@@@STEP_SUMMARY_TEXT@no roll required@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "submodule",
- "update",
- "--init",
- "--jobs",
- "4",
- "[START_DIR]/co/a1"
- ],
- "cwd": "[START_DIR]/co",
- "name": "a1.git submodule update",
- "timeout": 600,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "log",
- "--max-count=1",
- "--pretty=format:%H"
- ],
- "cwd": "[START_DIR]/co/a1",
- "name": "a1.get old revision",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@",
- "@@@STEP_SUMMARY_TEXT@1111111111111111111111111111111111111111@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "fetch",
- "origin",
- "main"
- ],
- "cwd": "[START_DIR]/co/a1",
- "name": "a1.git fetch",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "checkout",
- "FETCH_HEAD"
- ],
- "cwd": "[START_DIR]/co/a1",
- "name": "a1.git checkout",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "log",
- "--max-count=1",
- "--pretty=format:%H"
- ],
- "cwd": "[START_DIR]/co/a1",
- "name": "a1.get new revision",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@",
- "@@@STEP_SUMMARY_TEXT@2222222222222222222222222222222222222222@@@"
- ]
- },
- {
- "cmd": [],
- "name": "a1.get roll direction",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "merge-base",
- "--is-ancestor",
- "1111111111111111111111111111111111111111",
- "2222222222222222222222222222222222222222"
- ],
- "cwd": "[START_DIR]/co/a1",
- "name": "a1.get roll direction.is forward",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [
- "git",
- "merge-base",
- "--is-ancestor",
- "2222222222222222222222222222222222222222",
- "1111111111111111111111111111111111111111"
- ],
- "cwd": "[START_DIR]/co/a1",
- "name": "a1.get roll direction.is backward",
- "timeout": 600.0,
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@"
- ]
- },
- {
- "cmd": [],
- "name": "a1.get roll direction.get roll direction",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@2@@@",
- "@@@STEP_SUMMARY_TEXT@up-to-date@@@"
- ]
- },
- {
- "cmd": [],
- "name": "a1.cancelling roll",
- "~followup_annotations": [
- "@@@STEP_NEST_LEVEL@1@@@",
- "@@@STEP_SUMMARY_TEXT@not updating from 1111111 to 2222222 because 1111111 is newer than 2222222@@@",
- "@@@STEP_LINK@1111111111111111111111111111111111111111@https://foo.googlesource.com/a1/+/1111111111111111111111111111111111111111@@@",
- "@@@STEP_LINK@2222222222222222222222222222222222222222@https://foo.googlesource.com/a1/+/2222222222222222222222222222222222222222@@@"
- ]
- },
- {
- "cmd": [],
- "name": "b2",
- "~followup_annotations": [
- "@@@STEP_FAILURE@@@"
- ]
- },
- {
- "failure": {
- "failure": {},
- "humanReason": "no submodule \"b2\" (submodules: \"a1\")"
- },
- "name": "$result"
- }
-]
\ No newline at end of file
diff --git a/recipes/submodule_roller.proto b/recipes/submodule_roller.proto
index 58820e8..87095fd 100644
--- a/recipes/submodule_roller.proto
+++ b/recipes/submodule_roller.proto
@@ -17,23 +17,12 @@
package recipes.pigweed.submodule_roller;
import "recipe_modules/pigweed/checkout/options.proto";
+import "recipe_modules/pigweed/submodule_roll/submodule.proto";
import "recipe_modules/fuchsia/auto_roller/options.proto";
-message SubmoduleEntry {
- // The path of the submodule to update. Required.
- string path = 1;
-
- // The name of the submodule to update. Defaults to the value of path. Only
- // necessary if the name and path in the .gitmodules file are different.
- string name = 2;
-
- // Branch to track. By default retrieved from .gitmodules or "main".
- string branch = 3;
-}
-
message InputProperties {
// Submodules to update.
- repeated SubmoduleEntry submodules = 1;
+ repeated recipe_modules.pigweed.submodule_roll.SubmoduleEntry submodules = 1;
reserved 2;
diff --git a/recipes/submodule_roller.py b/recipes/submodule_roller.py
index 0cf0492..d642445 100644
--- a/recipes/submodule_roller.py
+++ b/recipes/submodule_roller.py
@@ -15,27 +15,22 @@
from __future__ import annotations
-import configparser
-import dataclasses
-import io
-import re
from typing import TYPE_CHECKING
import attrs
-from PB.recipes.pigweed.submodule_roller import InputProperties, SubmoduleEntry
+from PB.recipes.pigweed.submodule_roller import InputProperties
+from PB.recipe_modules.pigweed.submodule_roll.submodule import SubmoduleEntry
from recipe_engine import post_process
if TYPE_CHECKING: # pragma: no cover
from typing import Generator
- from recipe_engine import config_types, recipe_test_api
- from RECIPE_MODULES.pigweed.checkout import api as checkout_api
+ from recipe_engine import recipe_test_api
DEPS = [
'fuchsia/auto_roller',
- 'fuchsia/git',
'pigweed/checkout',
'pigweed/roll_util',
- 'recipe_engine/context',
+ 'pigweed/submodule_roll',
'recipe_engine/file',
'recipe_engine/properties',
'recipe_engine/step',
@@ -44,128 +39,6 @@
PROPERTIES = InputProperties
-@dataclasses.dataclass
-class Submodule:
- path: str
- name: str
- branch: str
- remote: str = dataclasses.field(default=None)
- dir: config_types.Path = dataclasses.field(default=None)
-
-
-@dataclasses.dataclass
-class RevisionChange:
- old: str
- new: str
-
-
-def _update_pin(api, checkout, path, new_revision):
- with api.context(cwd=checkout.top):
- api.git.submodule_update(
- paths=(path,),
- timeout=checkout.options.submodule_timeout_sec,
- )
-
- old_revision = api.checkout.get_revision(
- path, 'get old revision', test_data='1' * 40
- )
-
- with api.context(cwd=path):
- api.git('git fetch', 'fetch', 'origin', new_revision)
- api.git('git checkout', 'checkout', 'FETCH_HEAD')
-
- # In case new_revision is a branch name we need to retrieve the hash it
- # resolved to.
- if not re.search(r'^[0-9a-f]{40}$', new_revision):
- new_revision = api.checkout.get_revision(
- path, 'get new revision', test_data='2' * 40
- )
-
- return RevisionChange(old=old_revision, new=new_revision)
-
-
-def _update_submodules(
- api: recipe_api.RecipeScriptApi,
- checkout: checkout_api.CheckoutContext,
- submodule_entries: Sequence[Submodule],
-) -> dict[config_types.Path, api.roll_util.Roll]:
- # Confirm the given path is actually a submodule.
- gitmodules = api.file.read_text(
- 'read .gitmodules', checkout.root / '.gitmodules'
- )
- # Example .gitmodules file:
- # [submodule "third_party/pigweed"]
- # path = third_party/pigweed
- # url = https://pigweed.googlesource.com/pigweed/pigweed
-
- # configparser doesn't like leading whitespace on lines, despite what its
- # documentation says.
- gitmodules = re.sub(r'\n\s+', '\n', gitmodules)
- parser = configparser.RawConfigParser()
- parser.readfp(io.StringIO(gitmodules))
-
- rolls: dict[config_types.Path, api.roll_util.Roll] = {}
-
- for entry in submodule_entries:
- submodule = Submodule(
- path=entry.path,
- name=entry.name or entry.path,
- branch=entry.branch,
- )
- submodule.dir = checkout.root / submodule.path
-
- with api.step.nest(submodule.name) as pres:
- section = f'submodule "{submodule.name}"'
- if not parser.has_section(section):
- sections = parser.sections()
- submodules = sorted(
- re.sub(r'^.*"(.*)"$', r'\1', x) for x in sections
- )
- raise api.step.StepFailure(
- 'no submodule "{}" (submodules: {})'.format(
- submodule.name,
- ', '.join('"{}"'.format(x) for x in submodules),
- )
- )
-
- if not submodule.branch:
- try:
- submodule.branch = parser.get(section, 'branch')
- except configparser.NoOptionError:
- submodule.branch = 'main'
-
- submodule.remote = api.roll_util.normalize_remote(
- parser.get(section, 'url'),
- checkout.options.remote,
- )
-
- change = _update_pin(api, checkout, submodule.dir, submodule.branch)
-
- direction = api.roll_util.get_roll_direction(
- submodule.dir, change.old, change.new
- )
-
- # If the primary roll is not necessary or is backwards we can exit
- # immediately and don't need to check deps.
- if api.roll_util.can_roll(direction):
- rolls[submodule.path] = api.roll_util.create_roll(
- project_name=str(submodule.path),
- old_revision=change.old,
- new_revision=change.new,
- proj_dir=submodule.dir,
- direction=direction,
- nest_steps=False,
- )
-
- else:
- pres.step_summary_text = 'no roll required'
- api.roll_util.skip_roll_step(
- submodule.remote, change.old, change.new
- )
-
- return rolls
-
-
def RunSteps( # pylint: disable=invalid-name
api: recipe_api.RecipeScriptApi,
props: InputProperties,
@@ -181,7 +54,7 @@
props.checkout_options.use_trigger = False
checkout = api.checkout(props.checkout_options)
- rolls = _update_submodules(api, checkout, props.submodules)
+ rolls = api.submodule_roll.update(checkout, props.submodules)
if not rolls:
with api.step.nest('nothing to roll, exiting'):
@@ -325,10 +198,3 @@
api.roll_util.noop_roll('a1'),
api.roll_util.noop_roll('b2'),
)
-
- yield api.test(
- 'missing',
- properties(submodules('a1', 'b2'), cc_authors_on_rolls=True),
- gitmodules(a1='sso://foo/a1'),
- status='FAILURE',
- )